Skip to content

resource request parameter and audience in access token#13622

Closed
cgeorgilakis wants to merge 1 commit intokeycloak:mainfrom
eosc-kc:RCIAM-1061-request-aud
Closed

resource request parameter and audience in access token#13622
cgeorgilakis wants to merge 1 commit intokeycloak:mainfrom
eosc-kc:RCIAM-1061-request-aud

Conversation

@cgeorgilakis
Copy link
Copy Markdown
Contributor

Closes #13614

Tests for (postgres) undertow-map-jpa are failed. I can not understand why. Could you help me? What am I missing for these tests?

Copy link
Copy Markdown
Contributor

@sguilhen sguilhen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that the changes in the MapExportImportManager are not checking if the representation value is null before setting them, and defaultAudValueForAccessToken with null values are stored in the DB.

Later on, when the realm entity is converted into representation, the MapRealmAdapter.getAttributes() method collects the stored attributes into a Map and hits a NPE because the value mapper function is resulting in null.

Adding a null check in the MapExportImportManager should be enough to prevent this from happening.

@sguilhen
Copy link
Copy Markdown
Contributor

sguilhen commented Aug 8, 2022

I've also opened #13658 to revisit the MapRealmAdapter and change the value mapper function there, but for the moment it is important that all code that can set an attribute in an entity checks for null values before adding the attribute.

@sguilhen sguilhen requested a review from mposolda August 8, 2022 21:07
@cgeorgilakis cgeorgilakis force-pushed the RCIAM-1061-request-aud branch from 9530662 to 1dde269 Compare August 9, 2022 08:19
@cgeorgilakis
Copy link
Copy Markdown
Contributor Author

cgeorgilakis commented Aug 9, 2022

@sguilhen Thanks for your help. I have corrected it.

Moreover, I create related keycloak-admin-ui PR for changes in new Admin Console.

@cgeorgilakis cgeorgilakis requested a review from sguilhen August 9, 2022 09:46
@sguilhen
Copy link
Copy Markdown
Contributor

Glad it worked, @cgeorgilakis ! As for the thorough review I'll leave it to @mposolda to do it or assign someone to take a look.

@jonkoops
Copy link
Copy Markdown
Contributor

Can we get someone assigned to this so we can get this work merged? We have a related PR on the UI side that we'd like to get in after this.

cc @sguilhen @mposolda

Copy link
Copy Markdown
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cgeorgilakis Sorry for the late review.

Instead of adding new 1st level switch at the realm level and changing the core code, I suggest to introduce new "protocol mapper" implementation. For example Resource To Audience Mapper (or better name if you have an idea).

The resource parameter can be added as a client note to AuthenticationSessionModel (in authorization grant) and/or to AuthenticatedClientSessionModel (in some other grants). For example see:

Protocol mapper can then consume it from client session note and add to the aud . The default audience can be added as configuration option of the protocol mapper, but I suggest to add just if you need it for your own use-case.

The validation can be also done by protocol mapper itself and moved directly to protocol mapper.

For the tests, you can add some client scope and add your protocol mapper as protocol mapper to it (and possibly remove other client scopes, which are already adding audience by default).

This approach won't require too much changes in the core codebase (besides adding resource to the session note) and will allow to more flexibility as the resource parameter will be possible to consume by other places (For example someone may want to add his own protocol mapper, which will do the same like yours, but with some additional validations on top of it).

Also it won't change default behaviour - as I think that it is not correct that by default, the content of resource is added to the aud (it is possibly fine just for some deployments and those can add protocol mapper to their client scopes on demand)

Is it possible to update PR for this approach?

