[java-idp-oidc] branch main updated: JOIDC-200 - Support for OAuth2 Pushed Authorization Requests (PAR)
Henri Mikkonen
henri.mikkonen at iki.fi
Fri Sep 13 10:05:32 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=33ea46ad796914b946150296034753cf51edaf15
The following commit(s) were added to refs/heads/main by this push:
new 33ea46ad JOIDC-200 - Support for OAuth2 Pushed Authorization Requests (PAR)
33ea46ad is described below
commit 33ea46ad796914b946150296034753cf51edaf15
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Sep 13 13:04:58 2024 +0300
JOIDC-200 - Support for OAuth2 Pushed Authorization Requests (PAR)
https://shibboleth.atlassian.net/browse/JOIDC-200
- Changed OIDCAuthenticationResponseContext.requestObjectValidated into requestObjectFromPar to be more explicit
- The purpose and use of the flag is meant for signalling that the request object is built by OP/AS itself in PAR, and thus doesn't need to be validated in the same way as client-provided request object
- Modified ValidateRequestObject to compare client_id values also with PAR cases
---
.../context/OIDCAuthenticationResponseContext.java | 22 +++---
.../impl/SetRequestObjectToResponseContext.java | 2 +-
.../oauth2/profile/impl/ValidateRequestObject.java | 81 ++++++++++++----------
.../idp/flows/oidc/authorize/authorize-beans.xml | 4 +-
4 files changed, 59 insertions(+), 50 deletions(-)
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/context/OIDCAuthenticationResponseContext.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/context/OIDCAuthenticationResponseContext.java
index 3a9d5680..565a4d76 100644
--- a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/context/OIDCAuthenticationResponseContext.java
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/context/OIDCAuthenticationResponseContext.java
@@ -128,10 +128,10 @@ public class OIDCAuthenticationResponseContext extends BaseContext {
/** Session identifier. */
@Nullable private String sessionId;
- /** Whether request object has already been validated. */
- private boolean requestObjectValidated = false;
+ /** Whether request object has been provided from the PAR endooint. */
+ private boolean requestObjectFromPar = false;
- /** Whether request object valiadtion has failed. */
+ /** Whether request object validation has failed. */
private boolean requestObjectFailure = false;
/** DPoP Proof JWK thumbprint. */
@@ -570,25 +570,25 @@ public class OIDCAuthenticationResponseContext extends BaseContext {
}
/**
- * Get whether request object has already been validated.
+ * Get whether request object has been provided from the PAR endooint.
*
- * @return true if validated, false if not
+ * @return true if from the PAR endpoint, false if not
*
* @since 4.2.0
*/
- public boolean isRequestObjectValidated() {
- return requestObjectValidated;
+ public boolean isRequestObjectFromPar() {
+ return requestObjectFromPar;
}
/**
- * Set whether request object has already been validated.
+ * Set whether request object has been provided from the PAR endooint.
*
- * @param flag true if validated, false if not
+ * @param flag true if from the PAR endpoint, false if not
*
* @since 4.2.0
*/
- public void setRequestObjectValidated(final boolean flag) {
- requestObjectValidated = flag;
+ public void setRequestObjectFromPar(final boolean flag) {
+ requestObjectFromPar = flag;
}
/**
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetRequestObjectToResponseContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetRequestObjectToResponseContext.java
index 5ca78f97..c6153249 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetRequestObjectToResponseContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetRequestObjectToResponseContext.java
@@ -297,7 +297,7 @@ public class SetRequestObjectToResponseContext extends AbstractOAuthAuthorizatio
final JWTClaimsSet jwtClaimsSet = JWTClaimsSet.parse(claimsSet);
oidcResponseContext.setRequestObject(new PlainJWT(jwtClaimsSet));
log.debug("{} Request object by PAR reference stored to oidc response context", getLogPrefix());
- oidcResponseContext.setRequestObjectValidated(true);
+ oidcResponseContext.setRequestObjectFromPar(true);
return;
} catch (final ParseException e) {
log.error("{} Could not build JWT from the request_uri claims set", getLogPrefix(), e);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRequestObject.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRequestObject.java
index 16df6fb2..874eac2b 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRequestObject.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRequestObject.java
@@ -128,10 +128,6 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
log.debug("{} No request object, nothing to do", getLogPrefix());
return false;
}
- if (oidcResponseContext.isRequestObjectValidated()) {
- log.debug("{} Request object is already validated, nothing to do", getLogPrefix());
- return false;
- }
return true;
}
@@ -143,8 +139,40 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
assert oidcResponseContext != null;
+ final JWTClaimsSet claimsSet;
+ try {
+ assert requestObject != null;
+ claimsSet = requestObject.getJWTClaimsSet();
+ } catch (final ParseException e) {
+ log.error("{} Unable to parse request object {}", getLogPrefix(), e.getMessage());
+ oidcResponseContext.setRequestObjectFailure(true);
+ ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
+ return;
+ }
+ assert claimsSet != null;
+
+ final AuthorizationRequest authorizationRequest = getAuthorizationRequest();
+ if (authorizationRequest == null) {
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
+ log.error("{} Could not resolve AuthorizationRequest message from request", getLogPrefix());
+ return;
+ }
+
+ if (claimsSet.getClaims().containsKey("client_id")
+ && !authorizationRequest.getClientID()
+ .equals(new ClientID((String) claimsSet.getClaim("client_id")))) {
+ log.error("{} client_id in request object not matching client_id request parameter", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
+ return;
+ }
+
// We let "none" to be used only if nothing else has been registered.
if (requestObject instanceof PlainJWT) {
+ if (oidcResponseContext.isRequestObjectFromPar()) {
+ log.debug("{} Request object is built by the PAR endpoint and thus already validated",
+ getLogPrefix());
+ return;
+ }
if (getMetadataContext() == null) {
log.error("{} Request object unsigned, no client metadata", getLogPrefix());
oidcResponseContext.setRequestObjectFailure(true);
@@ -168,32 +196,15 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
}
}
- final JWTClaimsSet claimsSet;
- // Validate still client_id and response_type values
- try {
- assert requestObject != null;
- claimsSet = requestObject.getJWTClaimsSet();
- final AuthorizationRequest authorizationRequest = getAuthorizationRequest();
- if (authorizationRequest == null) {
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
- log.error("{} Could not resolve AuthorizationRequest message from request", getLogPrefix());
+ // Validate still response_type values
+ if (!parEndpointLogic && authorizationRequest instanceof AuthenticationRequest authenticationRequest) {
+ final ResponseType requestedType = authenticationRequest.getResponseType();
+ if (requestedType == null) {
+ log.error("{} mandatory response_type is missing from the request", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_RESPONSE_TYPE);
return;
}
- if (claimsSet.getClaims().containsKey("client_id")
- && !authorizationRequest.getClientID()
- .equals(new ClientID((String) claimsSet.getClaim("client_id")))) {
- log.error("{} client_id in request object not matching client_id request parameter", getLogPrefix());
- oidcResponseContext.setRequestObjectFailure(true);
- ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
- return;
- }
- if (!parEndpointLogic && authorizationRequest instanceof AuthenticationRequest authenticationRequest) {
- final ResponseType requestedType = authenticationRequest.getResponseType();
- if (requestedType == null) {
- log.error("{} mandatory response_type is missing from the request", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_RESPONSE_TYPE);
- return;
- }
+ try {
if (claimsSet.getClaims().containsKey("response_type")
&& !requestedType.equals(new ResponseType(claimsSet.getStringClaim("response_type").split(" ")))) {
log.error("{} response_type in request object not matching response_type request parameter",
@@ -202,12 +213,12 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
return;
}
+ } catch (final ParseException e) {
+ log.error("{} Unable to parse response_type from request object {}", getLogPrefix(), e.getMessage());
+ oidcResponseContext.setRequestObjectFailure(true);
+ ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
+ return;
}
- } catch (final ParseException e) {
- log.error("{} Unable to parse request object {}", getLogPrefix(), e.getMessage());
- oidcResponseContext.setRequestObjectFailure(true);
- ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
- return;
}
try {
@@ -223,10 +234,8 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
return;
}
+ }
- oidcResponseContext.setRequestObjectValidated(true);
- }
-
// Checkstyle: CyclomaticComplexity ON
}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
index 9acaba3c..447498ce 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
@@ -321,8 +321,8 @@
c:expression="#input.ensureOutboundMessageContext().ensureSubcontext(T(net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext)).getRequestObject() != null" />
</constructor-arg>
<constructor-arg>
- <bean id="RequestObjectNotVerified" parent="shibboleth.Conditions.Expression"
- c:expression="#input.ensureOutboundMessageContext().ensureSubcontext(T(net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext)).isRequestObjectValidated() == false" />
+ <bean id="RequestObjectNotFromPar" parent="shibboleth.Conditions.Expression"
+ c:expression="#input.ensureOutboundMessageContext().ensureSubcontext(T(net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext)).isRequestObjectFromPar() == false" />
</constructor-arg>
</bean>
</constructor-arg>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list