On Wed, Mar 15, 2017 at 12:01 PM, Bill Burke <bburke(a)redhat.com> wrote:
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
I understand that. Being the token I want, I can still provide ways to
configure their corresponding providers or a default (in case
requested_token_type is not provided) in admin console. It seems to be just
a 1:1 mapping between a token type and the corresponding provider. I think
clients of the token exchange api should not be aware of providers in KC,
but about the token types they use/need.
> "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.
That should be fine. But are you planning to support the exchange of SAML
assertions for OIDC/OAuth2 tokens ?
> "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.
Yeah. I understand Facebook or Google don't wllow token exchanges. But we
do provide an endpoint to obtain the token previously stored for a identity
provider. As you noticed, my point is that we could use the token exchange
for that and centralize such services in a single place.
And nothing stop us to support integration with external STSs by just
setting up things in admin console, just like we do for brokering. For
instance, suppose I have a business partner that supports OAuth2 Token
Exchanges and I need to access services protected by this partner's domain.
>
>
> 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