Documentation: add incomplete intro to OpenID Connect
This commit is contained in:
		
							
								
								
									
										140
									
								
								Documentation/openid-connect.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								Documentation/openid-connect.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| # An overview of OpenID Connect | ||||
|  | ||||
| This document attempts to provide an overview of the [OpenID Connect protocl]( | ||||
| https://openid.net/connect/), a flavor of OAuth2 that dex implements. While | ||||
| this document isn't complete we hope it provides a enough to get users up and | ||||
| running. | ||||
|  | ||||
| ## OAuth2 | ||||
|  | ||||
| OAuth2 should be familiar to anyone who's used something similar to a "Login | ||||
| with Facebook" button. In these cases an application has chosen to let an | ||||
| outside provider, in this case Facebook, attest to your identity instead of | ||||
| having you set a username and password with the app itself. | ||||
|  | ||||
| The general flow for server side apps is: | ||||
|  | ||||
| 1. A new user visits an application. | ||||
| 1. The application redirects the user to Facebook. | ||||
| 1. The user logs into Facebook, then is asked if it's okay to let the | ||||
| application view the user's profile, post on their behalf, etc. | ||||
| 1. If the user clicks okay, Facebook redirects the user back to the application | ||||
| with a code. | ||||
| 1. The application redeems that code with provider for a token that can be used | ||||
| to access the authorized actions, such as viewing a users profile or posting on | ||||
| their wall. | ||||
|  | ||||
| In these cases, dex is acting as Facebook (called the "provider" in OpenID | ||||
| Connect) while clients apps redirect to it for the end user's identity.  | ||||
|  | ||||
| ## ID Tokens | ||||
|  | ||||
| Unfortunately the access token applications get from OAuth2 providers is | ||||
| completely opaque to the client and unique to the provider. The token you | ||||
| receive from Facebook will be completely different from the one you'd get from | ||||
| Twitter or GitHub. | ||||
|  | ||||
| OpenID Connect's primary extension of OAuth2 is an additional token returned in | ||||
| the token response called the ID Token. This token is a [JSON Web Token]( | ||||
| https://tools.ietf.org/html/rfc7519) signed by the OpenID Connect server, with | ||||
| well known fields for user ID, name, email, etc. A typical token response from | ||||
| an OpenID Connect looks like (with less whitespace): | ||||
|  | ||||
| ``` | ||||
| HTTP/1.1 200 OK | ||||
| Content-Type: application/json | ||||
| Cache-Control: no-store | ||||
| Pragma: no-cache | ||||
|  | ||||
| { | ||||
|  "access_token": "SlAV32hkKG", | ||||
|  "token_type": "Bearer", | ||||
|  "refresh_token": "8xLOxBtZp8", | ||||
|  "expires_in": 3600, | ||||
|  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc | ||||
|    yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5 | ||||
|    NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ | ||||
|    fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz | ||||
|    AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q | ||||
|    Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ | ||||
|    NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd | ||||
|    QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS | ||||
|    K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4 | ||||
|    XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| That ID Token is a JWT with three base64'd fields separated by dots. The first | ||||
| is a header, the second is a payload, and the third is a signature of the first | ||||
| two fields. When parsed we can see the payload of this value is. | ||||
|  | ||||
| ``` | ||||
| { | ||||
|   "iss": "http://server.example.com", | ||||
|   "sub": "248289761001", | ||||
|   "aud": "s6BhdRkqt3", | ||||
|   "nonce": "n-0S6_WzA2Mj", | ||||
|   "exp": 1311281970, | ||||
|   "iat": 1311280970 | ||||
| } | ||||
| ``` | ||||
|  | ||||
| This has a few interesting fields such as | ||||
|  | ||||
| * The server that issued this token (`iss`). | ||||
| * The token's subject (`sub`). In this case a unique ID of the end user. | ||||
| * The token's audience (`aud`). The ID of the OAuth2 client this was issued for. | ||||
|  | ||||
| TODO: Add examples of payloads with "email" fields. | ||||
|  | ||||
| ## Discovery | ||||
|  | ||||
| OpenID Connect servers have a discovery mechanism for OAuth2 endpoints, scopes | ||||
| supported, and indications of various other OpenID Connect features. | ||||
|  | ||||
| ``` | ||||
| $ curl http://127.0.0.1:5556/.well-known/openid-configuration | ||||
| { | ||||
|   "issuer": "http://127.0.0.1:5556", | ||||
|   "authorization_endpoint": "http://127.0.0.1:5556/auth", | ||||
|   "token_endpoint": "http://127.0.0.1:5556/token", | ||||
|   "jwks_uri": "http://127.0.0.1:5556/keys", | ||||
|   "response_types_supported": [ | ||||
|     "code" | ||||
|   ], | ||||
|   "subject_types_supported": [ | ||||
|     "public" | ||||
|   ], | ||||
|   "id_token_signing_alg_values_supported": [ | ||||
|     "RS256" | ||||
|   ], | ||||
|   "scopes_supported": [ | ||||
|     "openid", | ||||
|     "email", | ||||
|     "profile" | ||||
|   ] | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Importantly, we've discovered the authorization endpoint, token endpoint, and | ||||
| the location of the server's public keys. OAuth2 clients should be able to use | ||||
| the token and auth endpoints immediately, while a JOSE library can be used to | ||||
| parse the keys. The keys endpoint returns a [JSON Web Key]( | ||||
| https://tools.ietf.org/html/rfc7517) Set of public keys that will look | ||||
| something like this: | ||||
|  | ||||
| ``` | ||||
| $ curl http://127.0.0.1:5556/keys | ||||
| { | ||||
|   "keys": [ | ||||
|     { | ||||
|       "use": "sig", | ||||
|       "kty": "RSA", | ||||
|       "kid": "5d19a0fde5547960f4edaa1e1e8293e5534169ba", | ||||
|       "alg": "RS256", | ||||
|       "n": "5TAXCxkAQqHEqO0InP81z5F59PUzCe5ZNaDsD1SXzFe54BtXKn_V2a3K-BUNVliqMKhC2LByWLuI-A5ZlA5kXkbRFT05G0rusiM0rbkN2uvRmRCia4QlywE02xJKzeZV3KH6PldYqV_Jd06q1NV3WNqtcHN6MhnwRBfvkEIm7qWdPZ_mVK7vayfEnOCFRa7EZqr-U_X84T0-50wWkHTa0AfnyVvSMK1eKL-4yc26OWkmjh5ALfQFtnsz30Y2TOJdXtEfn35Y_882dNBDYBxtJV4PaSjXCxhiaIuBHp5uRS1INyMXCx2ve22ASNx_ERorv6BlXQoMDqaML2bSiN9N8Q", | ||||
|       "e": "AQAB" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| ``` | ||||
		Reference in New Issue
	
	Block a user