From a4cb57ab5d7328a71b073302a41a7fcf66a6c48d Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Thu, 20 Apr 2017 16:48:09 -0700 Subject: [PATCH] Documentation: add a doc describing how to use dex --- Documentation/getting-started.md | 3 + Documentation/img/dex-flow.png | Bin 0 -> 21257 bytes Documentation/using-dex.md | 188 +++++++++++++++++++++++++++++++ README.md | 1 + 4 files changed, 192 insertions(+) create mode 100644 Documentation/img/dex-flow.png create mode 100644 Documentation/using-dex.md diff --git a/Documentation/getting-started.md b/Documentation/getting-started.md index bf85ae59..5633135d 100644 --- a/Documentation/getting-started.md +++ b/Documentation/getting-started.md @@ -40,8 +40,11 @@ Login to dex through the example app using the following steps. ## Further reading +Dex is generally used as a building block to drive authentication for other apps. See [_"Writing apps that use dex"_][using-dex] for an overview of instrumenting apps to work with dex. + Check out the Documentation directory for further reading on setting up different storages, interacting with the dex API, intros for OpenID Connect, and logging in through other identity providers such as Google, GitHub, or LDAP. [go-setup]: https://golang.org/doc/install [example-config]: ../examples/config-dev.yaml [oidc-discovery]: https://openid.net/specs/openid-connect-discovery-1_0-17.html#ProviderMetadata +[using-dex]: using-dex.md diff --git a/Documentation/img/dex-flow.png b/Documentation/img/dex-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..78acffd1a4ed91e3ac5dbec37bb172c338e91438 GIT binary patch literal 21257 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 y3!>S;SvUDNxWakbg4DJ#fa7W&<|CrepAe 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

46r?$k6z2X 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 literal 0 HcmV?d00001 diff --git a/Documentation/using-dex.md b/Documentation/using-dex.md new file mode 100644 index 00000000..8ac230fa --- /dev/null +++ b/Documentation/using-dex.md @@ -0,0 +1,188 @@ +# Writing apps that use dex + +Once you have dex up and running, the next step is to write applications that use dex to drive authentication. Apps that interact with dex generally fall into one of two categories: + +1. Apps that request OpenID Connect ID tokens to authenticate users. + * Used for authenticating an end user. + * Must be web based. +2. Apps that consume ID tokens from other apps. + * Needs to verify that a client is acting on behalf of a user. + +The first category of apps are standard OAuth2 clients. Users show up at a website, and the application wants to authenticate those end users by pulling claims out of the ID token. + +The second category of apps consume ID tokens as credentials. This lets another service handle OAuth2 flows, then use the ID token retrieved from dex to act on the end user's behalf with the app. An example of an app that falls into this category is the [Kubernetes API server][api-server]. + +## Requesting an ID token from dex + +Apps that directly use dex to authenticate a user use OAuth2 code flows to request a token response. The exact steps taken are: + +* User visits client app. +* Client app redirects user to dex with an OAuth2 request. +* Dex determines user's identity. +* Dex redirects user to dex with a code. +* Client exchanges code with dex for an id_token. + +![][dex-flow] + +The dex repo contains a small [example app][example-app] as a working, self contained app that performs this flow. + +The rest of this section explores the code sections which to help explain how to implementing this logic in your own app. + +### Configuring your app + +The example app uses the following Go packages to perform the code flow: + +* [github.com/coreos/go-oidc][go-oidc] +* [golang.org/x/oauth2][go-oauth2] + +First, client details should be present in the dex configuration. For example, we could register an app with dex with the following section: + +```yaml +staticClients: +- id: example-app + secret: example-app-secret + name: 'Example App' + # Where the app will be running. + redirectURIs: + - 'http://127.0.0.1:5555/callback' +``` + +In this case, the Go code would configured as: + +```go +// Initialize a provider by specifying dex's issuer URL. +provider, err := oidc.NewProvider(ctx, "https://dex-issuer-url.com") +if err != nil { + // handle error +} + +// Configure the OAuth2 config with the client values. +oauth2Config := oauth2.Config{ + // client_id and client_secret of the client. + ClientID: "example-app", + ClientSecret: "example-app-secret", + + // The redirectURL. + RedirectURL: "http://127.0.0.1:5556/callback", + + // Discovery returns the OAuth2 endpoints. + Endpoint: provider.Endpoint(), + + // "openid" is a required scope for OpenID Connect flows. + // + // Other scopes, such as "groups" can be requested. + Scopes: []string{oidc.ScopeOpenID, "profile", "email", "groups"}, +} + +// Create an ID token parser. +idTokenVerifier := provider.NewVerifier(&oidc.Config{ClientID: "example-app"}) +``` + +The HTTP server should then redirect unauthenticated users to dex to initialize the OAuth2 flow. + +```go +// handleRedirect is used to start an OAuth2 flow with the dex server. +func handleRedirect(w http.ResponseWriter, r *http.Request) { + state := newState() + http.Redirect(w, r, oauth2Config.AuthCodeURL(state), http.StatusFound) +} +``` + +After dex verifies the user's identity it redirects the user back to the client app with a code that can be exchanged for an ID token. The ID token can then be parsed by the verifier created above. This immediately + +```go +func handleOAuth2Callback(w http.ResponseWriter, r *http.Request) { + state := r.URL.Query().Get("state") + + // Verify state. + + oauth2Token, err := oauth2Config.Exchange(ctx, r.URL.Query().Get("code")) + if err != nil { + // handle error + } + + // Extract the ID Token from OAuth2 token. + rawIDToken, ok := oauth2Token.Extra("id_token").(string) + if !ok { + // handle missing token + } + + // Parse and verify ID Token payload. + idToken, err := idTokenVerifier.Verify(ctx, rawIDToken) + if err != nil { + // handle error + } + + // Extract custom claims. + var claims struct { + Email string `json:"email"` + Verified bool `json:"email_verified"` + Groups []string `json:"groups"` + } + if err := idToken.Claims(&claims); err != nil { + // handle error + } +} +``` + +### State tokens + +The state parameter is an arbitrary string that dex will always return with the callback. It plays a security role, preventing certain kinds of OAuth2 attacks. Specifically it can be used by clients to ensure: + +* The user who started the flow is the one who finished it, by linking the user's session with the state token. For example, by setting the state as an HTTP cookie, then comparing it when the user returns to the app. +* The request hasn't been replayed. This could be accomplished by associating some nonce in the state. + +A more thorough discussion of these kinds of best practices can be found in the [_"OAuth 2.0 Threat Model and Security Considerations"_][oauth2-threat-model] RFC. + +## Consuming ID tokens + +Apps can also choose to consume ID tokens, letting other trusted clients handle the web flows for login. Clients pass along the ID tokens they receive from dex, usually as a bearer token, letting them act at the user to the backend service. + +To accept ID tokens as user credentials, an app would construct an OpenID Connect verifier similarly to the above example. The verifier validates the ID token's signature, ensures it hasn't expired, etc. An important part of this code is that the verifier only trusts the example app's client. This ensures the example app is the one who's using the ID token, and not another, untrusted client. + +```go +// Initialize a provider by specifying dex's issuer URL. +provider, err := oidc.NewProvider(ctx, "https://dex-issuer-url.com") +if err != nil { + // handle error +} +// Create an ID token parser, but only trust ID tokens issued to "example-app" +idTokenVerifier := provider.NewVerifier(&oidc.Config{ClientID: "example-app"}) +``` + +The verifier can then be used to pull user info out of tokens: + +```go +type user struct { + email string + groups []string +} + +// authorize verifies a bearer token and pulls user information form the claims. +func authorize(ctx context.Context, bearerToken string) (*user, error) { + idToken, err := idTokenVerifier.Verify(ctx, bearerToken) + if err != nil { + return nil, fmt.Errorf("could not verify bearer token: %v", err) + } + // Extract custom claims. + var claims struct { + Email string `json:"email"` + Verified bool `json:"email_verified"` + Groups []string `json:"groups"` + } + if err := idToken.Claims(&claims); err != nil { + return nil, fmt.Errorf("failed to parse claims: %v", err) + } + if !claims.Verified { + return nil, fmt.Errorf("email (%q) in returned claims was not verified", claims.Email) + } + return &user{claims.Email, claims.Groups}, nil +} +``` + +[api-server]: https://kubernetes.io/docs/admin/authentication/#openid-connect-tokens +[dex-flow]: img/dex-flow.png +[example-app]: ../cmd/example-app +[oauth2-threat-model]: https://tools.ietf.org/html/rfc6819 +[go-oidc]: https://godoc.org/github.com/coreos/go-oidc +[go-oauth2]: https://godoc.org/golang.org/x/oauth2 diff --git a/README.md b/README.md index 4160dfdd..3a2c8b4f 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ More docs for running dex as a Kubernetes authenticator can be found [here](Docu ## Documentation * [Getting started](Documentation/getting-started.md) +* [Writing apps that use dex](Documentation/using-dex.md) * [What's new in v2](Documentation/v2.md) * [Custom scopes, claims, and client features](Documentation/custom-scopes-claims-clients.md) * [Storage options](Documentation/storage.md)