[java-idp-plugin-vci] 02/06: clientIDLookupStrategy is now expected to take ProfileRequestContext and not MessageContext as input
Codeberg
noreply at shibboleth.net
Tue Dec 9 07:21:57 UTC 2025
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/DPOP
in repository java-idp-plugin-vci.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-vci/commit/7948ad3b66ca6342f9529308a43e1110ae56955b
commit 7948ad3b66ca6342f9529308a43e1110ae56955b
Author: jlauros <janne.lauros at csc.fi>
AuthorDate: Tue Dec 9 08:54:12 2025 +0200
clientIDLookupStrategy is now expected to take ProfileRequestContext and not MessageContext as input
---
.../plugin/openidvci/profile/impl/UnwrapGrant.java | 80 +++++++++++++---------
1 file changed, 47 insertions(+), 33 deletions(-)
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/UnwrapGrant.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/UnwrapGrant.java
index 37a9358..d331cba 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/UnwrapGrant.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/UnwrapGrant.java
@@ -16,6 +16,7 @@ package org.geant.shibboleth.plugin.openidvci.profile.impl;
import java.io.IOException;
import java.text.ParseException;
+import java.time.Instant;
import java.util.function.Function;
import javax.annotation.Nonnull;
@@ -26,9 +27,9 @@ import org.geant.shibboleth.plugin.openidvci.profile.context.navigate.APIRequest
import org.geant.shibboleth.plugin.openidvci.storage.CredentialOfferCache;
import org.geant.shibboleth.plugin.openidvci.storage.CredentialOfferObject;
import org.geant.shibboleth.plugin.openidvci.token.support.CredentialOfferClaimsSet;
-import org.opensaml.messaging.context.MessageContext;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
import org.slf4j.Logger;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -46,6 +47,7 @@ import net.shibboleth.shared.annotation.ParameterName;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.FunctionSupport;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.security.DataSealer;
import net.shibboleth.shared.security.DataSealerException;
@@ -55,27 +57,27 @@ import net.shibboleth.shared.security.DataSealerException;
*
* <p>
* Operation is valid if it is successfully unwrapped, parsed as a code or
- * refresh token, is unexpired and was issued to the expected client.
+ * pre-authorized code, is unexpired and was issued to the expected client.
*
* Pre-authorized grant may also be located from storage.
* </p>
*
* <p>
- * The claims set from the authorization grant grant is stored to response context via
+ * The claims set from the authorization grant grant is stored to response
+ * context via
* {@link OIDCAuthenticationResponseContext#setAuthorizationGrantClaimsSet(TokenClaimsSet)}.
* </p>
*
* <p>
- * The credential offer object from pre-authorised grant is stored to response context via
- * {@link TokenContext#setCredentialOfferObject}.
+ * The credential offer object from pre-authorised grant is stored to response
+ * context via {@link TokenContext#setCredentialOfferObject}.
* </p>
*
* <p>
- * The potential credentials from pre-authorised grant is stored to response context via
- * {@link TokenContext#setPotentialCredentials}.
+ * The potential credentials from pre-authorised grant is stored to response
+ * context via {@link TokenContext#setPotentialCredentials}.
* </p>
*
- * @since 4.4.0
*/
public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
@@ -89,8 +91,8 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
/** Strategy used to obtain the client id value from token request. */
@Nonnull
- private Function<MessageContext, ClientID> clientIDLookupStrategy;
-
+ private Function<ProfileRequestContext, ClientID> clientIDLookupStrategy;
+
@NonnullAfterInit
private CredentialOfferCache credentialOfferCache;
@@ -101,9 +103,11 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
*/
public UnwrapGrant(@Nonnull @ParameterName(name = "sealer") final DataSealer sealer) {
dataSealer = Constraint.isNotNull(sealer, "DataSealer cannot be null");
- clientIDLookupStrategy = new APIRequestClientIDLookupFunction();
+ APIRequestClientIDLookupFunction lookup = new APIRequestClientIDLookupFunction();
+ lookup.setDataSealer(sealer);
+ clientIDLookupStrategy = FunctionSupport.compose(lookup, new InboundMessageContextLookup());
}
-
+
/**
* Set the credential offer cache instance to use.
*
@@ -114,18 +118,17 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
credentialOfferCache = Constraint.isNotNull(cache, "CredentialOfferCache cannot be null");
}
-
/**
* Set the strategy used to locate the client id of the request.
*
* @param strategy lookup strategy
*/
- public void setClientIDLookupStrategy(@Nonnull final Function<MessageContext, ClientID> strategy) {
+ public void setClientIDLookupStrategy(@Nonnull final Function<ProfileRequestContext, ClientID> strategy) {
ifInitializedThrowUnmodifiabledComponentException();
clientIDLookupStrategy = Constraint.isNotNull(strategy,
"ClientIDLookupStrategy lookup strategy cannot be null");
}
-
+
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
@@ -138,12 +141,8 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
/** {@inheritDoc} */
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
- final AuthorizationGrant grant = getTokenRequest() != null ? getTokenRequest().getAuthorizationGrant():null;
- //DO NOT ADD IT YET
- TokenContext tokenContext = profileRequestContext.getInboundMessageContext().ensureSubcontext(TokenContext.class);
+ final AuthorizationGrant grant = getTokenRequest() != null ? getTokenRequest().getAuthorizationGrant() : null;
if (grant != null) {
- // Grant type is something OP traditionally understands, not OP
- // Most of the code executed in this block is from OP Unwrap implementation.
log.debug("{} Unwrapping grant type: {}", getLogPrefix(), grant.getType());
TokenClaimsSet tokenClaimsSet = null;
if (GrantType.AUTHORIZATION_CODE.equals(grant.getType())) {
@@ -163,25 +162,26 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
}
log.debug("{} Authz code unwrapped {}", getLogPrefix(), authzCodeClaimsSet.serialize());
tokenClaimsSet = authzCodeClaimsSet;
-
+
} catch (final DataSealerException | ParseException e) {
log.warn("{} Unwrapping authz code failed: {}", getLogPrefix(), e.getMessage());
ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_GRANT);
return;
}
}
- }
+ }
validateTokenClaimsSet(profileRequestContext, tokenClaimsSet);
final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
assert oidcResponseContext != null;
oidcResponseContext.setAuthorizationGrantClaimsSet(tokenClaimsSet);
+ TokenContext tokenContext = profileRequestContext.getInboundMessageContext()
+ .ensureSubcontext(TokenContext.class);
tokenContext.setPotentialCredentials(tokenClaimsSet.getUserinfoDeliveryClaims());
return;
- }else if (getOpenIDVCITokenRequest().getPreAuthorizedCode() instanceof String ){
+ } else if (getOpenIDVCITokenRequest().getPreAuthorizedCode() instanceof String) {
// This is pre-authorized grant
String code = getOpenIDVCITokenRequest().getPreAuthorizedCode();
log.info("{} Unwrapping pre-authorization code: {}", getLogPrefix(), code);
-
Exception e;
try {
CredentialOfferClaimsSet credentialOffer = CredentialOfferClaimsSet.parse(code, dataSealer);
@@ -194,17 +194,32 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
}
log.debug("{} pre-authorized grant unwrapped {}", getLogPrefix(), credentialOffer.serialize());
validateTokenClaimsSet(profileRequestContext, credentialOffer);
+ TokenContext tokenContext = profileRequestContext.getInboundMessageContext()
+ .ensureSubcontext(TokenContext.class);
tokenContext.setCredentialOfferObject(CredentialOfferObject.parse(credentialOffer.getSubject()));
+ getOidcResponseContext().setAuthTime(Instant.now());
setPotentialCredentials(tokenContext);
+ // Subject and auth time set for access token creation. TODO make sure what
+ // content to use.
+ getOidcResponseContext().setSubject(clientIDLookupStrategy.apply(profileRequestContext).getValue());
+ getOidcResponseContext().setAuthTime(Instant.now());
return;
- } catch (final DataSealerException | JsonProcessingException | com.nimbusds.oauth2.sdk.ParseException | ParseException e2) {
- log.warn("{} Unwrapping authz code failed: {}, might be storage based", getLogPrefix(), e2.getMessage());
+ } catch (final DataSealerException | JsonProcessingException | com.nimbusds.oauth2.sdk.ParseException
+ | ParseException e2) {
+ log.warn("{} Unwrapping authz code failed: {}, might be storage based", getLogPrefix(),
+ e2.getMessage());
}
-
+
try {
+ TokenContext tokenContext = profileRequestContext.getInboundMessageContext()
+ .ensureSubcontext(TokenContext.class);
tokenContext.setCredentialOfferObject(credentialOfferCache.getCredentialOffer(code));
setPotentialCredentials(tokenContext);
credentialOfferCache.removeCredentialOffer(code);
+ // Subject and auth time set for access token creation. TODO make sure what
+ // content to use.
+ getOidcResponseContext().setSubject(clientIDLookupStrategy.apply(profileRequestContext).getValue());
+ getOidcResponseContext().setAuthTime(Instant.now());
return;
} catch (IOException | net.minidev.json.parser.ParseException e1) {
e = e1;
@@ -216,7 +231,8 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
}
- private void validateTokenClaimsSet(@Nonnull final ProfileRequestContext profileRequestContext, TokenClaimsSet tokenClaimsSet) {
+ private void validateTokenClaimsSet(@Nonnull final ProfileRequestContext profileRequestContext,
+ TokenClaimsSet tokenClaimsSet) {
if (tokenClaimsSet == null) {
log.warn("{} Grant type not supported", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_GRANT);
@@ -229,9 +245,8 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
}
final ClientID clientId = tokenClaimsSet.getClientID();
assert clientId != null;
- final ClientID requestClientId = clientIDLookupStrategy
- .apply(profileRequestContext.ensureInboundMessageContext());
- final ClientID inheritedClientId = new ClientID(clientId.getValue()+"/wallet");
+ final ClientID requestClientId = clientIDLookupStrategy.apply(profileRequestContext);
+ final ClientID inheritedClientId = new ClientID(clientId.getValue() + "/wallet");
if (!clientId.equals(requestClientId) && !inheritedClientId.equals(requestClientId)) {
log.warn("{} Token issued to client {}, invalid for {}", getLogPrefix(), clientId.getValue(),
requestClientId);
@@ -239,7 +254,7 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
return;
}
}
-
+
private void setPotentialCredentials(@Nonnull TokenContext ctx) {
ClaimsSet credentialOfferClaims = new ClaimsSet();
ctx.getCredentialOfferObject().getPreAuthorizedCredentials().forEach((key, value) -> {
@@ -253,5 +268,4 @@ public class UnwrapGrant extends AbstractOpenIDVCITokenResponseAction {
ctx.setPotentialCredentials(credentialOfferClaims);
}
-
}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list