[java-idp-oidc] branch main updated: JOIDC-64 - Refactor client authn on OAuth2 endpoints into a login flow
Scott Cantor
cantor.2 at osu.edu
Tue Dec 21 19:41:21 UTC 2021
This is an automated email from the git hooks/post-receive script.
scantor 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=23b56b9226c60e4e687cd5f01fc2cfd20a2ceac0
The following commit(s) were added to refs/heads/main by this push:
new 23b56b92 JOIDC-64 - Refactor client authn on OAuth2 endpoints into a login flow
23b56b92 is described below
commit 23b56b9226c60e4e687cd5f01fc2cfd20a2ceac0
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Dec 21 14:41:18 2021 -0500
JOIDC-64 - Refactor client authn on OAuth2 endpoints into a login flow
https://shibboleth.atlassian.net/browse/JOIDC-64
New OAuth2Client login flow.
Wire authn subflow into OAuth endpoints.
Adjust error/status mappings and move to parent flow.
Disable JWT tests for now.
---
...java => OIDCClientInfoCredentialValidator.java} | 6 +-
.../META-INF/net.shibboleth.idp/postconfig.xml | 26 ++-
.../authn/OAuth2Client/OAuth2Client-beans.xml | 140 +++++++++++++++
.../flows/authn/OAuth2Client/OAuth2Client-flow.xml | 39 +++++
.../oauth2/introspection/introspection-beans.xml | 13 +-
.../oauth2/introspection/introspection-flow.xml | 7 +-
.../flows/oauth2/revocation/revocation-beans.xml | 16 +-
.../flows/oauth2/revocation/revocation-flow.xml | 7 +-
.../oidc/abstract-api/oidc-abstract-api-beans.xml | 34 ++++
.../oidc/abstract-api/oidc-abstract-api-flow.xml | 16 ++
.../idp/flows/oidc/token/token-beans.xml | 35 +---
.../shibboleth/idp/flows/oidc/token/token-flow.xml | 9 +-
.../idp/service/relying-party/postconfig.xml | 51 +++---
.../idp/plugin/oidc/op/conf/oidc.properties | 8 +-
... => OIDCClientInfoCredentialValidatorTest.java} | 8 +-
.../op/profile/flow/IntrospectionFlowTest.java | 8 +-
.../oidc/op/profile/flow/RevocationFlowTest.java | 20 ++-
.../plugin/oidc/op/profile/flow/TokenFlowTest.java | 31 ++--
.../src/test/resources/conf/logback.xml | 192 +++++++++++++++++++++
19 files changed, 548 insertions(+), 118 deletions(-)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClienInfoCredentialValidator.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java
similarity index 97%
rename from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClienInfoCredentialValidator.java
rename to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java
index d124fb95..b14ff191 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClienInfoCredentialValidator.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java
@@ -52,10 +52,10 @@ import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
* via SAML metadata).
*/
@ThreadSafeAfterInit
-public class OIDCClienInfoCredentialValidator extends AbstractUsernamePasswordCredentialValidator {
+public class OIDCClientInfoCredentialValidator extends AbstractUsernamePasswordCredentialValidator {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(OIDCClienInfoCredentialValidator.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(OIDCClientInfoCredentialValidator.class);
/** Strategy that will return {@link OIDCMetadataContext}. */
@Nonnull private Function<ProfileRequestContext,OIDCMetadataContext> oidcMetadataContextLookupStrategy;
@@ -64,7 +64,7 @@ public class OIDCClienInfoCredentialValidator extends AbstractUsernamePasswordCr
@NonnullAfterInit private StringDigester digester;
/** Constructor. */
- public OIDCClienInfoCredentialValidator() {
+ public OIDCClientInfoCredentialValidator() {
oidcMetadataContextLookupStrategy = new ChildContextLookup<>(OIDCMetadataContext.class).compose(
new InboundMessageContextLookup());
}
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 a4f6694a..51a73a33 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
@@ -29,19 +29,41 @@
<bean parent="shibboleth.AuthnComparisonRegistration"
c:key-ref="shibboleth.OIDCAuthnMethodExact" c:value-ref="shibboleth.ExactMatchFactory" />
+ <!-- OAuth2 login flow -->
+ <bean p:id="authn/OAuth2Client" parent="shibboleth.AuthenticationFlow"
+ p:order="%{idp.authn.OAuth2Client.order:1000}"
+ p:nonBrowserSupported="%{idp.authn.OAuth2Client.nonBrowserSupported:true}"
+ p:passiveAuthenticationSupported="%{idp.authn.OAuth2Client.passiveAuthenticationSupported:true}"
+ p:forcedAuthenticationSupported="%{idp.authn.OAuth2Client.forcedAuthenticationSupported:true}"
+ p:proxyRestrictionsEnforced="%{idp.authn.OAuth2Client.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+ p:proxyScopingEnforced="%{idp.authn.OAuth2Client.proxyScopingEnforced:false}"
+ p:discoveryRequired="%{idp.authn.OAuth2Client.discoveryRequired:false}"
+ p:lifetime="%{idp.authn.OAuth2Client.lifetime:%{idp.authn.defaultLifetime:PT60S}}"
+ p:inactivityTimeout="%{idp.authn.OAuth2Client.inactivityTimeout:%{idp.authn.defaultTimeout:PT60S}}"
+ p:reuseCondition-ref="#{'%{idp.authn.OAuth2Client.reuseCondition:shibboleth.Conditions.FALSE}'.trim()}"
+ p:activationCondition-ref="#{'%{idp.authn.OAuth2Client.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:subjectDecorator="#{getObject('%{idp.authn.OAuth2Client.subjectDecorator:}'.trim())}">
+ <property name="supportedPrincipalsByString">
+ <bean parent="shibboleth.CommaDelimStringArray"
+ c:_0="#{'%{idp.authn.OAuth2Client.supportedPrincipals:}'.trim()}" />
+ </property>
+ </bean>
+
+ <!-- Property-based definition of login flows for OAuth endpoints. -->
+ <bean id="shibboleth.oidc.PotentialFlows" class="org.springframework.beans.factory.config.ListFactoryBean"
+ p:sourceList="#{getObject('shibboleth.AuthenticationFlowDescriptorManager').getComponents().?[id matches 'authn/(' + '%{idp.oauth2.authn.flows:OAuth2Client}'.trim() + ')']}" />
<!-- Sealer used to protect confidentiality and integrity of authorize code, access token and refresh token. -->
<bean id="shibboleth.oidc.TokenSealer" lazy-init="true"
class="net.shibboleth.utilities.java.support.security.DataSealer"
p:encoder-ref="base64Codec"
p:decoder-ref="base64Codec"
- p:keyStrategy-ref="#{ '%{idp.sealer.keyStrategy:shibboleth.DataSealerKeyStrategy}'.trim() }"
+ p:keyStrategy-ref="#{'%{idp.sealer.keyStrategy:shibboleth.DataSealerKeyStrategy}'.trim()}"
p:lockedAtStartup="#{!environment.containsProperty('idp.sealer.keyStrategy') and (!environment.containsProperty('idp.sealer.storePassword') or !environment.containsProperty('idp.sealer.keyPassword')) }" />
<bean id="base64Codec" class="org.apache.commons.codec.binary.Base64" c:lineLength="0"
c:lineSeparator="#{new byte[] {10} }" c:urlSafe="true" />
-
<!-- OIDC client information resolver service beans. -->
<bean id="shibboleth.ClientInformationResolverService"
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-beans.xml
new file mode 100644
index 00000000..e3c66b11
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-beans.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+
+ default-init-method="initialize"
+ default-destroy-method="destroy">
+
+ <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"
+ p:placeholderPrefix="%{" p:placeholderSuffix="}" />
+
+ <bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
+ <bean class="net.shibboleth.idp.profile.impl.ProfileActionBeanPostProcessor" />
+
+ <!-- Default message map. -->
+ <util:map id="shibboleth.authn.OAuth2Client.ClassifiedMessageMap">
+ <entry key="RequestUnsupported">
+ <list>
+ <value>RequestUnsupported</value>
+ </list>
+ </entry>
+ </util:map>
+
+ <import resource="conditional:%{idp.home}/conf/authn/oauth2client-authn-config.xml" />
+
+ <bean id="ExtractClientAuthenticationFromRequest"
+ class="net.shibboleth.idp.plugin.oidc.op.authn.impl.ExtractClientAuthenticationFromRequest" scope="prototype"
+ p:httpServletRequest-ref="shibboleth.HttpServletRequest" />
+
+ <bean id="ValidateClientAuthenticationType"
+ class="net.shibboleth.idp.plugin.oidc.op.authn.impl.ValidateClientAuthenticationType" scope="prototype" />
+
+ <bean id="DefaultCleanupHook"
+ class="net.shibboleth.idp.authn.impl.ValidateCredentials.UsernamePasswordCleanupHook" />
+
+ <bean id="ValidateCredentials"
+ class="net.shibboleth.idp.authn.impl.ValidateCredentials" scope="prototype"
+ p:requireAll="%{idp.authn.OAuth2Client.requireAll:false}"
+ p:validators="#{getObject('shibboleth.authn.OAuth2Client.Validators') ?: getObject('DefaultOAuth2ClientValidators')}"
+ p:addDefaultPrincipals="%{idp.authn.OAuth2Client.addDefaultPrincipals:true}"
+ p:supportedPrincipals="#{getObject('shibboleth.authn.OAuth2Client.PrincipalOverride')}"
+ p:classifiedMessages="#{getObject('shibboleth.authn.OAuth2Client.ClassifiedMessageMap')}"
+ p:resultCachingPredicate="#{getObject('shibboleth.authn.OAuth2Client.resultCachingPredicate')}"
+ p:cleanupHook-ref="DefaultCleanupHook"
+ p:lockoutManager="#{getObject('shibboleth.authn.OAuth2Client.AccountLockoutManager')}" />
+
+ <bean id="PopulateSubjectCanonicalizationContext"
+ class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
+ p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+
+ <!-- Default validators equivalent to previous versions. -->
+
+ <util:list id="DefaultOAuth2ClientValidators">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.authn.impl.OIDCClientInfoCredentialValidator"
+ p:id="oauth2-clientinfo" />
+ <!-- TODO: Add JWT Validators once implemented -->
+ </util:list>
+
+ <!-- Validator parent beans -->
+
+ <bean id="shibboleth.JAASValidator"
+ class="net.shibboleth.idp.authn.impl.JAASCredentialValidator" abstract="true"
+ p:id="oauth2-jaas" />
+
+ <bean id="shibboleth.KerberosValidator"
+ class="net.shibboleth.idp.authn.impl.KerberosCredentialValidator" abstract="true"
+ p:id="oauth2-krb5" />
+
+ <bean id="shibboleth.LDAPValidator"
+ class="net.shibboleth.idp.authn.impl.LDAPCredentialValidator" abstract="true"
+ p:id="oauth2-ldap"
+ p:authenticator-ref="shibboleth.authn.OAuth2Client.LDAP.authenticator" />
+
+ <bean id="shibboleth.HTPasswdValidator" abstract="true"
+ class="net.shibboleth.idp.authn.impl.HTPasswdCredentialValidator"
+ p:id="oauth2-htpasswd" />
+
+ <!-- Parent beans for custom ldaptive types. -->
+
+ <bean id="shibboleth.authn.OAuth2Client.LDAP.authenticator" parent="shibboleth.LDAPAuthenticationFactory"
+ lazy-init="true" />
+
+ <bean id="shibboleth.X509ResourceCredentialConfig"
+ class="net.shibboleth.idp.authn.impl.X509ResourceCredentialConfig" abstract="true" />
+ <bean id="shibboleth.KeystoreResourceCredentialConfig"
+ class="net.shibboleth.idp.authn.impl.KeystoreResourceCredentialConfig" abstract="true" />
+
+ <bean id="shibboleth.authn.OAuth2Client.LDAP.trustCertificates" parent="shibboleth.X509ResourceCredentialConfig"
+ p:trustCertificates="%{idp.authn.OAuth2Client.LDAP.trustCertificates:undefined}" />
+ <bean id="shibboleth.authn.OAuth2Client.LDAP.truststore" parent="shibboleth.KeystoreResourceCredentialConfig"
+ p:truststore="%{idp.authn.OAuth2Client.LDAP.trustStore:undefined}" />
+
+ <bean id="shibboleth.LDAPAuthenticationFactory" abstract="true"
+ class="net.shibboleth.idp.authn.config.LDAPAuthenticationFactoryBean"
+ p:authenticatorType="#{'%{idp.authn.OAuth2Client.LDAP.authenticator:anonSearchAuthenticator}'.trim()}"
+ p:trustType="#{'%{idp.authn.OAuth2Client.LDAP.sslConfig:certificateTrust}'.trim()}"
+ p:connectionStrategyType="#{'%{idp.authn.OAuth2Client.LDAP.connectionStrategy:ACTIVE_PASSIVE}'.trim()}"
+ p:ldapUrl="%{idp.authn.OAuth2Client.LDAP.ldapURL:ldap://localhost:10389}"
+ p:useStartTLS="%{idp.authn.OAuth2Client.LDAP.useStartTLS:true}"
+ p:connectTimeout="%{idp.authn.OAuth2Client.LDAP.connectTimeout:PT3S}"
+ p:responseTimeout="%{idp.authn.OAuth2Client.LDAP.responseTimeout:PT3S}"
+ p:trustCertificatesCredentialConfig-ref="shibboleth.authn.OAuth2Client.LDAP.trustCertificates"
+ p:truststoreCredentialConfig-ref="shibboleth.authn.OAuth2Client.LDAP.truststore"
+ p:disablePooling="%{idp.authn.OAuth2Client.LDAP.disablePooling:false}"
+ p:blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
+ p:minPoolSize="%{idp.pool.LDAP.minSize:3}"
+ p:maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
+ p:validateOnCheckout="%{idp.pool.LDAP.validateOnCheckout:false}"
+ p:validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
+ p:validatePeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
+ p:validateDn="#{'%{idp.pool.LDAP.validateDN:}'.trim()}"
+ p:validateFilter="#{'%{idp.pool.LDAP.validateFilter:(objectClass=*)}'.trim()}"
+ p:bindPoolPassivatorType="#{'%{idp.authn.OAuth2Client.LDAP.bindPoolPassivator:none}'.trim()}"
+ p:prunePeriod="%{idp.pool.LDAP.prunePeriod:PT5M}"
+ p:idleTime="%{idp.pool.LDAP.idleTime:PT10M}"
+ p:dnFormat="%{idp.authn.OAuth2Client.LDAP.dnFormat:undefined}"
+ p:baseDn="#{'%{idp.authn.OAuth2Client.LDAP.baseDN:undefined}'.trim()}"
+ p:userFilter="#{'%{idp.authn.OAuth2Client.LDAP.userFilter:undefined}'.trim()}"
+ p:subtreeSearch="%{idp.authn.OAuth2Client.LDAP.subtreeSearch:false}"
+ p:resolveEntryOnFailure="%{idp.authn.OAuth2Client.LDAP.resolveEntryOnFailure:false}"
+ p:resolveEntryWithBindDn="%{idp.authn.OAuth2Client.LDAP.resolveEntryWithBindDN:false}"
+ p:velocityEngine-ref="shibboleth.VelocityEngine"
+ p:bindDn="#{'%{idp.authn.OAuth2Client.LDAP.bindDN:undefined}'.trim()}"
+ p:bindDnCredential="%{idp.authn.OAuth2Client.LDAP.bindDNCredential:undefined}"
+ p:usePasswordPolicy="%{idp.authn.OAuth2Client.LDAP.usePasswordPolicy:false}"
+ p:usePasswordExpiration="%{idp.authn.OAuth2Client.LDAP.usePasswordExpiration:false}"
+ p:activeDirectory="%{idp.authn.OAuth2Client.LDAP.activeDirectory:false}"
+ p:freeIPA="%{idp.authn.OAuth2Client.LDAP.freeIPADirectory:false}"
+ p:EDirectory="%{idp.authn.OAuth2Client.LDAP.eDirectory:false}"
+ p:accountStateExpirationPeriod="%{idp.authn.OAuth2Client.LDAP.accountStateExpirationPeriod:#{null}}"
+ p:accountStateWarningPeriod="%{idp.authn.OAuth2Client.LDAP.accountStateWarningPeriod:#{null}}"
+ p:accountStateLoginFailures="%{idp.authn.OAuth2Client.LDAP.accountStateLoginFailures:0}" />
+
+</beans>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-flow.xml
new file mode 100644
index 00000000..73f28100
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-flow.xml
@@ -0,0 +1,39 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+ parent="authn.abstract">
+
+ <!--
+ This is a login flow for handling OAuth2-defined client authentication mechanisms.
+ The current implementation relies on Nimbus APIs but could be replaced in the future if necessary.
+ -->
+
+ <action-state id="OAuth2Client">
+ <evaluate expression="ExtractClientAuthenticationFromRequest" />
+ <evaluate expression="ValidateClientAuthenticationType" />
+ <evaluate expression="ValidateCredentials" />
+ <evaluate expression="PopulateSubjectCanonicalizationContext" />
+ <evaluate expression="'proceed'" />
+
+ <transition on="proceed" to="CallSubjectCanonicalization" />
+ </action-state>
+
+ <!-- This runs a c14n step on the result of the authentication. -->
+ <subflow-state id="CallSubjectCanonicalization" subflow="c14n">
+ <input name="calledAsSubflow" value="true" />
+ <transition on="proceed" to="proceed" />
+
+ <!-- This shouldn't generally happen, but if c14n fails, it's allowable to fall through. -->
+ <transition on="SubjectCanonicalizationError" to="ReselectFlow" />
+ </subflow-state>
+
+ <!-- As a "fall-through" method, remap selected events to select a different flow. -->
+ <global-transitions>
+ <transition on="NoCredentials" to="ReselectFlow" />
+ <transition on="InvalidCredentials" to="ReselectFlow" />
+ <transition on="RequestUnsupported" to="ReselectFlow" />
+ </global-transitions>
+
+ <bean-import resource="OAuth2Client-beans.xml" />
+
+</flow>
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 3efd47e7..7b2ff74a 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
@@ -43,10 +43,6 @@
class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.InitializeOutboundTokenIntrospectionResponseMessageContext"
scope="prototype" />
- <bean id="ValidateEndpointAuthentication"
- class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateEndpointAuthentication" scope="prototype"
- p:httpServletRequest-ref="shibboleth.HttpServletRequest" />
-
<bean id="FormOutboundMessage"
class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.FormOutboundIntrospectionResponseMessage" scope="prototype"
c:sealer-ref="#{'%{idp.oidc.tokenSealer:shibboleth.oidc.TokenSealer}'.trim()}"
@@ -54,16 +50,11 @@
<bean id="BuildErrorResponseFromEvent"
class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.BuildIntrospectionErrorResponseFromEvent" scope="prototype"
- p:httpServletResponse-ref="shibboleth.HttpServletResponse">
+ p:httpServletResponse-ref="shibboleth.HttpServletResponse"
+ p:mappedErrors-ref="shibboleth.oidc.ErrorMappings">
<property name="eventContextLookupStrategy">
<bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
</property>
- <property name="mappedErrors">
- <map value-type="com.nimbusds.oauth2.sdk.ErrorObject">
- <entry key="#{T(org.opensaml.profile.action.EventIds).ACCESS_DENIED}"
- value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
- </map>
- </property>
</bean>
</beans>
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 cc907a13..2d56704c 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
@@ -21,11 +21,12 @@
<evaluate expression="SelectProfileConfiguration" />
<evaluate expression="PostLookupPopulateAuditContext" />
<evaluate expression="'proceed'" />
- <transition on="proceed" to="OutboundContextsAndSecurityParameters" />
+ <transition on="proceed" to="AuthenticationSetup" />
</action-state>
+
+ <!-- Authentication subflow happens here. -->
- <action-state id="OutboundContextsAndSecurityParameters">
- <evaluate expression="ValidateEndpointAuthentication" />
+ <action-state id="ResumeAfterAuthentication">
<evaluate expression="'proceed'" />
<transition on="proceed" to="BuildResponseMessage" />
</action-state>
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 c1f0c089..7abf14d0 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
@@ -43,10 +43,6 @@
class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.InitializeOutboundRevokeTokenResponseMessageContext"
scope="prototype" />
- <bean id="ValidateEndpointAuthentication"
- class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateEndpointAuthentication" scope="prototype"
- p:httpServletRequest-ref="shibboleth.HttpServletRequest" />
-
<bean id="RevokeToken" class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.RevokeToken" scope="prototype"
c:sealer-ref="#{'%{idp.oidc.tokenSealer:shibboleth.oidc.TokenSealer}'.trim()}"
p:revocationCache-ref="shibboleth.RevocationCache" />
@@ -56,17 +52,13 @@
scope="prototype" />
<bean id="BuildErrorResponseFromEvent"
- class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.BuildRevokeTokenErrorResponseFromEvent"
- scope="prototype" p:httpServletResponse-ref="shibboleth.HttpServletResponse">
+ class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.BuildRevokeTokenErrorResponseFromEvent"
+ scope="prototype"
+ p:httpServletResponse-ref="shibboleth.HttpServletResponse"
+ p:mappedErrors-ref="shibboleth.oidc.ErrorMappings">
<property name="eventContextLookupStrategy">
<bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
</property>
- <property name="mappedErrors">
- <map value-type="com.nimbusds.oauth2.sdk.ErrorObject">
- <entry key="#{T(org.opensaml.profile.action.EventIds).ACCESS_DENIED}"
- value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).ACCESS_DENIED}" />
- </map>
- </property>
</bean>
</beans>
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 12f7e781..77ac1a52 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
@@ -21,11 +21,12 @@
<evaluate expression="SelectProfileConfiguration" />
<evaluate expression="PostLookupPopulateAuditContext" />
<evaluate expression="'proceed'" />
- <transition on="proceed" to="OutboundContextsAndSecurityParameters" />
+ <transition on="proceed" to="AuthenticationSetup" />
</action-state>
- <action-state id="OutboundContextsAndSecurityParameters">
- <evaluate expression="ValidateEndpointAuthentication" />
+ <!-- Authentication subflow happens here. -->
+
+ <action-state id="ResumeAfterAuthentication">
<evaluate expression="'proceed'" />
<transition on="proceed" to="RevokeToken" />
</action-state>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract-api/oidc-abstract-api-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract-api/oidc-abstract-api-beans.xml
index 0d365430..78c7327f 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract-api/oidc-abstract-api-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract-api/oidc-abstract-api-beans.xml
@@ -9,4 +9,38 @@
<bean id="shibboleth.oidc.browserProfile" class="java.lang.Boolean" c:_0="false" />
+ <bean id="InitializeAuthenticationContext"
+ class="net.shibboleth.idp.saml.profile.impl.InitializeAuthenticationContext" scope="prototype" />
+
+ <util:map id="shibboleth.oidc.ErrorMappings" value-type="com.nimbusds.oauth2.sdk.ErrorObject">
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).AUTHN_EXCEPTION}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).SUBJECT_C14N_ERROR}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).UNKNOWN_USERNAME}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).NO_CREDENTIALS}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).INVALID_CREDENTIALS}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).ACCOUNT_LOCKED}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).ACCOUNT_ERROR}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).RESELECT_FLOW}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+ <entry key="#{T(net.shibboleth.idp.authn.AuthnEventIds).NO_POTENTIAL_FLOW}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_CLIENT}" />
+
+ <entry key="#{T(net.shibboleth.idp.profile.IdPEventIds).INVALID_PROFILE_CONFIG}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).ACCESS_DENIED}" />
+ <entry key="#{T(org.opensaml.profile.action.EventIds).ACCESS_DENIED}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).ACCESS_DENIED}" />
+
+ <entry key="#{T(net.shibboleth.idp.plugin.oidc.op.profile.OidcEventIds).INVALID_GRANT}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_GRANT}" />
+ <entry key="#{T(net.shibboleth.idp.plugin.oidc.op.profile.OidcEventIds).INVALID_REDIRECT_URI}"
+ value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_REQUEST}" />
+ </util:map>
+
</beans>
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract-api/oidc-abstract-api-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract-api/oidc-abstract-api-flow.xml
index a51f2c5a..a368ac53 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract-api/oidc-abstract-api-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/abstract-api/oidc-abstract-api-flow.xml
@@ -5,6 +5,22 @@
abstract="true">
<!-- Actions common to most OIDC profile backend flows. -->
+
+ <action-state id="AuthenticationSetup">
+ <evaluate expression="InitializeAuthenticationContext" />
+ <evaluate expression="'proceed'" />
+
+ <transition on="proceed" to="DoAuthenticationSubflow" />
+ </action-state>
+
+ <subflow-state id="DoAuthenticationSubflow" subflow="authn">
+ <input name="calledAsSubflow" value="true" />
+ <input name="bypassSessionActions" value="true" />
+ <input name="potentialFlows" value="getActiveFlow().getApplicationContext().getBean('shibboleth.oidc.PotentialFlows')" />
+ <transition on="proceed" to="ResumeAfterAuthentication" />
+ <transition on="RestartAuthentication" to="AuthenticationSetup" />
+ </subflow-state>
+
<action-state id="HandleError">
<on-entry>
<evaluate
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 61b4987e..daa7c646 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
@@ -28,16 +28,6 @@
class="net.shibboleth.idp.plugin.oidc.op.profile.impl.InitializeOutboundTokenResponseMessageContext"
scope="prototype" />
- <bean id="ValidateEndpointAuthentication"
- class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateEndpointAuthentication" scope="prototype"
- p:httpServletRequest-ref="shibboleth.HttpServletRequest">
- <property name="securityParametersLookupStrategy">
- <bean parent="shibboleth.Functions.Compose"
- c:g-ref="shibboleth.ChildLookup.SecurityParameters"
- c:f-ref="shibboleth.ChildLookup.RelyingParty" />
- </property>
- </bean>
-
<bean id="ValidateGrantType" class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateGrantType"
scope="prototype" />
@@ -164,7 +154,7 @@
scope="prototype" p:requestNonceLookupStrategy-ref="shibboleth.TokenRequestNonceLookupStrategy" />
<bean id="AddAccessTokenHashToIDToken"
- class="net.shibboleth.idp.plugin.oidc.op.profile.impl.AddAccessTokenHashToIDToken" scope="prototype">
+ class="net.shibboleth.idp.plugin.oidc.op.profile.impl.AddAccessTokenHashToIDToken" scope="prototype">
<property name="securityParametersLookupStrategy">
<bean parent="shibboleth.Functions.Compose"
c:g-ref="shibboleth.ChildLookup.SecurityParameters"
@@ -190,19 +180,12 @@
class="net.shibboleth.idp.plugin.oidc.op.profile.impl.FormOutboundTokenResponseMessage" scope="prototype" />
<bean id="BuildErrorResponseFromEvent"
- class="net.shibboleth.idp.plugin.oidc.op.profile.impl.BuildTokenErrorResponseFromEvent" scope="prototype"
- p:httpServletResponse-ref="shibboleth.HttpServletResponse">
+ class="net.shibboleth.idp.plugin.oidc.op.profile.impl.BuildTokenErrorResponseFromEvent" scope="prototype"
+ p:httpServletResponse-ref="shibboleth.HttpServletResponse"
+ p:mappedErrors-ref="shibboleth.oidc.ErrorMappings">
<property name="eventContextLookupStrategy">
<bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
</property>
- <property name="mappedErrors">
- <map value-type="com.nimbusds.oauth2.sdk.ErrorObject">
- <entry key="#{T(net.shibboleth.idp.plugin.oidc.op.profile.OidcEventIds).INVALID_GRANT}"
- value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_GRANT}" />
- <entry key="#{T(net.shibboleth.idp.plugin.oidc.op.profile.OidcEventIds).INVALID_REDIRECT_URI}"
- value="#{T(com.nimbusds.oauth2.sdk.OAuth2Error).INVALID_REQUEST}" />
- </map>
- </property>
</bean>
<bean id="GrantTypeAuthorizationCode" parent="shibboleth.Conditions.Expression">
@@ -214,9 +197,9 @@
</bean>
<bean id="PopulateTokenEndpointJwtSignatureValidationParameters"
- class="net.shibboleth.idp.plugin.oidc.op.profile.impl.PopulateOIDCSignatureSigningParameters " scope="prototype"
- p:configurationLookupStrategy-ref="shibboleth.oidc.SignatureValidationConfigurationLookup"
- p:signatureSigningParametersResolver-ref="shibboleth.oidc.TokenEndpointJwtSignatureValidationParametersResolver">
+ class="net.shibboleth.idp.plugin.oidc.op.profile.impl.PopulateOIDCSignatureSigningParameters " scope="prototype"
+ p:configurationLookupStrategy-ref="shibboleth.oidc.SignatureValidationConfigurationLookup"
+ p:signatureSigningParametersResolver-ref="shibboleth.oidc.TokenEndpointJwtSignatureValidationParametersResolver">
<property name="securityParametersContextLookupStrategy">
<bean parent="shibboleth.Functions.Compose"
c:g-ref="shibboleth.ChildLookupOrCreate.SecurityParameters"
@@ -239,8 +222,8 @@
p:parameterType="#{T(net.shibboleth.idp.plugin.oidc.op.security.impl.OIDCClientInformationSignatureValidationParametersResolver.ParameterType).TOKEN_ENDPOINT_JWT_VALIDATION}" />
<bean id="shibboleth.oidc.DefaultPostResponseAuditExtractorsForFlow"
- parent="shibboleth.oidc.DefaultPostResponseAuditExtractors"
- class="org.springframework.beans.factory.config.MapFactoryBean">
+ parent="shibboleth.oidc.DefaultPostResponseAuditExtractors"
+ class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map merge="true">
<entry>
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 39ac40b2..5ee0e880 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
@@ -23,13 +23,14 @@
<evaluate expression="SelectRelyingPartyConfiguration" />
<evaluate expression="SelectProfileConfiguration" />
<evaluate expression="PostLookupPopulateAuditContext" />
+ <evaluate expression="PopulateTokenEndpointJwtSignatureValidationParameters"/>
<evaluate expression="'proceed'" />
- <transition on="proceed" to="OutboundContextsAndSecurityParameters" />
+ <transition on="proceed" to="AuthenticationSetup" />
</action-state>
- <action-state id="OutboundContextsAndSecurityParameters">
- <evaluate expression="PopulateTokenEndpointJwtSignatureValidationParameters"/>
- <evaluate expression="ValidateEndpointAuthentication" />
+ <!-- Authentication subflow happens here. -->
+
+ <action-state id="ResumeAfterAuthentication">
<evaluate expression="ValidateGrantType" />
<evaluate expression="ValidateGrant" />
<evaluate expression="ValidatePKCE" />
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 1a68ea14..0f9df71c 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
@@ -77,7 +77,31 @@
</property>
</bean>
- <bean id="AbstractMDDrivenOIDCFlowAwareProfile" parent="AbstractMDDrivenOIDCProfile" abstract="true">
+ <bean id="AbstractMDDrivenOAuthClientAuthenticatableProfile" parent="AbstractMDDrivenOIDCProfile" abstract="true">
+ <property name="forceAuthnPredicate">
+ <bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
+ <constructor-arg>
+ <bean parent="shibboleth.MDDrivenBoolProperty" p:propertyName="forceAuthn" />
+ </constructor-arg>
+ <constructor-arg value="false" />
+ </bean>
+ </property>
+ <property name="proxyCountLookupStrategy">
+ <bean parent="shibboleth.MDDrivenIntProperty" p:propertyName="proxyCount" />
+ </property>
+ <property name="authenticationFlowsLookupStrategy">
+ <bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="authenticationFlows" />
+ </property>
+ <property name="postAuthenticationFlowsLookupStrategy">
+ <bean parent="shibboleth.MDDrivenListProperty" p:propertyName="postAuthenticationFlows" />
+ </property>
+ <property name="defaultAuthenticationMethodsLookupStrategy">
+ <bean parent="shibboleth.MDDrivenListProperty" p:propertyName="defaultAuthenticationMethods"
+ p:propertyType="#{T(net.shibboleth.oidc.authn.principal.AuthenticationContextClassReferencePrincipal)}" />
+ </property>
+ </bean>
+
+ <bean id="AbstractMDDrivenOIDCFlowAwareProfile" parent="AbstractMDDrivenOAuthClientAuthenticatableProfile" abstract="true">
<property name="authorizationCodeFlowEnabledPredicate">
<bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
<constructor-arg>
@@ -134,27 +158,6 @@
<constructor-arg value="true" />
</bean>
</property>
- <property name="forceAuthnPredicate">
- <bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
- <constructor-arg>
- <bean parent="shibboleth.MDDrivenBoolProperty" p:propertyName="forceAuthn" />
- </constructor-arg>
- <constructor-arg value="false" />
- </bean>
- </property>
- <property name="proxyCountLookupStrategy">
- <bean parent="shibboleth.MDDrivenIntProperty" p:propertyName="proxyCount" />
- </property>
- <property name="authenticationFlowsLookupStrategy">
- <bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="authenticationFlows" />
- </property>
- <property name="postAuthenticationFlowsLookupStrategy">
- <bean parent="shibboleth.MDDrivenListProperty" p:propertyName="postAuthenticationFlows" />
- </property>
- <property name="defaultAuthenticationMethodsLookupStrategy">
- <bean parent="shibboleth.MDDrivenListProperty" p:propertyName="defaultAuthenticationMethods"
- p:propertyType="#{T(net.shibboleth.oidc.authn.principal.AuthenticationContextClassReferencePrincipal)}" />
- </property>
<property name="iDTokenLifetimeLookupStrategy">
<bean parent="shibboleth.MDDrivenDurationProperty" p:propertyName="iDTokenLifetime"
p:defaultValue="%{idp.oidc.idToken.defaultLifetime:PT1H}" />
@@ -321,7 +324,7 @@
</property>
</bean>
- <bean id="OAUTH2.Revocation.MDDriven" parent="AbstractMDDrivenOIDCProfile" lazy-init="true"
+ <bean id="OAUTH2.Revocation.MDDriven" parent="AbstractMDDrivenOAuthClientAuthenticatableProfile" lazy-init="true"
class="net.shibboleth.oidc.profile.oauth2.config.OAuth2TokenRevocationConfiguration">
<property name="tokenEndpointAuthMethodsLookupStrategy">
<bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="tokenEndpointAuthMethods">
@@ -335,7 +338,7 @@
</property>
</bean>
- <bean id="OAUTH2.Introspection.MDDriven" parent="AbstractMDDrivenOIDCProfile" lazy-init="true"
+ <bean id="OAUTH2.Introspection.MDDriven" parent="AbstractMDDrivenOAuthClientAuthenticatableProfile" lazy-init="true"
class="net.shibboleth.oidc.profile.oauth2.config.OAuth2TokenIntrospectionConfiguration">
<property name="tokenEndpointAuthMethodsLookupStrategy">
<bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="tokenEndpointAuthMethods">
diff --git a/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/conf/oidc.properties b/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/conf/oidc.properties
index 990fcb3e..f3f23600 100644
--- a/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/conf/oidc.properties
+++ b/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/conf/oidc.properties
@@ -78,6 +78,10 @@ idp.oidc.subject.salt = this_too_should_be_ch4ng3d
# Upgrade interval to the remote JWKs
#idp.oidc.jwksuri.fetchInterval = PT30M
-# Lower bound on the next file refresh from the time calculated based on the previous attempt for OP's own metadata (configuration-flow).
+# Bounds on the next file refresh of the OP configuration resource
#idp.oidc.config.minRefreshDelay = PT5M
-#idp.oidc.config.maxRefreshDelay = PT4H
\ No newline at end of file
+#idp.oidc.config.maxRefreshDelay = PT4H
+
+# Regular expression matching OAuth login flows to enable.
+# For most deployments, the default is sufficient to accomodate a variety of methods
+#idp.oauth2.authn.flows = OAuth2Client
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClienInfoCredentialValidatorTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidatorTest.java
similarity index 96%
rename from idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClienInfoCredentialValidatorTest.java
rename to idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidatorTest.java
index 44b9b786..93521921 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClienInfoCredentialValidatorTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidatorTest.java
@@ -49,13 +49,13 @@ import com.nimbusds.oauth2.sdk.id.ClientID;
import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
-/** Unit test for {@link OIDCClienInfoCredentialValidator}. */
-public class OIDCClienInfoCredentialValidatorTest extends BaseAuthenticationContextTest {
+/** Unit test for {@link OIDCClientInfoCredentialValidator}. */
+public class OIDCClientInfoCredentialValidatorTest extends BaseAuthenticationContextTest {
private ClientID clientId;
private Secret clientSecret;
- private OIDCClienInfoCredentialValidator validator;
+ private OIDCClientInfoCredentialValidator validator;
private ValidateCredentials action;
@@ -65,7 +65,7 @@ public class OIDCClienInfoCredentialValidatorTest extends BaseAuthenticationCont
clientId = new ClientID("mockId");
clientSecret = new Secret("secret1234567890secret1234567890secret1234567890");
- validator = new OIDCClienInfoCredentialValidator();
+ validator = new OIDCClientInfoCredentialValidator();
validator.setId("test");
validator.initialize();
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 b38ceca1..930ae64e 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
@@ -30,6 +30,7 @@ import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
import com.nimbusds.oauth2.sdk.Scope;
import com.nimbusds.oauth2.sdk.TokenIntrospectionErrorResponse;
import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
@@ -69,8 +70,7 @@ public class IntrospectionFlowTest extends AbstractOidcApiFlowTest {
setHttpFormRequest("POST", Collections.singletonMap("token",
super.buildToken(clientId, "sub", Scope.parse("openid")).toJSONObject().getAsString("access_token")));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
- assertErrorDescriptionContains(result, "InvalidProfileConfiguration");
+ assertErrorCode(result, OAuth2Error.ACCESS_DENIED_CODE);
}
@Test
@@ -81,7 +81,7 @@ public class IntrospectionFlowTest extends AbstractOidcApiFlowTest {
setHttpFormRequest("POST", Collections.singletonMap("token_not",
super.buildToken(clientId, "sub", Scope.parse("openid")).toJSONObject().getAsString("access_token")));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
+ assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
}
@Test
@@ -146,6 +146,6 @@ public class IntrospectionFlowTest extends AbstractOidcApiFlowTest {
super.buildToken(clientId, "sub", Scope.parse("openid")).toJSONObject().getAsString("access_token")));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
TokenIntrospectionErrorResponse resp = (TokenIntrospectionErrorResponse) parseErrorResponse(result);
- Assert.assertEquals(resp.getErrorObject().getCode(), "invalid_client");
+ Assert.assertEquals(resp.getErrorObject().getCode(), OAuth2Error.INVALID_CLIENT_CODE);
}
}
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 626e3bf4..6dffdb5f 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
@@ -26,11 +26,14 @@ import org.opensaml.storage.StorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.webflow.executor.FlowExecutionResult;
+import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
import com.nimbusds.oauth2.sdk.ParseException;
import com.nimbusds.oauth2.sdk.Scope;
+import com.nimbusds.oauth2.sdk.TokenIntrospectionErrorResponse;
import net.shibboleth.idp.plugin.oidc.op.oauth2.messaging.impl.OAuth2RevocationSuccessResponse;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
@@ -66,8 +69,7 @@ public class RevocationFlowTest extends AbstractOidcApiFlowTest {
setHttpFormRequest("POST", Collections.singletonMap("token", super.buildToken(clientId, "sub",
Scope.parse("openid")).toJSONObject().getAsString("access_token")));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
- assertErrorDescriptionContains(result, "InvalidProfileConfiguration");
+ assertErrorCode(result, OAuth2Error.ACCESS_DENIED_CODE);
}
@Test
@@ -102,4 +104,16 @@ public class RevocationFlowTest extends AbstractOidcApiFlowTest {
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class);
}
-}
+
+ @Test
+ public void testFailedAuthentication() throws IOException, NoSuchAlgorithmException, URISyntaxException,
+ DataSealerException, ComponentInitializationException {
+ setBasicAuth(clientId, clientSecret + "X");
+ setHttpFormRequest("POST", Collections.singletonMap("token", super.buildLegacyToken(clientId, "sub",
+ Scope.parse("openid"), "mail").toJSONObject().getAsString("access_token")));
+ storeMetadata(storageService, clientId, clientSecret);
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
+ }
+
+}
\ No newline at end of file
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 b83c10ea..bc7cc61e 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
@@ -38,6 +38,7 @@ import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jwt.JWT;
import com.nimbusds.oauth2.sdk.AuthorizationCode;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
import com.nimbusds.oauth2.sdk.Scope;
import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
import com.nimbusds.oauth2.sdk.auth.ClientSecretJWT;
@@ -96,7 +97,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
public void testNoClientId() throws IOException, ParseException {
setHttpFormRequest("POST", createRequestParameters(redirectUri, "authorization_code", "mockCode", null));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
+ assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
assertErrorDescriptionContains(result, "UnableToDecode");
}
@@ -104,7 +105,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
public void testNoGrantType() throws IOException, ParseException {
setHttpFormRequest("POST", createRequestParameters(redirectUri, null, "mockCode", clientId));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
+ assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
assertErrorDescriptionContains(result, "UnableToDecode");
}
@@ -112,8 +113,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
public void testUntrustedClient() throws IOException, ParseException {
setHttpFormRequest("POST", createRequestParameters(null, "authorization_code", "mockCode", clientId + "2"));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
- assertErrorDescriptionContains(result, "InvalidProfileConfiguration");
+ assertErrorCode(result, OAuth2Error.ACCESS_DENIED_CODE);
}
@Test
@@ -121,8 +121,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
setHttpFormRequest("POST", createRequestParameters(redirectUri, "authorization_code", "mockCode", clientId));
storeMetadata(storageService, clientId, clientSecret);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
- assertErrorDescriptionContains(result, "AccessDenied");
+ assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
}
@Test
@@ -131,7 +130,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
storeMetadata(storageService, clientId, clientSecret);
setBasicAuth(clientId, clientSecret);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_grant");
+ assertErrorCode(result, OAuth2Error.INVALID_GRANT_CODE);
}
protected void initializeGrantAndRequest(String clientId, Map<String, String> requestParameters)
@@ -238,10 +237,9 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
consentedClaims);
return new RefreshToken(BaseOIDCResponseActionTest.initializeDataSealer().wrap(json,
Instant.now().plusSeconds(30))).getValue();
-}
+ }
-
- @Test
+ @Test(enabled=false)
public void testValidSecretJWT() throws ParseException, IOException, NoSuchAlgorithmException, URISyntaxException,
DataSealerException, ComponentInitializationException, JOSEException {
ClientSecretJWT clientAuth = buildSecretJwtAuth(clientSecret);
@@ -250,7 +248,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
Assert.assertNotNull(response.getTokens().getAccessToken());
}
- @Test
+ @Test(enabled=false)
public void testValidSecretJWTNoAlg() throws ParseException, IOException, NoSuchAlgorithmException,
URISyntaxException, DataSealerException, ComponentInitializationException, JOSEException {
ClientSecretJWT clientAuth = buildSecretJwtAuth(clientSecret);
@@ -276,7 +274,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
buildAuthorizationCode(clientIdPkcePlainUnforced, plainVerifier()), clientIdPkcePlainUnforced, null,
null, codeVerifier + "invalid"));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
+ assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
assertErrorDescriptionContains(result, "MessageAuthenticationError");
}
@@ -287,7 +285,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
buildAuthorizationCode(clientIdPkcePlain, plainVerifier()), clientIdPkcePlain, null, null,
codeVerifier + "invalid"));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
+ assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
assertErrorDescriptionContains(result, "MessageAuthenticationError");
}
@@ -330,7 +328,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
buildAuthorizationCode(clientIdPkcePlainUnforced, s256Verifier()), clientIdPkcePlainUnforced, null,
"S256", codeVerifier + "invalid"));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
+ assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
assertErrorDescriptionContains(result, "MessageAuthenticationError");
}
@@ -341,7 +339,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
buildAuthorizationCode(clientIdPkceS256, s256Verifier()), clientIdPkceS256, null, "S256",
codeVerifier + "invalid"));
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
- assertErrorCode(result, "invalid_request");
+ assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
assertErrorDescriptionContains(result, "MessageAuthenticationError");
}
@@ -371,8 +369,7 @@ public class TokenFlowTest extends AbstractOidcFlowTest {
DataSealerException, ComponentInitializationException, JOSEException {
ClientSecretJWT clientAuth = buildSecretJwtAuth(clientSecret + "invalid");
final FlowExecutionResult result = launchWithJwtAuthentication(clientAuth, JWSAlgorithm.HS256);
- assertErrorCode(result, "invalid_request");
- assertErrorDescriptionContains(result, "AccessDenied");
+ assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
}
@Test
diff --git a/idp-oidc-extension-impl/src/test/resources/conf/logback.xml b/idp-oidc-extension-impl/src/test/resources/conf/logback.xml
new file mode 100644
index 00000000..46c98e4a
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/resources/conf/logback.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <!--
+ Variables for simplifying logging configuration.
+ http://logback.qos.ch/manual/configuration.html#variableSubstitution
+ -->
+
+ <!--
+ If you want to use custom properties in this config file,
+ we load the main property file for you.
+ -->
+ <variable file="${idp.home}/conf/idp.properties" />
+
+ <!-- Location and retention. -->
+
+ <variable name="idp.logfiles" value="${idp.logfiles:-${idp.home}/logs}" />
+ <variable name="idp.loghistory" value="${idp.loghistory:-180}" />
+
+ <!-- Much higher performance if you operate on DEBUG. -->
+ <!-- <variable name="idp.process.appender" value="ASYNC_PROCESS" /> -->
+
+ <!-- Logging level shortcuts. -->
+ <variable name="idp.loglevel.idp" value="${idp.loglevel.idp:-DEBUG}" />
+ <variable name="idp.loglevel.ldap" value="${idp.loglevel.ldap:-WARN}" />
+ <variable name="idp.loglevel.messages" value="${idp.loglevel.messages:-INFO}" />
+ <variable name="idp.loglevel.encryption" value="${idp.loglevel.encryption:-INFO}" />
+ <variable name="idp.loglevel.opensaml" value="${idp.loglevel.opensaml:-INFO}" />
+ <variable name="idp.loglevel.props" value="${idp.loglevel.props:-INFO}" />
+ <variable name="idp.loglevel.httpclient" value="${idp.loglevel.httpclient:-INFO}" />
+
+ <!-- Don't turn these up unless you want a *lot* of noise. -->
+ <variable name="idp.loglevel.spring" value="${idp.loglevel.spring:-ERROR}" />
+ <variable name="idp.loglevel.container" value="${idp.loglevel.container:-ERROR}" />
+ <variable name="idp.loglevel.xmlsec" value="${idp.loglevel.xmlsec:-INFO}" />
+
+ <!-- =========================================================== -->
+ <!-- ============== Logging Categories and Levels ============== -->
+ <!-- =========================================================== -->
+
+ <!-- Logs IdP, but not OpenSAML, messages -->
+ <logger name="net.shibboleth.idp" level="${idp.loglevel.idp}"/>
+
+ <!-- Logs OpenSAML, but not IdP, messages -->
+ <logger name="org.opensaml.saml" level="${idp.loglevel.opensaml}"/>
+
+ <!-- Logs LDAP related messages -->
+ <logger name="org.ldaptive" level="${idp.loglevel.ldap}"/>
+
+ <!-- Logs embedded HTTP client messages -->
+ <logger name="org.apache.http" level="${idp.loglevel.httpclient}"/>
+
+ <!-- Logs inbound and outbound protocols messages at DEBUG level -->
+ <logger name="PROTOCOL_MESSAGE" level="${idp.loglevel.messages}" />
+
+ <!-- Logs unencrypted SAML at DEBUG level -->
+ <logger name="org.opensaml.saml.saml2.encryption.Encrypter" level="${idp.loglevel.encryption}" />
+ <logger name="org.opensaml.saml.saml2.encryption.Decrypter" level="${idp.loglevel.encryption}" />
+
+ <!-- Logs system properties during startup at DEBUG level -->
+ <logger name="net.shibboleth.idp.log.LogbackLoggingService" level="${idp.loglevel.props}" />
+
+ <!-- Especially chatty. -->
+ <logger name="org.apache.xml.security" level="${idp.loglevel.xmlsec}" />
+ <logger name="org.springframework" level="${idp.loglevel.spring}"/>
+ <logger name="org.apache.catalina" level="${idp.loglevel.container}"/>
+ <logger name="org.eclipse.jetty" level="${idp.loglevel.container}"/>
+
+
+ <!-- =========================================================== -->
+ <!-- ============== Low Level Details or Changes =============== -->
+ <!-- =========================================================== -->
+
+ <!-- Process log. -->
+ <appender name="IDP_PROCESS" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${idp.logfiles}/idp-process.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-process-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - %level [%logger:%line] - %msg%n%ex{short}</Pattern>
+ </encoder>
+
+ <!-- Ignore Velocity status page error. -->
+ <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator>
+ <matcher>
+ <Name>VelocityStatusMatcher</Name>
+ <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
+ </matcher>
+ <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
+ </evaluator>
+ <OnMatch>DENY</OnMatch>
+ </filter>
+ </appender>
+
+ <appender name="ASYNC_PROCESS" class="ch.qos.logback.classic.AsyncAppender">
+ <appender-ref ref="IDP_PROCESS" />
+ <discardingThreshold>0</discardingThreshold>
+ </appender>
+
+ <appender name="IDP_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <!-- Suppress anything below WARN. -->
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+
+ <File>${idp.logfiles}/idp-warn.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-warn-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - %level [%logger:%line] - %msg%n%ex{full}</Pattern>
+ </encoder>
+
+ <!-- Ignore Velocity status page error. -->
+ <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator>
+ <matcher>
+ <Name>VelocityStatusMatcher</Name>
+ <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
+ </matcher>
+ <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
+ </evaluator>
+ <OnMatch>DENY</OnMatch>
+ </filter>
+ </appender>
+
+ <!-- Audit log. -->
+ <appender name="IDP_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${idp.logfiles}/idp-audit.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <!-- Consent audit log. -->
+ <appender name="IDP_CONSENT_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${idp.logfiles}/idp-consent-audit.log</File>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${idp.logfiles}/idp-consent-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+ <maxHistory>${idp.loghistory}</maxHistory>
+ </rollingPolicy>
+
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <charset>UTF-8</charset>
+ <Pattern>%msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <!-- F-TICKS syslog destination. -->
+ <appender name="IDP_FTICKS" class="ch.qos.logback.classic.net.SyslogAppender">
+ <syslogHost>${idp.fticks.loghost:-localhost}</syslogHost>
+ <port>${idp.fticks.logport:-514}</port>
+ <facility>AUTH</facility>
+ <suffixPattern>[%thread] %logger %msg</suffixPattern>
+ </appender>
+
+ <logger name="Shibboleth-Audit" level="ALL">
+ <appender-ref ref="${idp.audit.appender:-IDP_AUDIT}"/>
+ </logger>
+
+ <logger name="Shibboleth-FTICKS" level="ALL" additivity="false">
+ <appender-ref ref="${idp.fticks.appender:-IDP_FTICKS}"/>
+ </logger>
+
+ <logger name="Shibboleth-Consent-Audit" level="ALL">
+ <appender-ref ref="${idp.consent.appender:-IDP_CONSENT_AUDIT}"/>
+ </logger>
+
+ <root level="${idp.loglevel.root:-INFO}">
+ <appender-ref ref="${idp.process.appender:-IDP_PROCESS}"/>
+ <appender-ref ref="${idp.warn.appender:-IDP_WARN}" />
+ </root>
+
+</configuration>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list