[java-idp-oidc] branch dev/JOIDC-226 updated: JOIDC-226 - Autoconfigure CORS for public OIDC clients
Codeberg
noreply at shibboleth.net
Thu Nov 20 14:14:31 UTC 2025
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/JOIDC-226
in repository java-idp-oidc.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-oidc/commit/67c465aa21c0a559f195ec394997e362b54c53ca
The following commit(s) were added to refs/heads/dev/JOIDC-226 by this push:
new 67c465aa JOIDC-226 - Autoconfigure CORS for public OIDC clients
67c465aa is described below
commit 67c465aa21c0a559f195ec394997e362b54c53ca
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Thu Nov 20 16:13:47 2025 +0200
JOIDC-226 - Autoconfigure CORS for public OIDC clients
https://shibboleth.atlassian.net/browse/JOIDC-226
Initial implementation, WIP
- Wired a new ValidateOriginHeader action into most of the API-flows: par, token, userinfo, introspection and revocation
- The default validation (DefaultOriginHeaderValidationPredicate) is against the registered redirect URIs (some of them must start with origin-header + "/"
- The action publishes InvalidOriginHeader event if the validation fails
- The base action (AbstractBuildErrorResponseFromEvent) for endpoint-specific error messages supports mappedResponsesLookupStrategy to map the event into pre-defined response
- Default implementation shibboleth.oidc.DefaultMappedErrorResponsesLookupStrategy can be overridden per flow
- Default response is similar to Spring's "Invalid CORS request" -response
---
.../impl/DefaultInvalidOriginErrorResponse.java | 68 +++++++++++
.../oauth2/profile/impl/ValidateOriginHeader.java | 124 +++++++++++++++++++++
.../impl/AbstractBuildErrorResponseFromEvent.java | 32 ++++++
.../DefaultOriginHeaderValidationPredicate.java | 62 +++++++++++
.../META-INF/net.shibboleth.idp/postconfig.xml | 14 +++
.../oauth2/introspection/introspection-beans.xml | 1 +
.../oauth2/introspection/introspection-flow.xml | 1 +
.../pushed-authorization-beans.xml | 1 +
.../pushed-authorization-flow.xml | 1 +
.../flows/oauth2/revocation/revocation-beans.xml | 1 +
.../flows/oauth2/revocation/revocation-flow.xml | 1 +
.../flows/oidc/abstract/oidc-abstract-beans.xml | 4 +
.../idp/flows/oidc/token/token-beans.xml | 1 +
.../shibboleth/idp/flows/oidc/token/token-flow.xml | 1 +
.../idp/flows/oidc/userinfo/userinfo-beans.xml | 1 +
.../idp/flows/oidc/userinfo/userinfo-flow.xml | 1 +
.../oidc/op/profile/flow/AbstractOidcFlowTest.java | 12 +-
.../op/profile/flow/IntrospectionFlowTest.java | 40 +++++++
.../op/profile/flow/PushedAuthorizeFlowTest.java | 28 +++++
.../oidc/op/profile/flow/RevocationFlowTest.java | 33 ++++++
.../plugin/oidc/op/profile/flow/TokenFlowTest.java | 34 ++++++
.../plugin/oidc/op/profile/flow/UserInfoTest.java | 27 +++++
22 files changed, 487 insertions(+), 1 deletion(-)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/impl/DefaultInvalidOriginErrorResponse.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/impl/DefaultInvalidOriginErrorResponse.java
new file mode 100644
index 00000000..74e2c21c
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/impl/DefaultInvalidOriginErrorResponse.java
@@ -0,0 +1,68 @@
+/*
+ * 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.messaging.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+
+import com.nimbusds.oauth2.sdk.Response;
+import com.nimbusds.oauth2.sdk.http.HTTPResponse;
+
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * A Nimbus {@link Response} implementation representing an error response related to invalid Origin-header in request.
+ */
+public class DefaultInvalidOriginErrorResponse implements Response {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultInvalidOriginErrorResponse.class);
+
+ /** The error message body contents. */
+ @Nullable private final String contents;
+
+ /**
+ * Constructor with default (null) body contents.
+ */
+ public DefaultInvalidOriginErrorResponse() {
+ this(null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param body error message contents.
+ */
+ public DefaultInvalidOriginErrorResponse(@Nonnull @ParameterName(name = "body") final String body) {
+ contents = body;
+ }
+
+ /** {@inheritDoc} */
+ public boolean indicatesSuccess() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public HTTPResponse toHTTPResponse() {
+ final HTTPResponse response = new HTTPResponse(HTTPResponse.SC_FORBIDDEN);
+ if (contents != null) {
+ response.setContent(contents);
+ }
+ return response;
+ }
+}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateOriginHeader.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateOriginHeader.java
new file mode 100644
index 00000000..8a41359f
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateOriginHeader.java
@@ -0,0 +1,124 @@
+/*
+ * 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.oauth2.profile.impl;
+
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+
+import net.shibboleth.idp.plugin.oidc.op.profile.logic.DefaultOriginHeaderValidationPredicate;
+import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * Validates the possibly existing Origin-header via a configurable validator.
+ *
+ * @since 4.4.0
+ */
+public class ValidateOriginHeader extends AbstractProfileAction {
+
+ /** Event identifier for invalid origin header. */
+ public static final String EVENT_ID_INVALID_ORIGIN_HEADER = "InvalidOriginHeader";
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(ValidateOriginHeader.class);
+
+ /** Strategy used to locate the Origin -header value. */
+ @Nonnull private Function<ProfileRequestContext, String> originHeaderLookupStrategy;
+
+ /** Enforcer function for validating client ID against the configured policy. */
+ @Nonnull private Function<ProfileRequestContext, BiPredicate<ProfileRequestContext, String>>
+ originHeaderValidatorLookupStrategy;
+
+ /** The Origin -header value to be validated. */
+ @NonnullBeforeExec private String origin;
+
+ /** The validator for the Origin -header value. */
+ @NonnullBeforeExec private BiPredicate<ProfileRequestContext, String> originValidator;
+
+ /** Constructor. */
+ public ValidateOriginHeader() {
+ originHeaderLookupStrategy = prc -> getHttpServletRequest().getHeader("Origin");
+ originHeaderValidatorLookupStrategy = FunctionSupport.constant(new DefaultOriginHeaderValidationPredicate());
+ }
+
+ /**
+ * Set the strategy used to locate the Origin -header value.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setOriginHeaderLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
+ checkSetterPreconditions();
+
+ originHeaderLookupStrategy =
+ Constraint.isNotNull(strategy, "OriginHeaderLookupStrategy cannot be null");
+ }
+
+ /**
+ * Set the strategy used to locate the validator for the Origin -header value.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setOriginHeaderValidatorLookupStrategy(
+ final Function<ProfileRequestContext, BiPredicate<ProfileRequestContext, String>> strategy) {
+ checkSetterPreconditions();
+
+ originHeaderValidatorLookupStrategy = Constraint.isNotNull(strategy,
+ "OriginHeaderValidatorLookupStrategy cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ if (!super.doPreExecute(profileRequestContext)) {
+ return false;
+ }
+
+ origin = StringSupport.trimOrNull(originHeaderLookupStrategy.apply(profileRequestContext));
+ if (origin == null) {
+ log.trace("{} No Origin-header resolved, nothing to do", getLogPrefix());
+ return false;
+ }
+
+ originValidator = originHeaderValidatorLookupStrategy.apply(profileRequestContext);
+ if (originValidator == null) {
+ log.error("{} No validator for the Origin-header resolved, nothing to do", getLogPrefix());
+ return false;
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ if (!originValidator.test(profileRequestContext, origin)) {
+ log.warn("{} Origin {} did not pass the validation", getLogPrefix(), origin);
+ ActionSupport.buildEvent(profileRequestContext, EVENT_ID_INVALID_ORIGIN_HEADER);
+ return;
+ }
+ log.debug("{} Successfully validated origin {}", getLogPrefix(), origin);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
index db1a7d18..a0493b50 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
@@ -30,12 +30,14 @@ import org.slf4j.Logger;
import com.nimbusds.oauth2.sdk.ErrorObject;
import com.nimbusds.oauth2.sdk.ErrorResponse;
+import com.nimbusds.oauth2.sdk.Response;
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
import net.shibboleth.idp.plugin.oidc.op.profile.EventIdToErrorObjectMapping;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.FunctionSupport;
import net.shibboleth.shared.primitive.LoggerFactory;
/**
@@ -63,6 +65,9 @@ public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorRespons
@Nonnull
private Function<ProfileRequestContext, EventContext> eventContextLookupStrategy;
+ /** Strategy function for locating the map of eventIds to pre-configured response messages. */
+ @Nonnull private Function<ProfileRequestContext, Map<String, Response>> mappedResponsesLookupStrategy;
+
/** Map of eventIds to pre-configured error objects. */
private Map<String, ErrorObject> mappedErrors;
@@ -82,6 +87,7 @@ public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorRespons
*/
public AbstractBuildErrorResponseFromEvent(@Nullable final Collection<M> freeObjects) {
eventContextLookupStrategy = new CurrentOrPreviousEventLookup();
+ mappedResponsesLookupStrategy = FunctionSupport.constant(CollectionSupport.emptyMap());
mappedErrors = new HashMap<>();
defaultStatusCode = DEFAULT_HTTP_STATUS_CODE;
defaultCode = DEFAULT_ERROR_CODE;
@@ -118,6 +124,21 @@ public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorRespons
eventContextLookupStrategy = Constraint.isNotNull(strategy, "EventContext lookup strategy cannot be null");
}
+ /**
+ * Set strategy function for locating the map of eventIds to pre-configured response messages.
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 4.4.0
+ */
+ public void setMappedResponsesLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, Map<String, Response>> strategy) {
+ ifInitializedThrowUnmodifiabledComponentException();
+
+ mappedResponsesLookupStrategy =
+ Constraint.isNotNull(strategy, "MappedResponses lookup strategy cannot be null");
+ }
+
/**
* Set map of eventIds to pre-configured error objects.
*
@@ -167,6 +188,17 @@ public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorRespons
final Object event = eventCtx.getEvent();
assert event != null;
final String eventValue = event.toString();
+ final Map<String, Response> mappedResponses = mappedResponsesLookupStrategy.apply(profileRequestContext);
+ if (mappedResponses != null && mappedResponses.containsKey(eventValue)) {
+ final Response mappedResponse = mappedResponses.get(eventValue);
+ if (mappedResponse == null) {
+ log.warn("{} Ignoring null response specified for event {}", getLogPrefix(), eventValue);
+ } else {
+ log.debug("{} Found mapped response message for event {}", getLogPrefix(), eventValue);
+ profileRequestContext.ensureOutboundMessageContext().setMessage(mappedResponse);
+ return;
+ }
+ }
final ErrorObject error;
if (mappedErrors.containsKey(eventValue)) {
log.debug("{} Found mapped event for {}", getLogPrefix(), eventValue);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DefaultOriginHeaderValidationPredicate.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DefaultOriginHeaderValidationPredicate.java
new file mode 100644
index 00000000..b4f8ab8c
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/DefaultOriginHeaderValidationPredicate.java
@@ -0,0 +1,62 @@
+/*
+ * 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.net.URI;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultValidRedirectUrisLookupFunction;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * Default validation strategy for the Origin -header. This checks if any of the valid URIs fetched via lookup strategy
+ * starts with the Origin-value given in the input parameters.
+ *
+ * @since 4.4.0
+ */
+public class DefaultOriginHeaderValidationPredicate implements BiPredicate<ProfileRequestContext, String> {
+
+ /** Strategy used to obtain the redirect uris to compare request value to. */
+ @Nonnull private Function<ProfileRequestContext, Set<URI>> validRedirectURIsLookupStrategy;
+
+ /**
+ * Constructor.
+ */
+ public DefaultOriginHeaderValidationPredicate() {
+ validRedirectURIsLookupStrategy = new DefaultValidRedirectUrisLookupFunction();
+ }
+
+ @Override
+ public boolean test(@Nullable final ProfileRequestContext profileRequestContext, @Nullable final String origin) {
+ if (StringSupport.trimOrNull(origin) == null) {
+ return false;
+ }
+ return Optional.ofNullable(validRedirectURIsLookupStrategy.apply(profileRequestContext))
+ .map(set -> set.stream()
+ .map(uri -> uri.toString())
+ .map(uri -> uri.endsWith("/") ? uri : uri.concat("/"))
+ .anyMatch(uri -> uri.startsWith(origin)))
+ .orElse(false);
+ }
+
+}
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index cd6daefd..b2b716b3 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -965,4 +965,18 @@
<bean id="DefaultMetadataSkeleton" class="org.springframework.core.io.FileSystemResource" lazy-init="true"
c:path="%{idp.oidc.discovery.template:%{idp.home}/static/openid-configuration.json}" />
+ <bean id="shibboleth.oidc.DefaultMappedErrorResponsesLookupStrategy" parent="shibboleth.Functions.Constant">
+ <constructor-arg name="target">
+ <util:map id="shibboleth.oidc.DefaultMappedErrorResponses" value-type="com.nimbusds.oauth2.sdk.Response">
+ <entry>
+ <key>
+ <util:constant static-field="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.ValidateOriginHeader.EVENT_ID_INVALID_ORIGIN_HEADER"/>
+ </key>
+ <bean class="net.shibboleth.idp.plugin.oidc.op.messaging.impl.DefaultInvalidOriginErrorResponse"
+ c:body="Invalid CORS request"/>
+ </entry>
+ </util:map>
+ </constructor-arg>
+ </bean>
+
</beans>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-beans.xml
index a6e3d194..fe0a39be 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-beans.xml
@@ -55,6 +55,7 @@
class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.BuildIntrospectionErrorResponseFromEvent"
scope="prototype"
p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier"
+ p:mappedResponsesLookupStrategy="#{getObject('shibboleth.oauth2.introspection.MappedErrorResponsesLookupStrategy') ?: getObject('shibboleth.oidc.DefaultMappedErrorResponsesLookupStrategy')}"
p:mappedErrors="#{getObject('shibboleth.oauth2.introspection.MappedErrors') ?: getObject('shibboleth.oidc.DefaultApiMappedErrors')}">
<property name="eventContextLookupStrategy">
<bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-flow.xml
index 3aa8e59f..51b7a528 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-flow.xml
@@ -27,6 +27,7 @@
<action-state id="ResumeAfterAuthentication">
<evaluate expression="ValidateClientIDAgainstPolicy" />
+ <evaluate expression="ValidateOriginHeader" />
<evaluate expression="ProcessTokenForIntrospection" />
<evaluate expression="'proceed'" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-beans.xml
index 702ca83c..f656229e 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-beans.xml
@@ -372,6 +372,7 @@
class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.BuildPushedAuthorizationErrorResponseFromEvent"
scope="prototype"
p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier"
+ p:mappedResponsesLookupStrategy="#{getObject('shibboleth.oauth2.par.MappedErrorResponsesLookupStrategy') ?: getObject('shibboleth.oidc.DefaultMappedErrorResponsesLookupStrategy')}"
p:mappedErrors="#{getObject('shibboleth.oauth2.par.MappedErrors') ?: getObject('shibboleth.oidc.DefaultApiMappedErrors')}">
<property name="eventContextLookupStrategy">
<bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-flow.xml
index 496a74a9..efff4f70 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-flow.xml
@@ -28,6 +28,7 @@
<action-state id="ResumeAfterAuthentication">
<evaluate expression="ValidatePushedAuthorizationClientIDMatch" />
<evaluate expression="ValidateClientIDAgainstPolicy" />
+ <evaluate expression="ValidateOriginHeader" />
<evaluate expression="ValidateAuthorizationRequestType" />
<evaluate expression="InitializeOutboundMessageContext" />
<evaluate expression="SetRequestObjectToResponseContext" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-beans.xml
index 4655bc34..2f556f82 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-beans.xml
@@ -67,6 +67,7 @@
class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.BuildRevokeTokenErrorResponseFromEvent"
scope="prototype"
p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier"
+ p:mappedResponsesLookupStrategy="#{getObject('shibboleth.oauth2.revocation.MappedErrorResponsesLookupStrategy') ?: getObject('shibboleth.oidc.DefaultMappedErrorResponsesLookupStrategy')}"
p:mappedErrors="#{getObject('shibboleth.oauth2.revocation.MappedErrors') ?: getObject('shibboleth.oidc.DefaultApiMappedErrors')}">
<property name="eventContextLookupStrategy">
<bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-flow.xml
index ad68687a..5a470d1e 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-flow.xml
@@ -29,6 +29,7 @@
<action-state id="ResumeAfterAuthentication">
<evaluate expression="ValidateClientIDAgainstPolicy" />
+ <evaluate expression="ValidateOriginHeader" />
<evaluate expression="ProcessTokenForRevocation" />
<evaluate expression="RevokeToken" />
<evaluate expression="'proceed'" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract/oidc-abstract-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract/oidc-abstract-beans.xml
index aa8f2367..5805a4e6 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract/oidc-abstract-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract/oidc-abstract-beans.xml
@@ -140,4 +140,8 @@
c:type="#{ T(net.shibboleth.oidc.security.jose.context.SecurityParametersContext) }"
c:createContext="true" />
+ <bean id="ValidateOriginHeader" class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.ValidateOriginHeader"
+ scope="prototype"
+ p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier" />
+
</beans>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-beans.xml
index ef14c177..5c0c4fd1 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-beans.xml
@@ -660,6 +660,7 @@
<bean id="BuildErrorResponseFromEvent"
class="net.shibboleth.idp.plugin.oidc.op.profile.impl.BuildTokenErrorResponseFromEvent" scope="prototype"
p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier"
+ p:mappedResponsesLookupStrategy="#{getObject('shibboleth.oidc.token.MappedErrorResponsesLookupStrategy') ?: getObject('shibboleth.oidc.DefaultMappedErrorResponsesLookupStrategy')}"
p:mappedErrors="#{getObject('shibboleth.oidc.token.MappedErrors') ?: getObject('shibboleth.oidc.DefaultApiMappedErrors')}">
<property name="eventContextLookupStrategy">
<bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
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 9eb45d3f..8187342b 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
@@ -36,6 +36,7 @@
<action-state id="ResumeAfterAuthentication">
<evaluate expression="ValidateClientIDAgainstPolicy" />
+ <evaluate expression="ValidateOriginHeader" />
<evaluate expression="ValidateGrantType" />
<evaluate expression="'proceed'" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-beans.xml
index 61113570..60276ab1 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-beans.xml
@@ -228,6 +228,7 @@
<bean id="BuildErrorResponseFromEvent"
class="net.shibboleth.idp.plugin.oidc.op.userinfo.profile.impl.BuildUserInfoErrorResponseFromEvent" scope="prototype"
p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier"
+ p:mappedResponsesLookupStrategy="#{getObject('shibboleth.oidc.userinfo.MappedErrorResponsesLookupStrategy') ?: getObject('shibboleth.oidc.DefaultMappedErrorResponsesLookupStrategy')}"
p:mappedErrors="#{getObject('shibboleth.oidc.userinfo.MappedErrors') ?: getObject('shibboleth.oidc.DefaultOAuth2ProtectedApiMappedErrors')}"
p:securityParametersContextLookupStrategy-ref="DPoPSecurityParametersContextProfileRequestContextLookup"
p:algorithmCandidates="%{idp.oauth2.dpop.proofAlgorithms:RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512}"
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-flow.xml
index e7120437..9a744e36 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-flow.xml
@@ -48,6 +48,7 @@
<action-state id="ResumeAfterDoDPoPProofValidation">
<evaluate expression="ValidateClientIDAgainstPolicy" />
+ <evaluate expression="ValidateOriginHeader" />
<evaluate expression="ValidateAccessToken" />
<evaluate expression="ValidateScope" />
<evaluate expression="SetRequestedClaimsToResponseContext" />
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 9177af6f..75f4232d 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
@@ -94,6 +94,9 @@ import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.shibboleth.idp.plugin.oidc.op.messaging.impl.DefaultInvalidOriginErrorResponse;
import net.shibboleth.idp.plugin.oidc.op.token.support.AccessTokenClaimsSet;
import net.shibboleth.idp.plugin.oidc.op.token.support.TokenClaimsSet;
import net.shibboleth.idp.test.flows.AbstractFlowTest;
@@ -234,7 +237,14 @@ public abstract class AbstractOidcFlowTest extends AbstractFlowTest {
Assert.assertNotNull(errorResponse.getErrorObject().getDescription());
Assert.assertTrue(errorResponse.getErrorObject().getDescription().contains(errorDescription));
}
-
+
+ protected void assertInvalidOriginResponse(final FlowExecutionResult result) {
+ final Response response = parseResponse(result);
+ Assert.assertFalse(response.indicatesSuccess());
+ Assert.assertTrue(response instanceof DefaultInvalidOriginErrorResponse);
+ Assert.assertEquals(response.toHTTPResponse().getContent(), "Invalid CORS request");
+ }
+
protected void setJsonRequest(final String method, final String body) {
setRequest(method, body, "application/json");
}
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
index 26a20286..209145c6 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
@@ -219,6 +219,46 @@ public class IntrospectionFlowTest extends AbstractOidcClientAuthenticationFlowT
}
}
+ @Test
+ public void testSuccess_validOrigin() throws IOException, NoSuchAlgorithmException, URISyntaxException,
+ DataSealerException, ComponentInitializationException {
+ for (final String clientId : clientIds) {
+ storeMetadata(storageService, clientId, clientSecret, scope, "https://example.org/cb");
+ setBasicAuth(clientId, clientSecret);
+ request.addHeader("Origin", "https://example.org");
+ setHttpFormRequest("POST", Map.of(
+ "token",
+ buildToken(clientId, "sub", Scope.parse("openid")).toJSONObject().getAsString("access_token"),
+ "token_type",
+ "access_token"));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ final TokenIntrospectionSuccessResponse resp =
+ parseSuccessResponse(result, TokenIntrospectionSuccessResponse.class);
+ Assert.assertTrue(resp.isActive());
+ assertBearerToken(resp);
+ Assert.assertEquals(resp.getClientID().getValue(), clientId);
+ Assert.assertEquals(resp.getScope(), Scope.parse("openid"));
+ Assert.assertNull(resp.getAudience());
+ Assert.assertEquals(resp.getUsername(), "jdoe");
+ }
+ }
+
+ @Test
+ public void testFails_invalidOrigin() throws IOException, NoSuchAlgorithmException, URISyntaxException,
+ DataSealerException, ComponentInitializationException {
+ for (final String clientId : clientIds) {
+ storeMetadata(storageService, clientId, clientSecret, scope, "https://example.org/cb");
+ request.addHeader("Origin", "https://example.org:1234");
+ setBasicAuth(clientId, clientSecret);
+ setHttpFormRequest("POST", Map.of(
+ "token",
+ buildToken(clientId, "sub", Scope.parse("openid")).toJSONObject().getAsString("access_token"),
+ "token_type",
+ "access_token"));
+ assertInvalidOriginResponse(flowExecutor.launchExecution(FLOW_ID, null, externalContext));
+ }
+ }
+
@Test
public void testSuccessDPoP() throws IOException, NoSuchAlgorithmException, URISyntaxException, DataSealerException,
ComponentInitializationException {
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/PushedAuthorizeFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/PushedAuthorizeFlowTest.java
index f95b62af..2ec24d3c 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/PushedAuthorizeFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/PushedAuthorizeFlowTest.java
@@ -193,6 +193,34 @@ public class PushedAuthorizeFlowTest extends AbstractOidcClientAuthenticationFlo
}
}
+ @Test
+ public void testSuccess_validOrigin() throws IOException, NoSuchAlgorithmException, URISyntaxException,
+ DataSealerException, ComponentInitializationException {
+ for (final String clientId : clientIds) {
+ storeMetadata(storageService, clientId, clientSecret, scope, "https://example.org/cb");
+ setBasicAuth(clientId, clientSecret);
+ request.addHeader("Origin", "https://example.org");
+ setHttpFormRequest("POST", createRequestParameters(clientId));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertSuccessResponse(result, clientId);
+ final PushedAuthorizationSuccessResponse response =
+ parseSuccessResponse(result, PushedAuthorizationSuccessResponse.class);
+ verifyAuthorizeEndpoint(clientId, response.getRequestURI().toString());
+ }
+ }
+
+ @Test
+ public void testFails_invalidOrigin() throws IOException, NoSuchAlgorithmException, URISyntaxException,
+ DataSealerException, ComponentInitializationException {
+ for (final String clientId : clientIds) {
+ storeMetadata(storageService, clientId, clientSecret, scope, "https://example.org/cb");
+ setBasicAuth(clientId, clientSecret);
+ request.addHeader("Origin", "https://example.org:1234");
+ setHttpFormRequest("POST", createRequestParameters(clientId));
+ assertInvalidOriginResponse(flowExecutor.launchExecution(FLOW_ID, null, externalContext));
+ }
+ }
+
@Test
public void testFailure_unregisteredScope() throws IOException, NoSuchAlgorithmException, URISyntaxException, DataSealerException,
ComponentInitializationException {
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
index 4ad7fc55..e7fa12bf 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
@@ -142,6 +142,39 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
}
}
+ @Test
+ public void testSuccess_validOrigin() throws IOException, NoSuchAlgorithmException, URISyntaxException,
+ DataSealerException, ComponentInitializationException {
+ final String id = idGenerator.generateIdentifier();
+ final String rootId = idGenerator.generateIdentifier();
+ for (final String clientId : clientIds) {
+ setBasicAuth(clientId, clientSecret);
+ request.addHeader("Origin", "https://example.org");
+ storeMetadata(storageService, clientId, clientSecret, scope, "https://example.org/cb");
+ setHttpFormRequest("POST", Collections.singletonMap("token", super.buildToken(clientId, "sub",
+ Scope.parse("openid"), null, id, rootId).toJSONObject().getAsString("access_token")));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class);
+ Assert.assertFalse(revocationCache.isRevoked(RevocationCacheContexts.SINGLE_ACCESS_OR_REFRESH_TOKENS, id));
+ Assert.assertTrue(revocationCache.isRevoked(RevocationCacheContexts.AUTHORIZATION_CODE, rootId));
+ }
+ }
+
+ @Test
+ public void testFails_invalidOrigin() throws IOException, NoSuchAlgorithmException, URISyntaxException,
+ DataSealerException, ComponentInitializationException {
+ final String id = idGenerator.generateIdentifier();
+ final String rootId = idGenerator.generateIdentifier();
+ for (final String clientId : clientIds) {
+ setBasicAuth(clientId, clientSecret);
+ request.addHeader("Origin", "https://example.org:1234");
+ storeMetadata(storageService, clientId, clientSecret, scope, "https://example.org");
+ setHttpFormRequest("POST", Collections.singletonMap("token", super.buildToken(clientId, "sub",
+ Scope.parse("openid"), null, id, rootId).toJSONObject().getAsString("access_token")));
+ assertInvalidOriginResponse(flowExecutor.launchExecution(FLOW_ID, null, externalContext));
+ }
+ }
+
@Test
public void testSuccessWithPostAuthn() throws IOException, NoSuchAlgorithmException, URISyntaxException,
DataSealerException, ComponentInitializationException {
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
index a3cbd3cd..903bb3c2 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
@@ -278,6 +278,40 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
}
}
+ @Test
+ public void testValidGrantAcceptedOrigin() throws Exception {
+ for (final String clientId : clientIds) {
+ request.addHeader("Origin", "https://example.org");
+ initializeGrantAndRequest(clientId, createRequestParameters(redirectUri, "authorization_code",
+ buildAuthorizationCode(clientId), clientId));
+ storeConsent(storageService, "jdoe", clientId, "mail");
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ final OIDCTokenResponse response = parseSuccessResponse(result, OIDCTokenResponse.class);
+ Assert.assertNotNull(response.getTokens().getAccessToken());
+ Assert.assertNotNull(response.getTokens().getRefreshToken());
+ Assert.assertNotNull(response.getOIDCTokens().getIDToken());
+ Assert.assertNotNull(response.getOIDCTokens().getIDToken().getJWTClaimsSet().getClaim("at_hash"));
+ Assert.assertNull(getSidFromAccessToken(response.getTokens().getAccessToken()));
+ Assert.assertNull(getSidFromRefreshToken(response.getTokens().getRefreshToken()));
+ assertDecoratedRefreshToken(response.getTokens().getRefreshToken());
+ Assert.assertNull(getSidFromJWT(response.getOIDCTokens().getIDToken()));
+ assertDecoratedAccessToken(response.getTokens().getAccessToken());
+ assertDecoratedIdToken(response.getOIDCTokens().getIDToken());
+ }
+ }
+
+ @Test
+ public void testValidGrantInvalidOrigin() throws Exception {
+ for (final String clientId : clientIds) {
+ request.addHeader("Origin", "http://localhost:12345");
+ initializeGrantAndRequest(clientId, createRequestParameters(redirectUri, "authorization_code",
+ buildAuthorizationCode(clientId), clientId));
+ storeConsent(storageService, "jdoe", clientId, "mail");
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertInvalidOriginResponse(flowExecutor.launchExecution(FLOW_ID, null, externalContext));
+ }
+ }
+
@Test
public void testValidWithUriResource() throws Exception {
final Map<String, String> requestParameters = createRequestParameters(redirectUri, "authorization_code",
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 03b8fc1b..779cc69c 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
@@ -172,6 +172,33 @@ public class UserInfoTest extends AbstractOidcApiFlowTest {
Assert.assertNull(response.getUserInfoJWT());
}
+ @Test
+ public void testSuccess_validOrigin() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
+ ComponentInitializationException, IOException {
+ final BearerAccessToken token = buildToken(clientId, subject, new Scope("openid"));
+ storeMetadata(storageService, clientId, "mockSecret", scope, "https://example.org/cb");
+ request.addHeader("Authorization", getTokenHeaderValue(token));
+ request.addHeader("Origin", "https://example.org");
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ final UserInfoSuccessResponse response = parseSuccessResponse(result, UserInfoSuccessResponse.class);
+ Assert.assertEquals(response.getUserInfo().getSubject().getValue(), subject);
+ final UserInfo userInfo = response.getUserInfo();
+ Assert.assertNotNull(userInfo);
+ Assert.assertNull(userInfo.getEmailAddress());
+ Assert.assertNull(userInfo.getNickname());
+ Assert.assertNull(response.getUserInfoJWT());
+ }
+
+ @Test
+ public void testFails_invalidOrigin() throws URISyntaxException, NoSuchAlgorithmException, DataSealerException,
+ ComponentInitializationException, IOException {
+ final BearerAccessToken token = buildToken(clientId, subject, new Scope("openid"));
+ storeMetadata(storageService, clientId, "mockSecret", scope, "https://example.org/cb");
+ request.addHeader("Origin", "https://example.org:1234");
+ request.addHeader("Authorization", getTokenHeaderValue(token));
+ assertInvalidOriginResponse(flowExecutor.launchExecution(FLOW_ID, null, externalContext));
+ }
+
@Test
public void testFailsWhenNoOpenidScopeRequested() 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