Merge pull request #217 from patriot1burke/master
KEYCLOAK-5650 KEYCLOAK-5685 KEYCLOAK-5648
This commit is contained in:
commit
c9e0423266
1 changed files with 36 additions and 10 deletions
|
@ -304,9 +304,7 @@ new access token.
|
|||
|
||||
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
|
||||
provide either the public key to validate external token signatures, or a valid key URL to lookup key
|
||||
identifiers contained in the token.
|
||||
NOTE: SAML identity providers are not supported at this time. Twitter tokens cannot be exchanged either.
|
||||
|
||||
|
||||
==== 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
|
||||
|
||||
When your client is exchanging an existing internal token to an external one, you must provide the
|
||||
`subject_issuer` parameter. This parameter must be the alias of a configured identity provider. The
|
||||
`subject_token_type` parameter must be specified and either be an identity token, `urn:ietf:params:oauth:token-type:id_token`,
|
||||
or a JWT access token type `urn:ietf:params:oauth:token-type:jwt:access_token`. The `subject_token` must be a JWT
|
||||
irregardless and must be signed using Json Web Signatures.
|
||||
The `subject_token_type` must either be `urn:ietf:params:oauth:token-type:access_token` or `urn:ietf:params:oauth:token-type:jwt`.
|
||||
If the type is `urn:ietf:params:oauth:token-type:access_token` you must specify the `subject_issuer` parameter and it must be the
|
||||
alias of the configured identity provider. If the type is `urn:ietf:params:oauth:token-type:jwt`, the provider will be matched via
|
||||
the `issuer` claim within the JWT which must be the alias of the provider, or a registered issuer within the providers configuration.
|
||||
|
||||
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
|
||||
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" \
|
||||
-d "subject_token=...." \
|
||||
-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" \
|
||||
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
|
||||
----
|
||||
|
@ -384,7 +385,7 @@ curl -X POST \
|
|||
-d "client_secret=geheim" \
|
||||
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
|
||||
-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 "requested_subject=wburke" \
|
||||
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
|
||||
----
|
||||
|
||||
=== 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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue