Ok Pedro, all was clear!
Thank you very much for your support and your patience, your answers will
definitely help us in building our authorization system.
Have a nice day and, again, THANK YOU! :)
Matteo
On Tue, Apr 16, 2019 at 2:08 PM Pedro Igor Silva <psilva(a)redhat.com> wrote:
Yes, sure.
If you are using our adapter, you should be able to enable the policy
enforcer to your services. What it does is enforce access to protected
resources based on the policies you have on Keycloak.
The policy enforcer has two operation modes. One that uses regular access
tokens (sent as a bearer to your services) to obtain permissions from the
server, thus requiring interaction between the enforcer and Keycloak to
obtain the decision. And another one that leverages bearer token
authorization to enforce access based on the permissions within the token.
It is up to you to decide which one works best for your use case.
For instance, when using a regular access token to access your service, a
connection to Keycloak is necessary in order to check whether or not access
should be granted. Whereas if you are using a "permission token", you
don't
have this additional request. The regular access token approach makes your
client's life easier as they just need to send the access token, whereas
the other approach requires your client to exchange a regular access token
with a permission token. The permission token approach also allows you to
do incremental authorization so that your clients can obtain permissions on
demand, etc ...
Performance-wise, the regular access token approach is obviously more
expensive. But I don't think it should be a bottleneck. Microservices is
all about S2S :)
On Tue, Apr 16, 2019 at 4:16 AM Matteo Restelli <mrestelli(a)cuebiq.com>
wrote:
> Hi Pedro,
> you can find, inline below, a question about the authorization services (
> the last question, i promise :) ).
>
>
> Thank you again,
> Matteo
>
> On Mon, Apr 15, 2019 at 2:20 PM Pedro Igor Silva <psilva(a)redhat.com>
> wrote:
>
>>
>>
>> On Mon, Apr 15, 2019 at 5:08 AM Matteo Restelli <mrestelli(a)cuebiq.com>
>> wrote:
>>
>>> Hi Pedro,
>>> Thank you for your replies and your patience :)
>>> My answers inline below ;)
>>>
>>> Have a nice day,
>>> Matteo
>>>
>>> On Fri, Apr 12, 2019 at 4:53 PM Pedro Igor Silva <psilva(a)redhat.com>
>>> wrote:
>>>
>>>>
>>>>
>>>> On Fri, Apr 12, 2019 at 11:28 AM Matteo Restelli
<mrestelli(a)cuebiq.com>
>>>> wrote:
>>>>
>>>>> Thank you Pedro,
>>>>> My answers (and questions) inline below ;)
>>>>>
>>>>> Thank you!
>>>>> Matteo
>>>>>
>>>>> On Fri, Apr 12, 2019 at 3:20 PM Pedro Igor Silva
<psilva(a)redhat.com>
>>>>> wrote:
>>>>>
>>>>>> Thanks. Now it is more clear.
>>>>>>
>>>>>> Answers inline below.
>>>>>>
>>>>>>
>>>>>> On Fri, Apr 12, 2019 at 7:29 AM Matteo Restelli <
>>>>>> mrestelli(a)cuebiq.com> wrote:
>>>>>>
>>>>>>> Hi Pedro,
>>>>>>> i'll try to reply to your questions:
>>>>>>>
>>>>>>> - We've configured Cognito as an identity provider in
Keycloak,
>>>>>>> importing the configuration via the OIDC
discovery-configuration endpoint.
>>>>>>> At this point we needed to introduce the clientID &
secret, so we've
>>>>>>> created a new confidential client inside AWS Cognito and used
its id
>>>>>>> &secret in the Keycloak's Identity provider config
>>>>>>>
>>>>>>
>>>>>>> - We've set the permission & policy about token
exchange feature to
>>>>>>> our Keycloak client
>>>>>>>
>>>>>>> - The SRP flow leverages the SRP authentication protocol (so
>>>>>>> basically, no password is sent to the server). The result of
this flow is a
>>>>>>> couple of JWT tokens (access and id token), but the access
token doesn't
>>>>>>> respect the OIDC rules (it doesn't contain the openid
scope). This last
>>>>>>> point is what make the token exchange process impossible
(this because,
>>>>>>> during the process, Cognito replies that "the token
doesn't contain the
>>>>>>> openid scope"). About that i want to highlight the fact
that these problems
>>>>>>> are entirely Cognito related: if we use a standard OAuth2
Flow (like
>>>>>>> Authorization code grant or implicit) the process works as
expected.
>>>>>>>
>>>>>>
>>>>>> I see now. In this case, I think you should try to include
somehow
>>>>>> the openid scope in the access token so that Cognito can process
it. I
>>>>>> guess this error is returned when the broker is invoking the user
endpoint
>>>>>> on Cognito? based on the OIDC user info endpoint definition, the
endpoint
>>>>>> should accept access tokens.
>>>>>>
>>>>>
>>>>> Yeah unfortunately we're stuck with this option, because Cognito
is
>>>>> lacking support on adding this scope to the token (especially this
is
>>>>> caused by the Amplify.js library provided by AWS, which is the one
we're
>>>>> using to implement the SRP flow). Yes, the error is returned from
Cognito
>>>>> when Keycloak contacts the provider to validate the token.
>>>>>
>>>>
>>>>>
>>>>>
>>>>>>
>>>>>>
>>>>>>> - Since the SRP flow enables us to use a self-hosted login
page
>>>>>>> which doesn't send the password directly to the server,
we've tried to find
>>>>>>> other solution. So we've tried to provide to the token
exchange endpoint
>>>>>>> the id token, changing some parameters of the HTTP call. And
at this point
>>>>>>> something unexpected for us happened: the token exchange
process works also
>>>>>>> providing the id token. Here's the reason of my first
flow of questions: is
>>>>>>> this behaviour expected? Is the "exchange with id
token" approach a
>>>>>>> feasible and good one? Or is completely a bad approach?
>>>>>>>
>>>>>>> - Since using this flow (SRP) force us to provide the id
token to
>>>>>>> our backend side, here comes the other flow of questions :).
From an OIDC
>>>>>>> point of view, can be a right approach accessing a backend
resource from a
>>>>>>> single page application, using an id token? I've always
read that if you
>>>>>>> want to access to a backend resource, from a client
application, is better
>>>>>>> to use the access token, because the id token contains a lot
of user
>>>>>>> informations and must be used only by the client
application.
>>>>>>>
>>>>>>>
>>>>>> It is fine to use id_token (or any other format supported by the
>>>>>> server that can be specified via subject_token_type) when doing
the
>>>>>> exchange.
>>>>>>
>>>>>> However, here is the interesting part. If you look our
documentation
>>>>>> we should only support "access_token" and
"jwt" as a subject_token_type.
>>>>>> But the implementation can also handle "id_token". The
reason why
>>>>>> "id_token" works is that the validation of the token is
done locally by
>>>>>> Keycloak, differently than when you are using an access_token
where a
>>>>>> request will be sent to the user info endpoint on Cognito.
>>>>>>
>>>>>
>>>>> Oh! That's really interesting! :)
>>>>> About this point, in your opinion it will be feasible to call the
>>>>> token exchange endpoint every time a request comes to our backend
side?
>>>>> Imagine this scenario:
>>>>>
>>>>> - User authenticates to Cognito via the Spa app
>>>>> - Spa app calls backend services (tipically contacting a gateway)
>>>>> - Gateway performs the token exchange on keycloak
>>>>> - Gateway forwards the request (adding the new access token in place
>>>>> of the Cognito one) to the underlying microservices...
>>>>>
>>>>> Do you see any performance issues? Does Keycloak caches something
>>>>> during the token exchange process?
>>>>>
>>>>
>>>> I would ask you to try it out and check latency and response times.
>>>> Unfortunately, benchmarking is something we are lacking so we depend on
>>>> feedback from the community.
>>>>
>>>
>>>> Maybe, another option you could consider is to aggregate your APIs so
>>>> that your SPA doesn't need to interact with multiple backend
services
>>>> ? Where this API aggregator would be 1:1 mapped to your client and
>>>> responsible for all exchanges to access downstream services.
>>>>
>>>
>>> So the main idea is to put a gateway in front of all the microservices,
>>> so it will be the one who performs the token exchange process. To avoid
>>> performance issues we can think about a caching mechanism but in this way
>>> we need to investigate more (we're just evaluating the various options
>>> right now ;) ). By the way, IMHO, if a user calls the gateway 300 times in
>>> 3 minutes there's no reason to perform the token exchange process at
every
>>> call.
>>>
>>>
>>>
>>>>
>>>> Or you could eventually use different scopes to gain access to these
>>>> different services and still use the same token obtained by the client
>>>> during the authentication. There is a caveat here regarding audience
>>>> though, so you could maybe include some audience that logically
represent
>>>> your different APIs.
>>>>
>>>
>>> So, if i understood correctly:
>>> - Client contacts gateway with a Cognito access token
>>> - Gateway performs the token exchange process
>>> - Depending on which service needs to be called, the gateway requests
>>> scopes to Keycloak with the access token minted by Keycloak. Is this right?
>>> Or requesting scopes is done in the token exchange process?
>>>
>>> So i've some concepts regarding scopes that i read around on the
>>> Internet, and for what i've understood, a scope represents what an
oauth2
>>> client can do:
>>> - You need to call service A, perform a read operation
>>> - You request the custom scope read_service_a
>>>
>>> I'm lacking the link between those scopes and the authorization part.
>>> How are they linked with the authorization services in Keycloak? If a user
>>> isn't authorized to do something, will never receive the related scope?
Or
>>> are they completely separated concepts?
>>>
>>
>> There is no link between the two. I was considering a regular OAuth2
>> authorization where you would rely on the scopes granted by the server. I
>> think I missed the authorization services part in your first message :)
>>
>
> Ah ok. We are planning to store the authorization data into keycloak
> (something like user X has the permission to access to resource Y and to
> perform on it the action Z) in order to have this kind of information
> inside the access token minted by Keycloak during the exchange process.
> Once the resource server gets the token it will authorize or not the
> access. Do you think this could be the right way? It could be feasible, in
> your opinion?
>
>
>
>
>
>>
>>
>>>
>>> The audience part is fine for me, also here for what i've understood,
>>> the audience represents the "target" resource protected by the
server. Am i
>>> right?
>>>
>>
>> Yes.
>>
>>
>>>
>>>
>>>>
>>>>>
>>>>>
>>>>>>
>>>>>> Regarding your last question, no it is not a good practice to
use
>>>>>> id_token for bearer token authorization. In addition to privacy
concerns
>>>>>> (which is not really different than when using JWTs in access
tokens), ID
>>>>>> Token is about carrying the authentication context with specific
>>>>>> constraints. For instance, the audience is the client, not the
backend. The
>>>>>> lifetime of ID Token is shorter as they are mainly important to
>>>>>> authenticate the user into a client, etc.
>>>>>>
>>>>>> So, you are right. You should try to use access tokens.
>>>>>>
>>>>>
>>>>> Ok thank you for the explanation. We'll try to use access tokens
>>>>> (probably we'll stop using the SRP flow in favour of an OAuth2
flow like
>>>>> Authorization Code Grant with PKCE (which is the one recommended for
public
>>>>> Single page Applications)
>>>>>
>>>>
>>>> +1
>>>>
>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>
>>>>>>
>>>>>>> - Here's the curl of the token exchange process with the
access
>>>>>>> token (i'm omitting some infos):
>>>>>>>
>>>>>>> curl -X POST \
>>>>>>> -d "client_id=test" \
>>>>>>> -d "client_secret=<client_secret>" \
>>>>>>> --data-urlencode
>>>>>>>
"grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
>>>>>>> -d
"subject_issuer=<alias_of_the_identity_provider_in_keycloak>" \
>>>>>>> -d "subject_token=<access_token>" \
>>>>>>> --data-urlencode
>>>>>>>
"subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
>>>>>>> -d "audience=test" \
>>>>>>>
http://localhost:8080/auth/realms/
>>>>>>> <realm_name>/protocol/openid-connect/token
>>>>>>>
>>>>>>>
>>>>>>> - Here's the curl of the token exchange process with the
id token
>>>>>>> (i'm omitting some infos):
>>>>>>>
>>>>>>> curl -X POST \
>>>>>>> -d "client_id=test" \
>>>>>>> -d "client_secret=<client_secret>" \
>>>>>>> --data-urlencode
>>>>>>>
"grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
>>>>>>> -d
"subject_issuer=<alias_of_the_identity_provider_in_keycloak>" \
>>>>>>> -d "subject_token=<id_token>" \
>>>>>>> --data-urlencode
>>>>>>>
"subject_token_type=urn:ietf:params:oauth:token-type:id_token" \
>>>>>>> -d "audience=test" \
>>>>>>>
http://localhost:8080/auth/realms/
>>>>>>> <realm_name>/protocol/openid-connect/token
>>>>>>>
>>>>>>> Let me know if you need more infos.
>>>>>>>
>>>>>>> Thank you again,
>>>>>>> Matteo Restelli
>>>>>>>
>>>>>>> On Wed, Apr 10, 2019 at 3:40 PM Pedro Igor Silva
<psilva(a)redhat.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> So you are doing external to internal exchange. It is not
clear to
>>>>>>>> me how you configured AWS Cognito as an identity provider
and what/how the
>>>>>>>> SRP flow works. Could you provide more details, please?
Is the token issued
>>>>>>>> by Cognito a JWT ?
>>>>>>>>
>>>>>>>> In addition to that, how your token exchange request
looks like
>>>>>>>> when using both id_token and access_token as a
subject_token ?
>>>>>>>>
>>>>>>>> On Wed, Apr 10, 2019 at 9:56 AM Matteo Restelli <
>>>>>>>> mrestelli(a)cuebiq.com> wrote:
>>>>>>>>
>>>>>>>>> Any news on that?
>>>>>>>>>
>>>>>>>>> Thank you!
>>>>>>>>> Matteo
>>>>>>>>>
>>>>>>>>> =============================
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Hi all,
>>>>>>>>> We're using AWS Cognito as our Identity provider
for our
>>>>>>>>> platform. We're
>>>>>>>>> trying to use an internal instance of Keycloak, in
order to check
>>>>>>>>> the
>>>>>>>>> possibility to use KC for authorization purposes
(this because
>>>>>>>>> Keycloak has
>>>>>>>>> a wonderful and powerful authorization system that
fulfill our
>>>>>>>>> needs, and
>>>>>>>>> for that i want to say you "Thank you very
much" :) ). For this
>>>>>>>>> reason we
>>>>>>>>> want to use the token exchange feature of Keycloak.
>>>>>>>>> More specifically we want to follow this flow:
>>>>>>>>>
>>>>>>>>> - User authenticates on AWS Cognito via SRP auth flow
(which
>>>>>>>>> basically is
>>>>>>>>> not a standard OIDC/OAuth2 authentication flow)
>>>>>>>>> - User sends the access token to contact the backend
service and,
>>>>>>>>> in the
>>>>>>>>> middle, this token is translated to an internal one,
minted by
>>>>>>>>> Keycloak
>>>>>>>>>
>>>>>>>>> If we provide the AWS Cognito access token to the
token exchange
>>>>>>>>> endpoint,
>>>>>>>>> with the subject_token_type parameter set to
>>>>>>>>>
"urn:ietf:params:oauth:token-type:access_token", an error is
>>>>>>>>> returned
>>>>>>>>> stating that the access token doesn't contain the
"openid" scope.
>>>>>>>>> Despite
>>>>>>>>> this we've tried another way, providing the id
token to the token
>>>>>>>>> exchange
>>>>>>>>> endpoint with the subject_token_parameter set to
>>>>>>>>>
"urn:ietf:params:oauth:token-type:id_token", and we discovered
>>>>>>>>> that this
>>>>>>>>> alternative way works. So, my questions are:
>>>>>>>>>
>>>>>>>>> - Is the "exchange with id token" approach
a feasible and good
>>>>>>>>> one? Or is
>>>>>>>>> completely a bad approach?
>>>>>>>>> - From an OIDC point of view, can be a right approach
accessing a
>>>>>>>>> backend
>>>>>>>>> resource from a single page application, using an id
token? I've
>>>>>>>>> always
>>>>>>>>> read that if you want to access to a backend
resource, from a
>>>>>>>>> client
>>>>>>>>> application, is better to use the access token,
because the id
>>>>>>>>> token
>>>>>>>>> contains a lot of user informations and must be used
only by the
>>>>>>>>> client
>>>>>>>>> application
>>>>>>>>>
>>>>>>>>> Thank you very much,
>>>>>>>>> Matteo
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> PS: As a side note, i want to clarify that if we
follow an
>>>>>>>>> authorization
>>>>>>>>> code grant flow, or an implicit flow, during the
authentication
>>>>>>>>> against AWS
>>>>>>>>> Cognito, the access token exchange works as expected.
So this
>>>>>>>>> means that
>>>>>>>>> the problem is related to the shape of the token
released by
>>>>>>>>> Cognito.
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>>
>>>>>>>>> Like <
https://www.facebook.com/cuebiq/> I
Follow
>>>>>>>>> <
https://twitter.com/Cuebiq>I Connect
>>>>>>>>> <
https://www.linkedin.com/company/cuebiq>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> This email is reserved
>>>>>>>>> exclusively for sending and receiving messages
inherent working
>>>>>>>>> activities,
>>>>>>>>> and is not intended nor authorized for personal use.
Therefore,
>>>>>>>>> any
>>>>>>>>> outgoing messages or incoming response messages will
be treated
>>>>>>>>> as company
>>>>>>>>> messages and will be subject to the corporate IT
policy and may
>>>>>>>>> possibly to
>>>>>>>>> be read by persons other than by the subscriber of
the box.
>>>>>>>>> Confidential
>>>>>>>>> information may be contained in this message. If you
are not the
>>>>>>>>> address
>>>>>>>>> indicated in this message, please do not copy or
deliver this
>>>>>>>>> message to
>>>>>>>>> anyone. In such case, you should notify the sender
immediately
>>>>>>>>> and delete
>>>>>>>>> the original message.
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>>
>>>>>>>>> Like <
https://www.facebook.com/cuebiq/> I
Follow
>>>>>>>>> <
https://twitter.com/Cuebiq>I Connect
>>>>>>>>> <
https://www.linkedin.com/company/cuebiq>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> This email is reserved
>>>>>>>>> exclusively for sending and receiving messages
inherent working
>>>>>>>>> activities,
>>>>>>>>> and is not intended nor authorized for personal use.
Therefore,
>>>>>>>>> any
>>>>>>>>> outgoing messages or incoming response messages will
be treated
>>>>>>>>> as company
>>>>>>>>> messages and will be subject to the corporate IT
policy and may
>>>>>>>>> possibly to
>>>>>>>>> be read by persons other than by the subscriber of
the box.
>>>>>>>>> Confidential
>>>>>>>>> information may be contained in this message. If you
are not the
>>>>>>>>> address
>>>>>>>>> indicated in this message, please do not copy or
deliver this
>>>>>>>>> message to
>>>>>>>>> anyone. In such case, you should notify the sender
immediately
>>>>>>>>> and delete
>>>>>>>>> the original message.
>>>>>>>>> _______________________________________________
>>>>>>>>> keycloak-user mailing list
>>>>>>>>> keycloak-user(a)lists.jboss.org
>>>>>>>>>
https://lists.jboss.org/mailman/listinfo/keycloak-user
>>>>>>>>>
>>>>>>>>
>>>>>>> Like <
https://www.facebook.com/cuebiq/> I Follow
>>>>>>> <
https://twitter.com/Cuebiq>I Connect
>>>>>>> <
https://www.linkedin.com/company/cuebiq>
>>>>>>>
>>>>>>> This email is reserved exclusively for sending and receiving
>>>>>>> messages inherent working activities, and is not intended nor
authorized
>>>>>>> for personal use. Therefore, any outgoing messages or
incoming response
>>>>>>> messages will be treated as company messages and will be
subject to the
>>>>>>> corporate IT policy and may possibly to be read by persons
other than by
>>>>>>> the subscriber of the box. Confidential information may be
contained in
>>>>>>> this message. If you are not the address indicated in this
message, please
>>>>>>> do not copy or deliver this message to anyone. In such case,
you should
>>>>>>> notify the sender immediately and delete the original
message.
>>>>>>>
>>>>>>
>>>>> Like <
https://www.facebook.com/cuebiq/> I Follow
>>>>> <
https://twitter.com/Cuebiq>I Connect
>>>>> <
https://www.linkedin.com/company/cuebiq>
>>>>>
>>>>> This email is reserved exclusively for sending and receiving
messages
>>>>> inherent working activities, and is not intended nor authorized for
>>>>> personal use. Therefore, any outgoing messages or incoming response
>>>>> messages will be treated as company messages and will be subject to
the
>>>>> corporate IT policy and may possibly to be read by persons other than
by
>>>>> the subscriber of the box. Confidential information may be contained
in
>>>>> this message. If you are not the address indicated in this message,
please
>>>>> do not copy or deliver this message to anyone. In such case, you
should
>>>>> notify the sender immediately and delete the original message.
>>>>>
>>>>
>>> Like <
https://www.facebook.com/cuebiq/> I Follow
>>> <
https://twitter.com/Cuebiq>I Connect
>>> <
https://www.linkedin.com/company/cuebiq>
>>>
>>> This email is reserved exclusively for sending and receiving messages
>>> inherent working activities, and is not intended nor authorized for
>>> personal use. Therefore, any outgoing messages or incoming response
>>> messages will be treated as company messages and will be subject to the
>>> corporate IT policy and may possibly to be read by persons other than by
>>> the subscriber of the box. Confidential information may be contained in
>>> this message. If you are not the address indicated in this message, please
>>> do not copy or deliver this message to anyone. In such case, you should
>>> notify the sender immediately and delete the original message.
>>>
>>
> Like <
https://www.facebook.com/cuebiq/> I Follow
> <
https://twitter.com/Cuebiq>I Connect
> <
https://www.linkedin.com/company/cuebiq>
>
> This email is reserved exclusively for sending and receiving messages
> inherent working activities, and is not intended nor authorized for
> personal use. Therefore, any outgoing messages or incoming response
> messages will be treated as company messages and will be subject to the
> corporate IT policy and may possibly to be read by persons other than by
> the subscriber of the box. Confidential information may be contained in
> this message. If you are not the address indicated in this message, please
> do not copy or deliver this message to anyone. In such case, you should
> notify the sender immediately and delete the original message.
>
This email is reserved
exclusively for sending and receiving messages inherent working activities,
and is not intended nor authorized for personal use. Therefore, any
outgoing messages or incoming response messages will be treated as company
messages and will be subject to the corporate IT policy and may possibly to
be read by persons other than by the subscriber of the box. Confidential
information may be contained in this message. If you are not the address
indicated in this message, please do not copy or deliver this message to
anyone. In such case, you should notify the sender immediately and delete
the original message.