From e377d476ae78944cc32db49b788de95a20506d7b Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Wed, 10 Aug 2016 22:25:15 -0700 Subject: [PATCH] Documentation: add incomplete intro to OpenID Connect --- Documentation/openid-connect.md | 140 ++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 Documentation/openid-connect.md diff --git a/Documentation/openid-connect.md b/Documentation/openid-connect.md new file mode 100644 index 00000000..847d5bf1 --- /dev/null +++ b/Documentation/openid-connect.md @@ -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" + } + ] +} +```