On Tue, Mar 14, 2017 at 7:32 PM, Bill Burke <bburke(a)redhat.com> wrote:
There seems to be momentum building around token services,
particular
features around:
* Token downgrades. Reducing the scope of an access token when
delegating to a separate less trusted service. For example, you have a
token with admin priveleges and you want to remove those privleges
before re-using the token against another service.
* Token exchanges. Ability to convert a foreign token to and from a
Keycloak one. For example, if you want to trust tokens issued by some
proprietary IBM IDM.
* Trusting tokens from other Keycloak domains. (Although I think this
can fall under token exchanges).
* Token revalidation (I think we have this).
There are some specs around this that Pedro pointed me to:
[
1]https://tools.ietf.org/html/draft-richer-oauth-chain-00
[
2]https://tools.ietf.org/html/draft-campbell-oauth-sts-01
<
https://tools.ietf.org/html/draft-campbell-oauth-sts-01>
I don't think they are either missing things we need or too complex for
our needs.
* Token downgrades, or token redelgation/chaining
I don't want to require apps to know the exact scope they have to
downgrade to if they want to reduce the scope when interacting with
another service. Let's provide an additional extension to [1] and
supply a "client" parameter in which the clientId of the redelegation
you want to perform is used. The token returned would be a union of the
access token's scope and the configured scope of the target client.
* Token exchanges
For [2] Keycloak just doesn't have all the concepts that are spoken
about here. I also don't think the spec is good enough. Coverting
tokens would be handled by a Token Exchange SPI. A provider would be
configured per realm and implemented on top of the ComponentModel SPI.
Each of these provider instances would handle either converting from an
external token to a realm token and/or from a realm token to an external
token. There will also be a rest endpoint on the realm to convert from
external to Keycloak and a separate REST endpoint for converting from
Keycloak to an external token.
From externl to Keycloka:
This would be a form POST to /token/convert-from with these additional
form parameters
"token" - REQUIRED. string rep of the token
"provider" - REQUIRED. id of transformer register in the realm for the
token type
Why you need to send "provider" ? If you are already sending "
requested_token_type", the provider is implicit, right ?
Or if you don't send "requested_token_type" you can allow users to specify
the default token type to be issued.
"requested-token-type" - OPTIONAL. "id",
"access", "offline", or
I think we have a great opportunity here to also support use cases where
you need to exchange a SAML assertion with an OAuth2/OIDC token. There is a
specific standard for that, but I think a STS would be perfect for this.
I remember some people asking for this and I think it will be a great win
for enterprise use cases and legacy systems.
"refresh". Default is "access".
"scope" - OPTIONAL. Same as oauth scope.
> This operation is analogous to the code to token flow. Here we are
> creating a token tailored to the authenticated client. So all scope
> configurations and mappers that the client has are applied. This means
> that the client must be registered as an OIDC client. The SPI would look
> something like this:
>
> interface TokenExchangeFromProvider extends Provider {
>
> Transformer parse(ClientModel client, Map<String, String>
> formParameters);
>
> interface Transformer {
>
> UserModel getUser();
> IDToken convert(IDToken idToken);
> AccessToken convert(AccessToken accessToken);
> }
> }
>
> The getUser() method returns a user that was authenticated from the
> external token. The convert() methods just gives the provider the
> flexibility to do further transformations on the returned token.
>
> The runtime would do something like this:
>
> ClientModel authenticatedClient = ...;
> ComponentModel model = realm.getComponent(formParams.get("provider"));
> TokenExchangeFromProvider provider =
> session.getProvider(TokenExchangeFromProvider.class, model);
> Transformer transformer = provider.parse(formParams);
> UserModel user = transformer.getUser();
> if (formParam.get("requested-token-type").equals("access")) {
> AccessToken accessToken = generateAccessToken(authenticatedClient,
> user, ...);
> accessToken = transformer.convert(accessToken).
> }
>
> Something similar would be done for converting a Keycloak token to an
> external token:
>
> This would be a form POST to /token/convert-to with these additional
> form parameters
>
> "token" - REQUIRED. string rep of the token
> "provider" - REQUIRED. id of transformer register in the realm for the
token type
Same comments I did to "external to Keycloak" exchange. In this particular
case, I think we can also provide some integration with identity brokering
functionality.
For instance, suppose I have a KC token and I want to obtain a Facebook AT.
I know we have ways to do that today, but I think that using a STS is much
more neat. In this case, we also don't need to send the provider, but we
can make this completely configurable from admin console. E.g.: associate
token types with a OOTB/custom identity providers. Maybe we can even define
a Token Exchange Identity Provider, which can be configured to integrate
with an external STS.
interface TokenExchangeToProvider extends Provider {
ResponseBuilder parse(ClientModel client, Map<String, String>
formParameters);
}
Since we're crafting something for an external token system, we give the
provider complete autonomy in crafting the HTTP response to this operation.
Not sure you remember. But when we were discussing SAML on the earlier days
of Keycloak, I mentioned a API for Security Token Service that we had in PL
for years (I think Stefan did it). Plus a simplified version of this API in
PL JEE/IDM. One of the things that I liked most in PL is that the STS is
the backbone for the IdP. What I mean is, the IdP don't care about how a
token is issued/revoked/validated/renewed, but delegate this to STS. Being
responsible to basically implement the communication/protocol between the
involved parties.
_______________________________________________
keycloak-dev mailing list
keycloak-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/keycloak-dev