Skip to content
Snippets Groups Projects
Unverified Commit 01d63b08 authored by Eric Chiang's avatar Eric Chiang Committed by GitHub
Browse files

Merge pull request #1176 from vyshane/master

New id_provider scope that adds the connector ID and user ID to the ID token claims
parents ce686390 b03c85e5
Branches
Tags
No related merge requests found
...@@ -12,6 +12,7 @@ The following is the exhaustive list of scopes supported by dex: ...@@ -12,6 +12,7 @@ The following is the exhaustive list of scopes supported by dex:
| `email` | ID token claims should include the end user's email and if that email was verified by an upstream provider. | | `email` | ID token claims should include the end user's email and if that email was verified by an upstream provider. |
| `profile` | ID token claims should include the username of the end user. | | `profile` | ID token claims should include the username of the end user. |
| `groups` | ID token claims should include a list of groups the end user is a member of. | | `groups` | ID token claims should include a list of groups the end user is a member of. |
| `federated:id` | ID token claims should include information from the ID provider. The token will contain the connector ID and the user ID assigned at the provider. |
| `offline_access` | Token response should include a refresh token. Doesn't work in combinations with some connectors, notability the [SAML connector][saml-connector] ignores this scope. | | `offline_access` | Token response should include a refresh token. Doesn't work in combinations with some connectors, notability the [SAML connector][saml-connector] ignores this scope. |
| `audience:server:client_id:( client-id )` | Dynamic scope indicating that the ID token should be issued on behalf of another client. See the _"Cross-client trust and authorized party"_ section below. | | `audience:server:client_id:( client-id )` | Dynamic scope indicating that the ID token should be issued on behalf of another client. See the _"Cross-client trust and authorized party"_ section below. |
...@@ -22,10 +23,20 @@ Beyond the [required OpenID Connect claims][core-claims], and a handful of [stan ...@@ -22,10 +23,20 @@ Beyond the [required OpenID Connect claims][core-claims], and a handful of [stan
| Name | Description | | Name | Description |
| ---- | ------------| | ---- | ------------|
| `groups` | A list of strings representing the groups a user is a member of. | | `groups` | A list of strings representing the groups a user is a member of. |
| `federated_claims` | The connector ID and the user ID assigned to the user at the provider. |
| `email` | The email of the user. | | `email` | The email of the user. |
| `email_verified` | If the upstream provider has verified the email. | | `email_verified` | If the upstream provider has verified the email. |
| `name` | User's display name. | | `name` | User's display name. |
The `federated_claims` claim has the following format:
```json
"federated_claims": {
"connector_id": "github",
"user_id": "110272483197731336751"
}
```
## Cross-client trust and authorized party ## Cross-client trust and authorized party
Dex has the ability to issue ID tokens to clients on behalf of other clients. In OpenID Connect terms, this means the ID token's `aud` (audience) claim being a different client ID than the client that performed the login. Dex has the ability to issue ID tokens to clients on behalf of other clients. In OpenID Connect terms, this means the ID token's `aud` (audience) claim being a different client ID than the client that performed the login.
......
...@@ -107,6 +107,7 @@ const ( ...@@ -107,6 +107,7 @@ const (
scopeGroups = "groups" scopeGroups = "groups"
scopeEmail = "email" scopeEmail = "email"
scopeProfile = "profile" scopeProfile = "profile"
scopeFederatedID = "federated:id"
scopeCrossClientPrefix = "audience:server:client_id:" scopeCrossClientPrefix = "audience:server:client_id:"
) )
...@@ -255,6 +256,13 @@ type idTokenClaims struct { ...@@ -255,6 +256,13 @@ type idTokenClaims struct {
Groups []string `json:"groups,omitempty"` Groups []string `json:"groups,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
FederatedIDClaims *federatedIDClaims `json:"federated_claims,omitempty"`
}
type federatedIDClaims struct {
ConnectorID string `json:"connector_id,omitempty"`
UserID string `json:"user_id,omitempty"`
} }
func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []string, nonce, accessToken, connID string) (idToken string, expiry time.Time, err error) { func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []string, nonce, accessToken, connID string) (idToken string, expiry time.Time, err error) {
...@@ -313,6 +321,11 @@ func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []str ...@@ -313,6 +321,11 @@ func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []str
tok.Groups = claims.Groups tok.Groups = claims.Groups
case scope == scopeProfile: case scope == scopeProfile:
tok.Name = claims.Username tok.Name = claims.Username
case scope == scopeFederatedID:
tok.FederatedIDClaims = &federatedIDClaims{
ConnectorID: connID,
UserID: claims.UserID,
}
default: default:
peerID, ok := parseCrossClientScope(scope) peerID, ok := parseCrossClientScope(scope)
if !ok { if !ok {
...@@ -405,7 +418,7 @@ func (s *Server) parseAuthorizationRequest(r *http.Request) (req storage.AuthReq ...@@ -405,7 +418,7 @@ func (s *Server) parseAuthorizationRequest(r *http.Request) (req storage.AuthReq
switch scope { switch scope {
case scopeOpenID: case scopeOpenID:
hasOpenIDScope = true hasOpenIDScope = true
case scopeOfflineAccess, scopeEmail, scopeProfile, scopeGroups: case scopeOfflineAccess, scopeEmail, scopeProfile, scopeGroups, scopeFederatedID:
default: default:
peerID, ok := parseCrossClientScope(scope) peerID, ok := parseCrossClientScope(scope)
if !ok { if !ok {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment