├── .github ├── workflows │ ├── LICENSE.md │ ├── update.yml │ ├── archive.yml │ ├── publish.yml │ └── ghpages.yml └── CODEOWNERS ├── LICENSE.md ├── .editorconfig ├── Makefile ├── .gitignore ├── README.md ├── CONTRIBUTING.md ├── draft-parecki-oauth-metadata-for-nested-flows.md └── nested-oauth-flow.svg /.github/workflows/LICENSE.md: -------------------------------------------------------------------------------- 1 | This project is in the public domain. 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | See the 4 | [guidelines for contributions](https://github.com/aaronpk/oauth-metadata-for-nested-flows/blob/main/CONTRIBUTING.md). 5 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Automatically generated CODEOWNERS 2 | # Regenerate with `make update-codeowners` 3 | draft-parecki-oauth-metadata-for-nested-flows.md aaron@parecki.com 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # See http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*.{md,xml,org}] 6 | charset = utf-8 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LIBDIR := lib 2 | include $(LIBDIR)/main.mk 3 | 4 | $(LIBDIR)/main.mk: 5 | ifneq (,$(shell grep "path *= *$(LIBDIR)" .gitmodules 2>/dev/null)) 6 | git submodule sync 7 | git submodule update $(CLONE_ARGS) --init 8 | else 9 | git clone -q --depth 10 $(CLONE_ARGS) \ 10 | -b main https://github.com/martinthomson/i-d-template $(LIBDIR) 11 | endif 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.pdf 3 | *.redxml 4 | *.swp 5 | *.txt 6 | *.upload 7 | *~ 8 | .tags 9 | /*-[0-9][0-9].xml 10 | /.gems/ 11 | /.refcache 12 | /.targets.mk 13 | /.venv/ 14 | /.vscode/ 15 | /lib 16 | /node_modules/ 17 | /versioned/ 18 | Gemfile.lock 19 | archive.json 20 | draft-parecki-oauth-metadata-for-nested-flows.xml 21 | package-lock.json 22 | report.xml 23 | !requirements.txt 24 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: "Update Generated Files" 2 | # This rule is not run automatically. 3 | # It can be run manually to update all of the files that are part 4 | # of the template, specifically: 5 | # - README.md 6 | # - CONTRIBUTING.md 7 | # - .note.xml 8 | # - .github/CODEOWNERS 9 | # - Makefile 10 | # 11 | # 12 | # This might be useful if you have: 13 | # - added, removed, or renamed drafts (including after adoption) 14 | # - added, removed, or changed draft editors 15 | # - changed the title of drafts 16 | # 17 | # Note that this removes any customizations you have made to 18 | # the affected files. 19 | on: workflow_dispatch 20 | 21 | jobs: 22 | build: 23 | name: "Update Files" 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: "Checkout" 27 | uses: actions/checkout@v2 28 | 29 | - name: "Update Generated Files" 30 | uses: martinthomson/i-d-template@v1 31 | with: 32 | make: update-files 33 | token: ${{ github.token }} 34 | 35 | - name: "Push Update" 36 | run: git push 37 | -------------------------------------------------------------------------------- /.github/workflows/archive.yml: -------------------------------------------------------------------------------- 1 | name: "Archive Issues and Pull Requests" 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 0,2,4' 6 | repository_dispatch: 7 | types: [archive] 8 | workflow_dispatch: 9 | inputs: 10 | archive_full: 11 | description: 'Recreate the archive from scratch' 12 | default: false 13 | type: boolean 14 | 15 | jobs: 16 | build: 17 | name: "Archive Issues and Pull Requests" 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: "Checkout" 21 | uses: actions/checkout@v2 22 | 23 | # Note: No caching for this build! 24 | 25 | - name: "Update Archive" 26 | uses: martinthomson/i-d-template@v1 27 | env: 28 | ARCHIVE_FULL: ${{ inputs.archive_full }} 29 | with: 30 | make: archive 31 | token: ${{ github.token }} 32 | 33 | - name: "Update GitHub Pages" 34 | uses: martinthomson/i-d-template@v1 35 | with: 36 | make: gh-archive 37 | token: ${{ github.token }} 38 | 39 | - name: "Save Archive" 40 | uses: actions/upload-artifact@v3 41 | with: 42 | path: archive.json 43 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: "Publish New Draft Version" 2 | 3 | on: 4 | push: 5 | tags: 6 | - "draft-*" 7 | 8 | jobs: 9 | build: 10 | name: "Publish New Draft Version" 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: "Checkout" 14 | uses: actions/checkout@v3 15 | 16 | # See https://github.com/actions/checkout/issues/290 17 | - name: "Get Tag Annotations" 18 | run: git fetch -f origin ${{ github.ref }}:${{ github.ref }} 19 | 20 | - name: "Setup" 21 | id: setup 22 | run: date -u "+date=%FT%T" >>"$GITHUB_OUTPUT" 23 | 24 | - name: "Caching" 25 | uses: actions/cache@v3 26 | with: 27 | path: | 28 | .refcache 29 | .venv 30 | .gems 31 | node_modules 32 | .targets.mk 33 | key: i-d-${{ steps.setup.outputs.date }} 34 | restore-keys: i-d- 35 | 36 | - name: "Build Drafts" 37 | uses: martinthomson/i-d-template@v1 38 | with: 39 | token: ${{ github.token }} 40 | 41 | - name: "Upload to Datatracker" 42 | uses: martinthomson/i-d-template@v1 43 | with: 44 | make: upload 45 | 46 | - name: "Archive Submitted Drafts" 47 | uses: actions/upload-artifact@v3 48 | with: 49 | path: "versioned/draft-*-[0-9][0-9].*" 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OAuth Client and Device Metadata for Nested Flows 2 | 3 | This is the working area for the individual Internet-Draft, "OAuth Client and Device Metadata for Nested Flows". 4 | 5 | * [Editor's Copy](https://aaronpk.github.io/oauth-metadata-for-nested-flows/#go.draft-parecki-oauth-metadata-for-nested-flows.html) 6 | * [Datatracker Page](https://datatracker.ietf.org/doc/draft-parecki-oauth-metadata-for-nested-flows) 7 | * [Individual Draft](https://datatracker.ietf.org/doc/html/draft-parecki-oauth-metadata-for-nested-flows) 8 | * [Compare Editor's Copy to Individual Draft](https://aaronpk.github.io/oauth-metadata-for-nested-flows/#go.draft-parecki-oauth-metadata-for-nested-flows.diff) 9 | 10 | 11 | ## Contributing 12 | 13 | See the 14 | [guidelines for contributions](https://github.com/aaronpk/oauth-metadata-for-nested-flows/blob/main/CONTRIBUTING.md). 15 | 16 | Contributions can be made by creating pull requests. 17 | The GitHub interface supports creating pull requests using the Edit (✏) button. 18 | 19 | 20 | ## Command Line Usage 21 | 22 | Formatted text and HTML versions of the draft can be built using `make`. 23 | 24 | ```sh 25 | $ make 26 | ``` 27 | 28 | Command line usage requires that you have the necessary software installed. See 29 | [the instructions](https://github.com/martinthomson/i-d-template/blob/main/doc/SETUP.md). 30 | 31 | -------------------------------------------------------------------------------- /.github/workflows/ghpages.yml: -------------------------------------------------------------------------------- 1 | name: "Update Editor's Copy" 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - README.md 7 | - CONTRIBUTING.md 8 | - LICENSE.md 9 | - .gitignore 10 | pull_request: 11 | paths-ignore: 12 | - README.md 13 | - CONTRIBUTING.md 14 | - LICENSE.md 15 | - .gitignore 16 | 17 | jobs: 18 | build: 19 | name: "Update Editor's Copy" 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: "Checkout" 23 | uses: actions/checkout@v3 24 | 25 | - name: "Setup" 26 | id: setup 27 | run: date -u "+date=%FT%T" >>"$GITHUB_OUTPUT" 28 | 29 | - name: "Caching" 30 | uses: actions/cache@v3 31 | with: 32 | path: | 33 | .refcache 34 | .venv 35 | .gems 36 | node_modules 37 | .targets.mk 38 | key: i-d-${{ steps.setup.outputs.date }} 39 | restore-keys: i-d- 40 | 41 | - name: "Build Drafts" 42 | uses: martinthomson/i-d-template@v1 43 | with: 44 | token: ${{ github.token }} 45 | 46 | - name: "Update GitHub Pages" 47 | uses: martinthomson/i-d-template@v1 48 | if: ${{ github.event_name == 'push' }} 49 | with: 50 | make: gh-pages 51 | token: ${{ github.token }} 52 | 53 | - name: "Archive Built Drafts" 54 | uses: actions/upload-artifact@v3 55 | with: 56 | path: | 57 | draft-*.html 58 | draft-*.txt 59 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This repository relates to activities in the Internet Engineering Task Force 4 | ([IETF](https://www.ietf.org/)). All material in this repository is considered 5 | Contributions to the IETF Standards Process, as defined in the intellectual 6 | property policies of IETF currently designated as 7 | [BCP 78](https://www.rfc-editor.org/info/bcp78), 8 | [BCP 79](https://www.rfc-editor.org/info/bcp79) and the 9 | [IETF Trust Legal Provisions (TLP) Relating to IETF Documents](http://trustee.ietf.org/trust-legal-provisions.html). 10 | 11 | Any edit, commit, pull request, issue, comment or other change made to this 12 | repository constitutes Contributions to the IETF Standards Process 13 | (https://www.ietf.org/). 14 | 15 | You agree to comply with all applicable IETF policies and procedures, including, 16 | BCP 78, 79, the TLP, and the TLP rules regarding code components (e.g. being 17 | subject to a Simplified BSD License) in Contributions. 18 | ## Working Group Information 19 | 20 | Discussion of this work occurs on the [Web Authorization Protocol 21 | Working Group mailing list](mailto:oauth@ietf.org) 22 | ([archive](https://mailarchive.ietf.org/arch/browse/oauth/), 23 | [subscribe](https://www.ietf.org/mailman/listinfo/oauth)). 24 | In addition to contributions in GitHub, you are encouraged to participate in 25 | discussions there. 26 | 27 | **Note**: Some working groups adopt a policy whereby substantive discussion of 28 | technical issues needs to occur on the mailing list. 29 | 30 | You might also like to familiarize yourself with other 31 | [Working Group documents](https://datatracker.ietf.org/wg/oauth/documents/). 32 | -------------------------------------------------------------------------------- /draft-parecki-oauth-metadata-for-nested-flows.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "OAuth Client and Device Metadata for Nested Flows" 3 | abbrev: "Metadata for Nested Flows" 4 | category: std 5 | 6 | docname: draft-parecki-oauth-metadata-for-nested-flows-latest 7 | submissiontype: IETF 8 | number: 9 | date: 10 | consensus: true 11 | v: 3 12 | area: "Security" 13 | workgroup: "Web Authorization Protocol" 14 | keyword: 15 | - oauth 16 | - delegation 17 | venue: 18 | group: "Web Authorization Protocol" 19 | type: "Working Group" 20 | mail: "oauth@ietf.org" 21 | arch: "https://mailarchive.ietf.org/arch/browse/oauth/" 22 | github: "aaronpk/oauth-metadata-for-nested-flows" 23 | latest: "https://aaronpk.github.io/oauth-metadata-for-nested-flows/draft-parecki-oauth-metadata-for-nested-flows.html" 24 | 25 | author: 26 | - 27 | fullname: Aaron Parecki 28 | organization: Okta 29 | email: aaron@parecki.com 30 | uri: https://aaronparecki.com 31 | 32 | normative: 33 | RFC6749: 34 | OpenID: 35 | title: OpenID Connect Core 1.0 36 | target: https://openid.net/specs/openid-connect-core-1_0.html 37 | date: November 8, 2014 38 | author: 39 | - ins: N. Sakimura 40 | - ins: J. Bradley 41 | - ins: M. Jones 42 | - ins: B. de Medeiros 43 | - ins: C. Mortimore 44 | 45 | informative: 46 | RFC9101: 47 | RFC9126: 48 | 49 | 50 | --- abstract 51 | 52 | This specification defines a vocabulary and method of transmitting 53 | information about an OAuth client when a user is redirected through one 54 | or more authorization servers during an OAuth flow. This 55 | provides the deeper nested authorization servers with additional context 56 | that they can use for informational or revocation purposes. 57 | 58 | 59 | --- middle 60 | 61 | # Introduction 62 | 63 | In a typical OAuth flow, the OAuth client redirects the user agent to the 64 | authorization server where the user logs in and (optionally) approves the 65 | request. The OAuth framework describes the interaction between the Client, 66 | the Authorization Server, and the Resource Server. The interaction between 67 | the End-User and the Authorization Server, when the user logs in, 68 | is intentionally out of scope of OAuth. In practice, user authentication at 69 | the Authorization Server happens via a wide variety of methods, including 70 | simple username/password login, as well as redirecting to additional OAuth 71 | or OpenID Connect servers, such as when using consumer social login providers 72 | or enterprise identity providers. 73 | 74 | When user authentication happens via an external identity provider, it 75 | takes place as a brand new OAuth flow from the initial authorization server to the 76 | external identity provider. The initial authorizaiton server acts as an OAuth 77 | client to the external identity provider. Because this is a new flow, the context of the 78 | original OAuth flow is lost, and the external identity provider is unable 79 | to take actions or record information based on the actual OAuth client the 80 | End-User is using. 81 | 82 | This specification introduces a vocabulary and method of transmitting 83 | information about an OAuth client to an external identity provider when 84 | used in nested flows. 85 | 86 | 87 | # Conventions and Definitions 88 | 89 | {::boilerplate bcp14-tagged} 90 | 91 | ## Terminology 92 | 93 | This specification uses the terms "Access Token", "Authorization Code", 94 | "Authorization Endpoint", "Authorization Server" (AS), "Client", "Client Authentication", 95 | "Client Identifier", "Client Secret", "End-User", "Grant Type", "Protected Resource", 96 | "Redirection URI", "Refresh Token", "Resource Owner", "Resource Server" (RS) 97 | and "Token Endpoint" defined by {{RFC6749}}, 98 | and the terms "OpenID Provider" (OP) and "ID Token" defined by {{OpenID}}. 99 | 100 | TODO: Replace RFC6749 references with OAuth 2.1 101 | 102 | This specification defines the following terms: 103 | 104 | "Application Class": 105 | : The type of application the End-User is logging in to, as defined by the AS 106 | in the first OAuth flow. 107 | 108 | "Device": 109 | : The physical device the End-User is interacting with when authorizing a Client. 110 | 111 | This specification uses the term "Identity Provider" (IdP) to refer to 112 | the Authorization Server or OpenID Provider that is used for End-User authentication. 113 | 114 | 115 | # Protocol Overview {#overview} 116 | 117 | For the sake of simplicity, we will refer to the parties involved in the flow as: 118 | 119 | * User Agent: The browser used by the End-User 120 | * Client: The OAuth client that is being used by the End-User 121 | * Authorization Server (AS): The authorization server the Client interacts with and is expecting to receive tokens from 122 | * Identity Provider (IdP): The authorization server where the End-User has an account and logs in 123 | 124 | (In practice, in the inner OAuth flow, the Authorization Server is acting as an OAuth Client to the Identity Provider.) 125 | 126 | 127 | TODO: Convert to ASCII art 128 | 129 | https://github.com/aaronpk/oauth-metadata-for-nested-flows/blob/main/nested-oauth-flow.svg 130 | 131 | 132 | 1. The OAuth Client initiates an OAuth flow by redirecting the User Agent to the Authorization Server. 133 | 2. The User Agent visits the Authorization Server. 134 | 3. The Authorization Server initiates a new OAuth flow as the OAuth client to the Identity Provider by redirecting the User Agent to the Identity Provider, and provides the additional parameters defined in {{parameters}}. 135 | 4. The User Agent visits the Identity Provider. 136 | 5. The Identity Provider authenticates the End-User. 137 | 6. The Identity Provider issues an authorization code and redirects the User Agent back to the Authorization Server. 138 | 7. The User Agent visits the Authorization Server carrying the authorization code from the Identity Provider. 139 | 8. The Authorization Server exchanges the authorization code at the Identity Provider for an access token and optional ID token. 140 | 9. The Identity Provider responds with the tokens. 141 | 10. The Authorization Server consumes the tokens and issues its own authorization code, and redirects the User Agent back to the Client. 142 | 11. The User Agent visits the Client carrying the authorization code from the Authorization Server. 143 | 12. The Client exchanges the authorization code for an access token at the Authorization Server. 144 | 13. The Authorization Server responds with the tokens. 145 | 146 | In this example, the two OAuth flows are authorization code flows. In practice, the inner flow can often be the OpenID Connect Implicit Flow (with `response_type=id_token`) where there is no intermediate authorization code issued. This distinction is not relevant to the rest of this specification. 147 | 148 | Either or both OAuth flows may also be using other OAuth extensions, such as Pushed Authorization Requests {{RFC9126}}, JWT-Secured Authorization Request {{RFC9101}} or others. While these extensions may change the example sequence above slightly, they do not fundamentally change the need for the additional context added by this specification. See {{use-in-flows}} for examples of how to provide the properties defined in this specification along with other OAuth extensions. 149 | 150 | 151 | # Parameters {#parameters} 152 | 153 | This specification introduces new parameters in the authorization request to the Identity Provider 154 | to indicate information about the downstream OAuth client: 155 | 156 | "application_class_id": 157 | : An identifier for the Application Class, unique within the Authorization Server 158 | 159 | "application_class_name": 160 | : A human-readable name describing the Application Class, e.g. "Chat App for iOS" 161 | 162 | "device_id": 163 | : An identifier for the Device the End-User is using 164 | 165 | "device_name": 166 | : A human-readable name describing the End-User's device, e.g. "Alice's iPhone" 167 | 168 | "session_ref": 169 | : A reference to the End-User session at the OAuth Authorization Server. This MUST NOT 170 | be the actual session cookie. This identifier enables the IdP to identify a user's session. 171 | 172 | 173 | 174 | # Use in OAuth Flows {#use-in-flows} 175 | 176 | These parameters can be used in any authorization request to an OAuth Authorization Server or OpenID Provider. Below are examples of including the new parameters in various OAuth flows and extensions. 177 | 178 | ## OAuth Authorization Request 179 | 180 | https://idp.example.com/authorize?response_type=code 181 | &state=af0ifjsldkj 182 | &client_id=s6BhdRkqt3 183 | &redirect_uri=https%3A%2F%2Fas.example.org%2Fcb 184 | &code_challenge=K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U 185 | &code_challenge_method=S256 186 | &scope=openid+profile 187 | &application_class_id=1234 188 | &application_class_name=Chat+for+iOS 189 | &device_id=9876 190 | &device_name=Alice's+iPhone 191 | &session_ref=5124 192 | 193 | 194 | ## Pushed Authorization Requests (PAR) {#par} 195 | 196 | The parameters defined in {{parameters}} are added to the Pushed Authorization Request as POST body parameters, as described in Section 2.1 of {{RFC9126}}. 197 | 198 | POST /par HTTP/1.1 199 | Host: idp.example.com 200 | Content-Type: application/x-www-form-urlencoded 201 | 202 | response_type=code 203 | &state=af0ifjsldkj 204 | &client_id=s6BhdRkqt3 205 | &redirect_uri=https%3A%2F%2Fas.example.org%2Fcb 206 | &code_challenge=K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U 207 | &code_challenge_method=S256 208 | &scope=openid+profile 209 | &application_class_id=1234 210 | &application_class_name=Chat+for+iOS 211 | &device_id=9876 212 | &device_name=Alice's+iPhone 213 | &session_ref=5124 214 | 215 | 216 | ## JWT-Secured Authorization Request (JAR) {#jar} 217 | 218 | The parameters defined in {{parameters}} are added to the Request Object as described in Section 4 of {{RFC9101}}. 219 | 220 | The following is an example of the Claims in a Request Object before the base64url encoding and signing. 221 | 222 | { 223 | "iss": "s6BhdRkqt3", 224 | "aud": "https://idp.example.com", 225 | "response_type": "code", 226 | "client_id": "s6BhdRkqt3", 227 | "redirect_uri": "https://as.example.org/cb", 228 | "scope": "openid profile", 229 | "state": "af0ifjsldkj", 230 | "max_age": 86400, 231 | "application_class_id": "1234", 232 | "application_class_name": "Chat for iOS", 233 | "device_id": "9876", 234 | "device_name": "Alice's iPhone", 235 | "session_ref": "5124" 236 | } 237 | 238 | 239 | 240 | 241 | # Security Considerations 242 | 243 | TODO 244 | 245 | ## Client Authentication 246 | 247 | Because the parameters defined by this specification are not pre-registered at the Identity Provider, the Identity Provider is trusting the Authorization Server with the values provided in the request. 248 | 249 | For this reason, the Authorization Server MUST be a confidential client and use some form of client authentication to the Identity Provider. 250 | 251 | 252 | ## Confidentiality 253 | 254 | The parameters defined by this specification may contain sensitive data, and should not be exposed to unnecessary parties. In particular, passing this data via the browser in redirects opens up opportunities for observing or tampering with this data. 255 | 256 | For this reason, Authorization Servers SHOULD use Pushed Authorization Requests {{RFC9126}} and/or JWT-Secured Authorization Request {{RFC9101}} to prevent tampering and exfiltration of the data. 257 | 258 | 259 | ## Session Reference 260 | 261 | The `session_ref` parameter is meant to be a pointer to a session, and MUST NOT be the same value as the browser sends to the server as the session cookie. 262 | 263 | 264 | # Privacy Considerations 265 | 266 | TODO 267 | 268 | 269 | 270 | # IANA Considerations {#iana} 271 | 272 | TODO 273 | 274 | 275 | --- back 276 | 277 | # Document History 278 | 279 | (( To be removed from the final specification )) 280 | 281 | -00 282 | 283 | * Initial Draft 284 | 285 | 286 | # Acknowledgments 287 | {:numbered="false"} 288 | 289 | TODO 290 | 291 | -------------------------------------------------------------------------------- /nested-oauth-flow.svg: -------------------------------------------------------------------------------- 1 | title%20Nested%20OAuth%20Flow%0A%0Aparticipant%20%22User%20Agent%22%20as%20UA%0Aparticipant%20%22Client%22%20as%20C%0Aparticipant%20%22Authorization%20Server%22%20as%20AS%0Aparticipant%20%22Identity%20Provider%22%20as%20IdP%0A%0A%0Agroup%20Outer%20OAuth%20Flow%20(Client%20to%20AS)%0AC-%3EUA%3A%201.%20Redirect%20to%20AS%0AUA-%3EAS%3A%202.%20Redirect%20to%20AS%0Agroup%20Inner%20OAuth%20flow%20(AS%20to%20IdP)%0AAS-%3EUA%3A%203.%20Redirect%20to%20IDP%0AUA-%3EIdP%3A%204.%20Redirect%20to%20IdP%0Anote%20over%20IdP%3A%205.%20User%20Login%0AIdP--%3EUA%3A%206.%20Authorization%20Code%0AUA-%3EAS%3A%207.%20Authorization%20Code%0AAS-%3EIdP%3A%208.%20Token%20Request%20with%5CnAuthorization%20Code%0AIdP--%3EAS%3A%209.%20Access%20Token%5Cn%20%20%20%20%2B%20ID%20Token%0Aend%0AUA%3C--AS%3A%2010.%20Authorization%20Code%0AUA-%3EC%3A%2011.%20Authorization%20Code%0AC-%3EAS%3A%2012.%20Token%20Request%20with%5CnAuthorization%20Code%0AC%3C--AS%3A%2013.%20Access%20Token%0AendNested OAuth FlowUser AgentClientAuthorization ServerIdentity Provider1. Redirect to AS2. Redirect to AS3. Redirect to IDP4. Redirect to IdP5. User Login6. Authorization Code7. Authorization Code8. Token Request withAuthorization Code9. Access Token    + ID Token10. Authorization Code11. Authorization Code12. Token Request withAuthorization Code13. Access TokenOuter OAuth Flow (Client to AS)Inner OAuth flow (AS to IdP) --------------------------------------------------------------------------------