[keycloak-dev] token service
Bill Burke
bburke at redhat.com
Wed Mar 15 11:01:47 EDT 2017
On 3/15/17 7:24 AM, Pedro Igor Silva wrote:
>
> 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.
provider matches up with a Keycloak ComponentModel which matches up to a
Keycloak ProviderFactory which knows how to do the translation. Need
some way of finding the service that can handle the translation of the
external token.
The requested_token_type in my proposal is the catagory of token you
want, not its actual type
> "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.
I still think we should have a separation between external and internal
exchanges.
>
> "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.
An STS could be used to convert a Facebook AT into a Keycloak one, but
not vice versa. For Facebook, Google etc. a browser protocol is
required in many cases to obtain the external token. With Identity
Brokering you are delegating authentication to another IDP. Keycloak
doesn't know how the user will be authenticated. For instance, with
Google a user may require authentication via SMS. FYI, this is why the
"Client Initiated Account Linking" protocol was just implemented.
There's also a lot of brokers that can only do logout via a browser
protocol.
I see what you mean though. We already have the beginnings of an STS
that is spread out in different classes and services.
>
>
> 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.
We already have this separation. Authentication is independent of
protocol and we have a common data model that isn't protocol specific.
We also do not map from a brokered SAML assertion to a client's OIDC
access token. The brokered SAML assertion is mapped into a common data
model which is then mapped to the OIDC access token.
I see what you are saying though. Token Exchange should be done in
conjunction with refactoring and rewriting the Identity Brokering SPI as
the two are related. This also probably has an effect on Client
configuration as I could see an STS-only based client that is just
interacting with the STS.
Bill
More information about the keycloak-dev
mailing list