[java-idp-oidc] 03/04: JOIDC-201 - Support for OAuth 2.0 Demonstrating Proof of Possession (DPoP)
Henri Mikkonen
henri.mikkonen at iki.fi
Fri May 17 09:18:36 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=a4f3f645330fdf4005f364a66028d7c293db200f
commit a4f3f645330fdf4005f364a66028d7c293db200f
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri May 17 12:14:13 2024 +0300
JOIDC-201 - Support for OAuth 2.0 Demonstrating Proof of Possession (DPoP)
https://shibboleth.atlassian.net/browse/JOIDC-201
- Require valid access token hash claim in DPoP proof within the UserInfo endpoint
- user info flow test now covers the use of "ath"
- Included "dpop_signing_alg_values_supported" claim in the OP metadata skeleton
---
...oPAccessTokenHashFromRequestLookupFunction.java | 100 +++++++++++++++++++
.../idp/service/relying-party/postconfig.xml | 26 ++++-
.../oidc/op/static/openid-configuration.json | 8 ++
.../oidc/op/profile/flow/AbstractOidcFlowTest.java | 34 +++++--
.../plugin/oidc/op/profile/flow/UserInfoTest.java | 77 ++++++++++++++-
...cessTokenHashFromRequestLookupFunctionTest.java | 108 +++++++++++++++++++++
6 files changed, 342 insertions(+), 11 deletions(-)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DPoPAccessTokenHashFromRequestLookupFunction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DPoPAccessTokenHashFromRequestLookupFunction.java
new file mode 100644
index 00000000..aec6711c
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DPoPAccessTokenHashFromRequestLookupFunction.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.oidc.op.profile.logic;
+
+import java.util.Enumeration;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.util.Base64URL;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.dpop.DPoPUtils;
+import com.nimbusds.oauth2.sdk.token.DPoPAccessToken;
+
+import jakarta.servlet.http.HttpServletRequest;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * A function that calculates a hash of the DPoP access token from the {@link HttpServletRequest} if found.
+ *
+ * @since 4.2.0
+ */
+public class DPoPAccessTokenHashFromRequestLookupFunction extends AbstractIdentifiableInitializableComponent
+ implements Function<ProfileRequestContext, String> {
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(DPoPAccessTokenHashFromRequestLookupFunction.class);
+
+ /** Supplier for the {@link HttpServletRequest}. */
+ @NonnullAfterInit private Supplier<HttpServletRequest> httpServletRequestSupplier;
+
+ /**
+ * Set the supplier for the {@link HttpServletRequest}.
+ *
+ * @param strategy What to set.
+ */
+ public void setHttpServletRequestSupplier(final @Nonnull Supplier<HttpServletRequest> supplier) {
+ httpServletRequestSupplier = Constraint.isNotNull(supplier, "Http servlet request supplier cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+ if (httpServletRequestSupplier == null) {
+ throw new ComponentInitializationException("Http servlet request supplier cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable
+ public String apply(final @Nullable ProfileRequestContext input) {
+ checkComponentActive();
+ final HttpServletRequest httpServletRequest = httpServletRequestSupplier.get();
+ if (httpServletRequest == null) {
+ return null;
+ }
+ final Enumeration<String> authorizationHeaders = httpServletRequest.getHeaders("Authorization");
+ if (authorizationHeaders == null) {
+ return null;
+ }
+ while (authorizationHeaders.hasMoreElements()) {
+ try {
+ final DPoPAccessToken token = DPoPAccessToken.parse(authorizationHeaders.nextElement());
+ if (token != null) {
+ final Base64URL hash = DPoPUtils.computeSHA256(token);
+ if (hash != null) {
+ return hash.toString();
+ }
+ }
+ } catch (final ParseException e) {
+ // ignore, could not parse the DPoPAccessToken
+ } catch (final JOSEException e) {
+ log.warn("Could not compute SHA256 hash for the DPoP access token", e);
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
index 2e3faf09..03a5e6d5 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
@@ -27,7 +27,7 @@
p:deniedUserInfoAttributes="%{idp.oidc.deniedUserInfoAttributes:}"
p:issuedClaimsValidator-ref="DefaultUserInfoJWTClaimsValidator"
p:unregisteredClientPolicy="#{getObject('shibboleth.oidc.DefaultUnregisteredClientPolicy')}"
- p:dpopProofClaimsValidator-ref="DefaultDPoPProofClaimsValidator"
+ p:dpopProofClaimsValidator-ref="DefaultUserInfoDPoPProofClaimsValidator"
p:dpopProofSignatureValidationConfiguration-ref="DPoPSignatureValidationConfiguration" />
<bean id="OIDC.Registration" parent="AbstractOIDCProfile" lazy-init="true"
@@ -422,7 +422,7 @@
<property name="dpopProofClaimsValidatorLookupStrategy">
<bean parent="shibboleth.MDDrivenBeanProperty" p:propertyName="dpopProofClaimsValidator"
p:propertyType="#{T(net.shibboleth.oidc.jwt.claims.ClaimsValidator)}"
- p:defaultValue-ref="DefaultDPoPProofClaimsValidator" />
+ p:defaultValue-ref="DefaultUserInfoDPoPProofClaimsValidator" />
</property>
<property name="dpopProofSignatureValidationConfigurationLookupStrategy">
<bean parent="shibboleth.MDDrivenBeanProperty" p:propertyName="dpopProofSignatureValidationConfiguration"
@@ -1000,6 +1000,10 @@
class="net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator"
p:claimValidators-ref="DPoPProofClaimsValidators" />
+ <bean id="DefaultUserInfoDPoPProofClaimsValidator"
+ class="net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator"
+ p:claimValidators-ref="UserInfoDPoPProofClaimsValidators" />
+
<util:list id="DPoPProofClaimsValidators" value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator">
<ref bean="ExpiryClaimsValidator" />
<ref bean="NotBeforeClaimsValidator" />
@@ -1022,4 +1026,22 @@
</bean>
</util:list>
+ <bean id="UserInfoDPoPProofClaimsValidators" parent="DPoPProofClaimsValidators"
+ class="org.springframework.beans.factory.config.ListFactoryBean">
+ <property name="sourceList">
+ <list merge="true">
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ExactMatchClaimsValidator" p:claimName="ath">
+ <property name="valueToMatchLookupStrategy">
+ <bean parent="shibboleth.BiFunctions.Expression" c:expression="#custom.apply(null)">
+ <property name="customObject">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.profile.logic.DPoPAccessTokenHashFromRequestLookupFunction"
+ p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier"/>
+ </property>
+ </bean>
+ </property>
+ </bean>
+ </list>
+ </property>
+ </bean>
+
</beans>
diff --git a/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/static/openid-configuration.json b/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/static/openid-configuration.json
index 7276dbe2..d0270d5b 100644
--- a/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/static/openid-configuration.json
+++ b/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/static/openid-configuration.json
@@ -84,6 +84,14 @@
"ES384",
"ES512"
],
+ "dpop_signing_alg_values_supported":[
+ "RS256",
+ "RS384",
+ "RS512",
+ "ES256",
+ "ES384",
+ "ES512"
+ ],
"token_endpoint_auth_methods_supported":[
"client_secret_basic",
"client_secret_post",
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcFlowTest.java
index ae0d9885..a290d890 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcFlowTest.java
@@ -84,6 +84,7 @@ import com.nimbusds.oauth2.sdk.auth.Secret;
import com.nimbusds.oauth2.sdk.dpop.DPoPProofFactory;
import com.nimbusds.oauth2.sdk.dpop.DefaultDPoPProofFactory;
import com.nimbusds.oauth2.sdk.id.ClientID;
+import com.nimbusds.oauth2.sdk.token.AccessToken;
import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
@@ -604,18 +605,37 @@ public abstract class AbstractOidcFlowTest extends AbstractFlowTest {
}
protected static SignedJWT buildDPoPProof(final String method, final String uri) {
+ return buildDPoPProof(method, uri, null);
+ }
+
+ protected static SignedJWT buildDPoPProof(final String method, final String uri, final AccessToken accessToken) {
+ return buildDPoPProof(defaultDPoPProofKey(), JWSAlgorithm.ES256, method, uri, accessToken);
+ }
+
+ protected static SignedJWT buildDPoPProof(final JWK jwk, final JWSAlgorithm alg, final String method,
+ final String uri, final AccessToken accessToken) {
try {
- ECKey jwk = new ECKeyGenerator(Curve.P_256)
- .keyID("1")
- .generate();
- DPoPProofFactory proofFactory = new DefaultDPoPProofFactory(
- jwk,
- JWSAlgorithm.ES256);
- return proofFactory.createDPoPJWT(method, new URI(uri));
+ DPoPProofFactory proofFactory = new DefaultDPoPProofFactory(jwk, alg);
+ if (accessToken == null) {
+ return proofFactory.createDPoPJWT(method, new URI(uri));
+ } else {
+ return proofFactory.createDPoPJWT(method, new URI(uri), accessToken);
+ }
} catch (JOSEException | URISyntaxException e) {
Assert.fail("Could not create DPoP proof", e);
}
return null;
+
}
+ protected static ECKey defaultDPoPProofKey() {
+ try {
+ return new ECKeyGenerator(Curve.P_256)
+ .keyID("1")
+ .generate();
+ } catch (JOSEException e) {
+ Assert.fail("Could not initialize DPoP proof key", e);
+ }
+ return null;
+ }
}
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 2ae1705b..8a73e8b8 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
@@ -35,6 +35,7 @@ import org.testng.annotations.Test;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
@@ -316,7 +317,7 @@ public class UserInfoTest extends AbstractOidcApiFlowTest {
@SuppressWarnings("null")
@Test
- public void testSuccessOnlySubjectWithDPoPNoAudience() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
+ public void testFailWithDPoP_noAth() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
ComponentInitializationException, IOException, com.nimbusds.oauth2.sdk.ParseException, JOSEException {
final SignedJWT dpopProof = buildDPoPProof("POST", "http://localhost/idp/profile/oidc/userinfo");
final AccessTokenClaimsSet claims =
@@ -325,6 +326,42 @@ public class UserInfoTest extends AbstractOidcApiFlowTest {
final DPoPAccessToken token = new DPoPAccessToken(claims.serialize(getDataSealer()));
request.addHeader("DPoP", dpopProof.serialize());
+ storeMetadata(storageService, clientId, "mockSecret", scope);
+ request.addHeader("Authorization", getTokenHeaderValue(token));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertErrorCode(result, OAuth2Error.INVALID_DPOP_PROOF_CODE);
+ }
+
+ @SuppressWarnings("null")
+ @Test
+ public void testFailWithDPoP_nonMatchingAth() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
+ ComponentInitializationException, IOException, com.nimbusds.oauth2.sdk.ParseException, JOSEException {
+ final SignedJWT dpopProof = buildDPoPProof("POST", "http://localhost/idp/profile/oidc/userinfo", new DPoPAccessToken("mock"));
+ final AccessTokenClaimsSet claims =
+ buildDPoPAccessTokenClaimsSet((dpopProof.getHeader().getJWK().computeThumbprint().toString()));
+
+ final DPoPAccessToken token = new DPoPAccessToken(claims.serialize(getDataSealer()));
+ request.addHeader("DPoP", dpopProof.serialize());
+
+ storeMetadata(storageService, clientId, "mockSecret", scope);
+ request.addHeader("Authorization", getTokenHeaderValue(token));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertErrorCode(result, OAuth2Error.INVALID_DPOP_PROOF_CODE);
+ }
+
+ @SuppressWarnings("null")
+ @Test
+ public void testSuccessOnlySubjectWithDPoP() 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, "POST",
+ "http://localhost/idp/profile/oidc/userinfo", token);
+ request.addHeader("DPoP", dpopProof.serialize());
+
storeMetadata(storageService, clientId, "mockSecret", scope);
request.addHeader("Authorization", getTokenHeaderValue(token));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
@@ -339,7 +376,7 @@ public class UserInfoTest extends AbstractOidcApiFlowTest {
@SuppressWarnings("null")
@Test
- public void testSuccessOnlySubjectWithDPoPJWTNoAudience() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
+ public void testFailWithJWTDPoP_noAth() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
ComponentInitializationException, IOException, com.nimbusds.oauth2.sdk.ParseException, JOSEException {
final SignedJWT dpopProof = buildDPoPProof("POST", "http://localhost/idp/profile/oidc/userinfo");
final AccessTokenClaimsSet claims =
@@ -348,6 +385,42 @@ public class UserInfoTest extends AbstractOidcApiFlowTest {
final DPoPAccessToken token = buildJWTDPoPToken(claims, signingKey.getPrivateKey(), "RS256");
request.addHeader("DPoP", dpopProof.serialize());
+ storeMetadata(storageService, clientId, "mockSecret", scope);
+ request.addHeader("Authorization", getTokenHeaderValue(token));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertErrorCode(result, OAuth2Error.INVALID_DPOP_PROOF_CODE);
+ }
+
+ @SuppressWarnings("null")
+ @Test
+ public void testFailWithJWTDPoP_nonMatchingAth() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
+ ComponentInitializationException, IOException, com.nimbusds.oauth2.sdk.ParseException, JOSEException {
+ final SignedJWT dpopProof = buildDPoPProof("POST", "http://localhost/idp/profile/oidc/userinfo", new DPoPAccessToken("mock"));
+ final AccessTokenClaimsSet claims =
+ buildDPoPAccessTokenClaimsSet((dpopProof.getHeader().getJWK().computeThumbprint().toString()));
+
+ final DPoPAccessToken token = buildJWTDPoPToken(claims, signingKey.getPrivateKey(), "RS256");
+ request.addHeader("DPoP", dpopProof.serialize());
+
+ storeMetadata(storageService, clientId, "mockSecret", scope);
+ request.addHeader("Authorization", getTokenHeaderValue(token));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertErrorCode(result, OAuth2Error.INVALID_DPOP_PROOF_CODE);
+ }
+
+ @SuppressWarnings("null")
+ @Test
+ public void testSuccessOnlySubjectWithDPoPJWTNoAudience() 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 = buildJWTDPoPToken(claims, signingKey.getPrivateKey(), "RS256");
+ final SignedJWT dpopProof = buildDPoPProof(dpopProofKey, JWSAlgorithm.ES256, "POST",
+ "http://localhost/idp/profile/oidc/userinfo", token);
+ request.addHeader("DPoP", dpopProof.serialize());
+
storeMetadata(storageService, clientId, "mockSecret", scope);
request.addHeader("Authorization", getTokenHeaderValue(token));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DPoPAccessTokenHashFromRequestLookupFunctionTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DPoPAccessTokenHashFromRequestLookupFunctionTest.java
new file mode 100644
index 00000000..caa603d7
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DPoPAccessTokenHashFromRequestLookupFunctionTest.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.oidc.op.profile.logic;
+
+import java.util.function.Supplier;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.oauth2.sdk.dpop.DPoPUtils;
+import com.nimbusds.oauth2.sdk.token.DPoPAccessToken;
+
+import jakarta.servlet.http.HttpServletRequest;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.component.UninitializedComponentException;
+import net.shibboleth.shared.primitive.NonnullSupplier;
+
+/**
+ * Unit tests for {@link DPoPAccessTokenHashFromRequestLookupFunction}.
+ */
+public class DPoPAccessTokenHashFromRequestLookupFunctionTest {
+
+ DPoPAccessTokenHashFromRequestLookupFunction function;
+
+ @Test(expectedExceptions = ComponentInitializationException.class)
+ public void testNoSupplier() throws ComponentInitializationException {
+ function = new DPoPAccessTokenHashFromRequestLookupFunction();
+ function.setId("mockId");
+ function.initialize();
+ }
+
+ @Test(expectedExceptions = UninitializedComponentException.class)
+ public void testNotInitialized(){
+ function = new DPoPAccessTokenHashFromRequestLookupFunction();
+ function.setHttpServletRequestSupplier(new Supplier<>() {
+
+ @Override
+ public HttpServletRequest get() {
+ return null;
+ }
+
+ });
+ function.apply(null);
+ }
+
+ @Test
+ public void testNoValues() {
+ function = initWithSupplier();
+ Assert.assertNull(function.apply(null));
+ }
+
+ @Test
+ public void testOneValue() throws JOSEException {
+ function = initWithSupplier("DPoP mock");
+ Assert.assertEquals(function.apply(null), DPoPUtils.computeSHA256(new DPoPAccessToken("mock")).toString());
+ }
+
+ @Test
+ public void testOneBearerValue() {
+ function = initWithSupplier("Bearer mock");
+ Assert.assertNull(function.apply(null));
+ }
+
+ @Test
+ public void testMultioleValues() throws JOSEException {
+ function = initWithSupplier("Bearer mock1", "DPoP mock2");
+ Assert.assertEquals(function.apply(null), DPoPUtils.computeSHA256(new DPoPAccessToken("mock2")).toString());
+ }
+
+ protected DPoPAccessTokenHashFromRequestLookupFunction initWithSupplier(final String... values) {
+ final NonnullSupplier<HttpServletRequest> supplier = new NonnullSupplier<>() {
+
+ @Override
+ public HttpServletRequest get() {
+ final MockHttpServletRequest httpRequest = new MockHttpServletRequest();
+ for (final String value : values) {
+ assert value != null;
+ httpRequest.addHeader("Authorization", value);
+ }
+ return httpRequest;
+ }
+
+ };
+ function = new DPoPAccessTokenHashFromRequestLookupFunction();
+ function.setHttpServletRequestSupplier(supplier);
+ function.setId("mockId");
+ try {
+ function.initialize();
+ } catch (ComponentInitializationException e) {
+ Assert.fail();
+ }
+ return function;
+ }
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list