Merge pull request #217 from patriot1burke/master

KEYCLOAK-5650 KEYCLOAK-5685 KEYCLOAK-5648
This commit is contained in:
Bill Burke 2017-10-16 18:18:15 -04:00 committed by GitHub
commit c9e0423266

View file

@ -304,9 +304,7 @@ new access token.
These types of changes required a configured identity provider in the admin console. These types of changes required a configured identity provider in the admin console.
NOTE: Only OIDC identity providers are support at this time. Validate signatures switch is required and you must NOTE: SAML identity providers are not supported at this time. Twitter tokens cannot be exchanged either.
provide either the public key to validate external token signatures, or a valid key URL to lookup key
identifiers contained in the token.
==== Granting Permission for the Exchange ==== Granting Permission for the Exchange
@ -320,11 +318,14 @@ to do this is <<_client_to_client_permission, discussed earlier>> in this sectio
==== Making the Request ==== Making the Request
When your client is exchanging an existing internal token to an external one, you must provide the The `subject_token_type` must either be `urn:ietf:params:oauth:token-type:access_token` or `urn:ietf:params:oauth:token-type:jwt`.
`subject_issuer` parameter. This parameter must be the alias of a configured identity provider. The If the type is `urn:ietf:params:oauth:token-type:access_token` you must specify the `subject_issuer` parameter and it must be the
`subject_token_type` parameter must be specified and either be an identity token, `urn:ietf:params:oauth:token-type:id_token`, alias of the configured identity provider. If the type is `urn:ietf:params:oauth:token-type:jwt`, the provider will be matched via
or a JWT access token type `urn:ietf:params:oauth:token-type:jwt:access_token`. The `subject_token` must be a JWT the `issuer` claim within the JWT which must be the alias of the provider, or a registered issuer within the providers configuration.
irregardless and must be signed using Json Web Signatures.
For validation, if the token is an access token, the provider's user info service will be invoked to validate the token. A successful call
will mean that the access token is valid. If the subject token is a JWT and if the provider has signature validation enabled, that will be attempted,
otherwise, it will default to also invoking on the user info service to validate the token.
By default, the internal token minted will use the calling client to determine what's in the token using the protocol By default, the internal token minted will use the calling client to determine what's in the token using the protocol
mappers defined for the calling client. Alternatively, you can specify a different target client using the `audience` mappers defined for the calling client. Alternatively, you can specify a different target client using the `audience`
@ -338,7 +339,7 @@ curl -X POST \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \ -d "subject_token=...." \
-d "subject_issuer=myOidcProvider" \ -d "subject_issuer=myOidcProvider" \
--data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:id_token" --data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:access_token"
-d "audience=target-client" \ -d "audience=target-client" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
---- ----
@ -384,7 +385,7 @@ curl -X POST \
-d "client_secret=geheim" \ -d "client_secret=geheim" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \ -d "subject_token=...." \
--data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:refresh_token" \ --data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "audience=target-client" \ -d "audience=target-client" \
-d "requested_subject=wburke" \ -d "requested_subject=wburke" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
@ -457,6 +458,31 @@ curl -X POST \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
---- ----
=== Expand Permission Model With Service Accounts
When granting clients permission to exchange, you don't necessarily have to manually enable those permissions for each and every client.
If the client has a service account associated with it, you can use a role to group permissions together and assign exchange permissions
by assigning a role to the client's service account. For example, you might define a `naked-exchange` role and any service account that has that
role can do a naked exchange.
=== Exchange Vulnerabilities
When you start allowing token exchanges, there's various things you have to both be aware of and careful of.
The first is public clients. Public clients do not have or require a client credential in order to perform an exchange. Anybody that has a valid
token will be able to __impersonate__ the public client and perform the exchanges that public client is allowed to perform. If there
are any untrustworthy clients that are managed by your realm, public clients may open up vulnerabilities in your permission models.
This is why direct naked exchanges do not allow public clients and will abort with an error if the calling client is public.
It is possible to exchange social tokens provided by Facebook, Google, etc. for a realm token. Be careful and vigilante on what
the exchange token is allowed to do as its not hard to create fake accounts on these social websites. Use default roles, groups, and identity provider mappers to control what attributes and roles
are assigned to the external social user.
Direct naked exchanges are quite dangerous. You are putting a lot of trust in the calling client that it will never leak out
its client credentials. If those credentials are leaked, then the thief can impersonate anybody in your system. This is in direct
contrast to confidential clients that have existing tokens. You have two factors of authentication, the access token and the client
credentials, and you're only dealing with one user. So use direct naked exchanges sparingly.