MCP requirement - Audience Mapper and Checker referring RFC 8707 resource parameter#45739
MCP requirement - Audience Mapper and Checker referring RFC 8707 resource parameter#45739tnorimat wants to merge 1 commit intokeycloak:mainfrom
Conversation
631ce01 to
ade1cb3
Compare
|
Thanks for picking this up again. I see that you are using a protocol mapper to restrict the allowed resource indicator uris. I used the same approach in my initial PR, but this was declined back then as restricting values for a protocol flow via mapper was uncommon back then. That's why I went with the more sophisticated approach that introduced a SPI to restrict allowed resource indicators backed by authorization services to allow users to define resources. Perhaps opinions changed in-between :) I think using a protocol mapper to declare a static list of allowed resource indicator uris per client has its limits but might still be expressive enough to solve common scenarios. |
|
@thomasdarimont Hello, thank you for the comments. I missed the point. |
28ef4e1 to
0d7456b
Compare
|
@stianst Hello, the feature is also important the same as CIMD to comply with MCP spec even if there is the workaround using client scope. Coud anyone in your team check the PR? |
cgeorgilakis
left a comment
There was a problem hiding this comment.
Nice work for a needed feature.
See my comments for proposed changes.
|
|
||
| public static final String PROVIDER_ID = "oidc-resource-indicator-mapper"; | ||
|
|
||
| private static final List<ProviderConfigProperty> configProperties = new ArrayList<>(); |
There was a problem hiding this comment.
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.
I propose to add an optional default value for aud claim (defaultAud) . Default value will be null.
If resource is empty and defaultAud is not empty, mapper will add this default value to aud claim.
In this way Keycloak will respect the JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens for aud claim.
|
|
||
| String acr; | ||
|
|
||
| String resource; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| String resourceParam = authzRequestContext.getAuthorizationEndpointRequest().getResource(); | ||
| logger.debugv(" on authz request: resourceParam = {0}", resourceParam); | ||
| List<String> allowResourceList = convertContentFilledList(configuration.getAllowPermittedResources()); | ||
| if (allowResourceList != null && !allowResourceList.isEmpty()) { |
There was a problem hiding this comment.
Combine two if in one if for better performance and clearance.
There was a problem hiding this comment.
I modified the codes as follows:
if (allowResourceList != null && !allowResourceList.isEmpty() && !allowResourceList.contains(resourceParam)) {
logger.warnv("not allowed resource parameter value: resource = {0}", resourceParam);
throw new ClientPolicyException(OAuthErrorException.INVALID_REQUEST, ERR_NOT_PERMITTED_RESOURCE);
}
|
@cgeorgilakis Hello, thank you for the comment. I will check them. |
ece170c to
8652ad0
Compare
stianst
left a comment
There was a problem hiding this comment.
Could you provide an overview on how this should be used? Is it basically just mapping a known resource into the token? Not sure if that makes all that much sense to me.
I haven't had time to look at this in more detail sorry, but hope to take a look next week.
|
@stianst Hello, The PR's resource parameter support should be used as follows: The same thing can be done by client scope + audience mapper, but it does not work if several resource servers support the same name of scope. It consists of two parts: mapper and executor. The mapper has a single role: putting The executor has two roles:
From security perspective, both should be applied. If not, any Comparison of RFC 8707 specification and the spec of the PR is as follows:
|
8652ad0 to
ab5c41d
Compare
There was a problem hiding this comment.
Pull request overview
This pull request implements support for RFC 8707 Resource Indicators to meet MCP (Model Context Protocol) specification requirements. The implementation adds the ability to include a resource parameter in OAuth2 authorization and token requests, which gets mapped to the aud (audience) claim in access tokens.
Changes:
- Introduces a new experimental feature flag
RESOURCE_INDICATORfor RFC 8707 support - Adds
ResourceIndicatorMapperprotocol mapper to bind resource parameter values to access token audience claims - Adds
SecureResourceIndicatorExecutorclient policy executor to validate resource parameter values across authorization and token requests
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| common/src/main/java/org/keycloak/common/Profile.java | Adds RESOURCE_INDICATOR experimental feature flag |
| services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java | Defines RESOURCE_PARAM constant for RFC 8707 |
| services/src/main/java/org/keycloak/protocol/oidc/mappers/ResourceIndicatorMapper.java | New protocol mapper that adds resource parameter to access token audience |
| services/src/main/java/org/keycloak/services/clientpolicy/executor/SecureResourceIndicatorExecutor.java | New executor that validates resource parameters in authorization and token requests |
| services/src/main/java/org/keycloak/services/clientpolicy/executor/SecureResourceIndicatorExecutorFactory.java | Factory for SecureResourceIndicatorExecutor |
| services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequest.java | Adds resource field to authorization request model |
| services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java | Parses resource parameter from authorization requests |
| services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java | Propagates resource parameter through authorization flow |
| services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java | Manages resource parameter in client session notes |
| services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper | Registers ResourceIndicatorMapper |
| services/src/main/resources/META-INF/services/org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProviderFactory | Registers SecureResourceIndicatorExecutorFactory |
| tests/base/src/test/java/org/keycloak/tests/oauth/ResourceIndicatorMapperTest.java | Comprehensive test coverage for resource indicator functionality |
| tests/utils-shared/src/main/java/org/keycloak/testsuite/util/oauth/LoginUrlBuilder.java | Adds resource parameter support to login URL builder |
| tests/utils-shared/src/main/java/org/keycloak/testsuite/util/oauth/AccessTokenRequest.java | Adds resource parameter support to access token requests |
| tests/utils-shared/src/main/java/org/keycloak/testsuite/util/oauth/RefreshRequest.java | Adds resource parameter support to refresh token requests |
| testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientPoliciesUtil.java | Adds utility method for creating resource executor config |
| tests/utils-shared/src/main/java/org/keycloak/testsuite/util/ClientPoliciesUtil.java | New utilities file with complete client policy helper methods |
ab5c41d to
db1d68d
Compare
I'm not really following TBH; so to use this I have to:
Also, if I don't do 2, then a client can get any resource into the aud claim of the token? |
|
@stianst Yes, so make it secure, applying the executor is needed. |
1ed0a20 to
18ddfea
Compare
…urce parameter closes keycloak#41527 Signed-off-by: Takashi Norimatsu <[email protected]>
18ddfea to
01f98d3
Compare
|
Closing this since we now have experimental support for resource indicators through audience filtering: #46763 |
closes #41527
The PR's code size is large, but half of them are for testing.
Class structure
ResourceIndicatorMapper: adds the value ofresourceparameter in an authorization request to an access token's "aud" claim.SecureResourceIndicatorExecutor/SecureResourceIndicatorExecutorFactory: checks ifresourceparameter value in an authorization request and token request are valid. If not, returns an error.The way of adding
resourceparameter value to an access token'saudclaimAuthorizationEndpoint.updateAuthenticationSessionstores theresourceparameter value in an authorization request to anAuthenticationSession.TokenManager.attachAuthenticationSessioncopies theresourceparameter value of theAuthenticationSessiontoAuthenticatedClientSession.ResourceIndicatorMapperandSecureResourceIndicatorExecutorcan see it fromAuthenticatedClientSession.getNote.