[java-idp-oidc] 02/02: JOIDC-201 - Support for OAuth 2.0 Demonstrating Proof of Possession (DPoP)
Henri Mikkonen
henri.mikkonen at iki.fi
Mon Oct 21 16:05:09 UTC 2024
This is an automated email from the git hooks/post-receive script.
hjmikkon pushed a commit to branch main
in repository java-idp-oidc.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=2598960f5677ec126a92b049c5816d714caa7b8a
commit 2598960f5677ec126a92b049c5816d714caa7b8a
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Mon Oct 21 19:03:55 2024 +0300
JOIDC-201 - Support for OAuth 2.0 Demonstrating Proof of Possession (DPoP)
https://shibboleth.atlassian.net/browse/JOIDC-201
- Modified 'ValidateGrant' to populate DPoP proof thumbprint to context with client credentials grant
- Included 'ValidateGrant' to the client credentials flow
- Improved tests to cover DPoP issuance with the client credentials flow
- Add test to cover use of DPoP token as Bearer token
---
.../plugin/oidc/op/profile/impl/ValidateGrant.java | 6 ++++
.../shibboleth/idp/flows/oidc/token/token-flow.xml | 1 +
.../flow/ClientCredentialsTokenFlowTest.java | 32 +++++++++++++++++++++-
.../plugin/oidc/op/profile/flow/UserInfoTest.java | 19 +++++++++++++
4 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ValidateGrant.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ValidateGrant.java
index 5701b5aa..70f41ea0 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ValidateGrant.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ValidateGrant.java
@@ -383,6 +383,12 @@ public class ValidateGrant extends AbstractOIDCTokenResponseAction {
}
} else if (GrantType.CLIENT_CREDENTIALS.equals(grant.getType())) {
+ final String proofThumbprint = dpopProofThumbprintLookupStrategy.apply(profileRequestContext);
+ if (proofThumbprint != null) {
+ final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
+ assert oidcResponseContext != null;
+ oidcResponseContext.setDpopProofJwkThumbprint(proofThumbprint);
+ }
return;
}
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-flow.xml
index b899bb64..98e1d836 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-flow.xml
@@ -68,6 +68,7 @@
<!-- These steps apply to grants that are self-contained on this endpoint. -->
<action-state id="ClientCredentialsGrantProcessing">
+ <evaluate expression="ValidateGrant" />
<evaluate expression="SetAuthenticationContextClassReferenceToResponseContext" />
<evaluate expression="SetAuthenticationTimeToResponseContext" />
<evaluate expression="SetSubjectFromSubjectContextToResponseContext" />
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/ClientCredentialsTokenFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/ClientCredentialsTokenFlowTest.java
index fff13395..2459f13a 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/ClientCredentialsTokenFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/ClientCredentialsTokenFlowTest.java
@@ -46,6 +46,7 @@ import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEDecrypter;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.crypto.RSADecrypter;
+import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jwt.EncryptedJWT;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
@@ -355,7 +356,36 @@ public class ClientCredentialsTokenFlowTest extends AbstractOidcClientAuthentica
verifyClaims("JWT", response.getTokens().getBearerAccessToken(), clientIdSaml, scope,
Collections.singletonList(resourceSaml), "customEmailName", "eduPersonScopedAffiliation");
}
-
+
+ @Test
+ public void testSamlDPoP() throws Exception {
+ setHttpFormRequest("POST", createRequestParameters(clientIdSaml, scope, resourceSaml));
+ setBasicAuth(clientIdSaml, clientSecretSaml);
+ final ECKey dpopProofKey = defaultDPoPProofKey();
+ final SignedJWT dpopProof = buildDPoPProof(dpopProofKey, JWSAlgorithm.ES256, request.getMethod(),
+ "http://localhost/idp/profile/oidc/token", null, createValidDPoPNonce(clientIdSaml));
+ request.addHeader("DPoP", dpopProof.serialize());
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ final AccessTokenResponse response = parseSuccessResponse(result, AccessTokenResponse.class);
+ Assert.assertNotNull(response.getTokens().getDPoPAccessToken());
+ Assert.assertEquals(response.getTokens().getDPoPAccessToken().getLifetime(), 600);
+ Assert.assertEquals(response.getTokens().getDPoPAccessToken().getScope(), scope);
+ verifyClaims("JWT", response.getTokens().getDPoPAccessToken(), clientIdSaml, scope,
+ Collections.singletonList(resourceSaml), "customEmailName", "eduPersonScopedAffiliation");
+ }
+
+ @Test
+ public void testSamlDPoP_noMandatoryNonce() throws Exception {
+ setHttpFormRequest("POST", createRequestParameters(clientIdSaml, scope, resourceSaml));
+ setBasicAuth(clientIdSaml, clientSecretSaml);
+ final ECKey dpopProofKey = defaultDPoPProofKey();
+ final SignedJWT dpopProof = buildDPoPProof(dpopProofKey, JWSAlgorithm.ES256, request.getMethod(),
+ "http://localhost/idp/profile/oidc/token", null, null);
+ request.addHeader("DPoP", dpopProof.serialize());
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertErrorCode(result, OAuth2Error.USE_DPOP_NONCE_CODE);
+ }
+
protected FlowExecutionResult launchWithJwtAuthentication(final JWTAuthentication authnMethod,
final JWSAlgorithm algorithm) throws Exception {
final String clientId = authnMethod.getClientID().getValue();
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/UserInfoTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/UserInfoTest.java
index de743304..ab976b4a 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/UserInfoTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/UserInfoTest.java
@@ -413,6 +413,25 @@ public class UserInfoTest extends AbstractOidcApiFlowTest {
Assert.assertNull(response.getUserInfoJWT());
}
+ @SuppressWarnings("null")
+ @Test
+ public void testFailWithBearerTokenWithDPoP() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
+ ComponentInitializationException, IOException, com.nimbusds.oauth2.sdk.ParseException, JOSEException {
+ final ECKey dpopProofKey = defaultDPoPProofKey();
+ final AccessTokenClaimsSet claims =
+ buildDPoPAccessTokenClaimsSet(dpopProofKey.computeThumbprint().toString());
+
+ final DPoPAccessToken token = new DPoPAccessToken(claims.serialize(getDataSealer()));
+ final SignedJWT dpopProof = buildDPoPProof(dpopProofKey, JWSAlgorithm.ES256, request.getMethod(),
+ "http://localhost/idp/profile/oidc/userinfo", token, createValidDPoPNonce(clientId));
+ request.addHeader("DPoP", dpopProof.serialize());
+
+ storeMetadata(storageService, clientId, "mockSecret", scope);
+ request.addHeader("Authorization", getTokenHeaderValue(token).replace("DPoP ", "Bearer "));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertInvalidDPoPToken(result);
+ }
+
@Test
public void testFailWithBearerTokenWhenDPoPEnforced() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
ComponentInitializationException, IOException {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list