// This cannot be moved higher because it acts on differently based on environment (e.g. sometimes it checks
// scheme, sometimes it doesn't).
if (requireValidUrl) {
URL ignored = uri.toURL(); // throws an exception
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: For validation, you can just call uri.toURL() without creating any variable?

@mposolda mposolda self-assigned this Nov 23, 2022
@cgeorgilakis
Copy link
Copy Markdown
Contributor Author

cgeorgilakis commented Nov 28, 2022

@cgeorgilakis Sorry for the late review.

Instead of adding new 1st level switch at the realm level and changing the core code, I suggest to introduce new "protocol mapper" implementation. For example Resource To Audience Mapper (or better name if you have an idea).

The resource parameter can be added as a client note to AuthenticationSessionModel (in authorization grant) and/or to AuthenticatedClientSessionModel (in some other grants). For example see:

Protocol mapper can then consume it from client session note and add to the aud . The default audience can be added as configuration option of the protocol mapper, but I suggest to add just if you need it for your own use-case.

The validation can be also done by protocol mapper itself and moved directly to protocol mapper.

For the tests, you can add some client scope and add your protocol mapper as protocol mapper to it (and possibly remove other client scopes, which are already adding audience by default).

This approach won't require too much changes in the core codebase (besides adding resource to the session note) and will allow to more flexibility as the resource parameter will be possible to consume by other places (For example someone may want to add his own protocol mapper, which will do the same like yours, but with some additional validations on top of it).

Also it won't change default behaviour - as I think that it is not correct that by default, the content of resource is added to the aud (it is possibly fine just for some deployments and those can add protocol mapper to their client scopes on demand)

Is it possible to update PR for this approach?

Our goal is Keycloak be compliant to OAuth specifications together with the need not to need any migration.

From JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens :

aud REQUIRED - as defined in Section 4.1.3 of [RFC7519]. See
Section 3 for indications on how an authorization server should
determine the value of "aud" depending on the request.
If the request does not include a "resource" parameter, the
authorization server MUST use a default resource indicator in the
"aud" claim. If a "scope" parameter is present in the request, the
authorization server SHOULD use it to infer the value of the default
resource indicator to be used in the "aud" claim.

As you can see aud is required. A default value is needed if not requested. We make it default empty if someone does not want it and for keep Keycloak behaviour same as old versions.

From Resource Indicators for OAuth 2.0 :

resource
Indicates the target service or resource to which access is being
requested. Its value MUST be an absolute URI, as specified by
Section 4.3 of [RFC3986]. The URI MUST NOT include a fragment
component.
The following error code is provided for an authorization server to
indicate problems with the requested resource(s) in response to an
authorization request or access token request. It can also be used
to inform the client that it has requested an invalid combination of
resource and scope.
invalid_target
The requested resource is invalid, missing, unknown, or malformed.
The authorization server SHOULD audience-restrict issued access
tokens to the resource(s) indicated by the "resource" parameter.
Audience restrictions can be communicated in JSON Web Tokens
[RFC7519] with the "aud" claim and the top-level member of the same
name provides the audience restriction information in a Token
Introspection [RFC7662] response. The authorization server may use
the exact "resource" value as the audience or it may map from that
value to a more general URI or abstract identifier for the given
resource.

So validation for resource parameter must be, Use "resource" value for the audience should be done (you must have good reason for not doing it). We use 'exact "resource" value as the audience'. We could discuss enhancement. I believe that proposed new protocol mapper make things more complex, need lots of code changes and need a default 'Include In Token Scope' value equal to false Client Scope ( user must not see an extra scope for this). If someone does not want 'resource' as desribed in the Resource Indicators for OAuth 2.0, he must not use this request parameter. Keycloak now omit 'resource' request parameter

@cgeorgilakis cgeorgilakis requested review from mposolda and removed request for sguilhen November 28, 2022 08:09
@mposolda
Copy link
Copy Markdown
Contributor

mposolda commented Dec 2, 2022

@cgeorgilakis Sorry for the late review.
Instead of adding new 1st level switch at the realm level and changing the core code, I suggest to introduce new "protocol mapper" implementation. For example Resource To Audience Mapper (or better name if you have an idea).
The resource parameter can be added as a client note to AuthenticationSessionModel (in authorization grant) and/or to AuthenticatedClientSessionModel (in some other grants). For example see:

Protocol mapper can then consume it from client session note and add to the aud . The default audience can be added as configuration option of the protocol mapper, but I suggest to add just if you need it for your own use-case.
The validation can be also done by protocol mapper itself and moved directly to protocol mapper.
For the tests, you can add some client scope and add your protocol mapper as protocol mapper to it (and possibly remove other client scopes, which are already adding audience by default).
This approach won't require too much changes in the core codebase (besides adding resource to the session note) and will allow to more flexibility as the resource parameter will be possible to consume by other places (For example someone may want to add his own protocol mapper, which will do the same like yours, but with some additional validations on top of it).
Also it won't change default behaviour - as I think that it is not correct that by default, the content of resource is added to the aud (it is possibly fine just for some deployments and those can add protocol mapper to their client scopes on demand)
Is it possible to update PR for this approach?

Our goal is Keycloak be compliant to OAuth specifications together with the need not to need any migration.

From JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens :

aud REQUIRED - as defined in Section 4.1.3 of [RFC7519]. See
Section 3 for indications on how an authorization server should
determine the value of "aud" depending on the request.
If the request does not include a "resource" parameter, the
authorization server MUST use a default resource indicator in the
"aud" claim. If a "scope" parameter is present in the request, the
authorization server SHOULD use it to infer the value of the default
resource indicator to be used in the "aud" claim.

As you can see aud is required. A default value is needed if not requested. We make it default empty if someone does not want it and for keep Keycloak behaviour same as old versions.

Keycloak already has some flexibility how is aud claim added to the access token. Details here: https://www.keycloak.org/docs/latest/server_admin/index.html#audience-support

But you're right that aud is required and hence should be added. I think that for handling empty audience, we can use existing AudienceResolveProtocolMapper, which is already present in the default client scope roles and hence automatically processed for each OIDC client by default.

From Resource Indicators for OAuth 2.0 :

resource
Indicates the target service or resource to which access is being
requested. Its value MUST be an absolute URI, as specified by
Section 4.3 of [RFC3986]. The URI MUST NOT include a fragment
component.
The following error code is provided for an authorization server to
indicate problems with the requested resource(s) in response to an
authorization request or access token request. It can also be used
to inform the client that it has requested an invalid combination of
resource and scope.
invalid_target
The requested resource is invalid, missing, unknown, or malformed.
The authorization server SHOULD audience-restrict issued access
tokens to the resource(s) indicated by the "resource" parameter.
Audience restrictions can be communicated in JSON Web Tokens
[RFC7519] with the "aud" claim and the top-level member of the same
name provides the audience restriction information in a Token
Introspection [RFC7662] response. The authorization server may use
the exact "resource" value as the audience or it may map from that
value to a more general URI or abstract identifier for the given
resource.

So validation for resource parameter must be, Use "resource" value for the audience should be done (you must have good reason for not doing it). We use 'exact "resource" value as the audience'. We could discuss enhancement. I believe that proposed new protocol mapper make things more complex, need lots of code changes and need a default 'Include In Token Scope' value equal to false Client Scope ( user must not see an extra scope for this). If someone does not want 'resource' as desribed in the Resource Indicators for OAuth 2.0, he must not use this request parameter. Keycloak now omit 'resource' request parameter

This specification does not imply that Keycloak should take resource parameter and automatically add all the values from it to the aud claim without any further verifications (I don't mean the basic validations for fragment and URI, which you added, but some more validations for check that user+client combination is allowed to request particular resource).

I don't know how exactly this check might be done. But as step 1, we can possibly stick to the behaviour you added (just add the resources to the audience without any further checks) as long as it is done by the protocol mapper. It definitely should not be the default behaviour as adding random audiences, which user added himself in the resource parameter, is not very secure way of handling this (even if it can be fine for your particular use-case)

In general, we are trying to rely on the protocol mappers and client policies in Keycloak to allow some flexibility. So we're rather moving away from hardcoding the behaviour for the token content in the TokenManager class and moving stuff from this class to be rather added by protocol mappers. Also we're trying to avoid adding realm-wide switches for the things like this.

@mposolda
Copy link
Copy Markdown
Contributor

@cgeorgilakis No further response, so I am closing this PR. I don't think that this issue should be addressed in a way as did in this PR. Feel free to re-open, but please consider to use the approach based on protocol mapper in that case (or suggest some other approach, which will allow to address this with some good flexibility, and won't change the default Keycloak behaviour regarding handling of audience)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support OAuth flow 'resource' parameter

4 participants