Atlassian uses cookies to improve your browsing experience, perform analytics and research, and conduct advertising. Accept all cookies to indicate that you agree to our use of cookies on your device.
Atlassian uses cookies to improve your browsing experience, perform analytics and research, and conduct advertising. Accept all cookies to indicate that you agree to our use of cookies on your device. Atlassian cookies and tracking notice, (opens new window)
The authn/X509 login flow leverages any surrounding mechanism you have available for TLS client certificate authentication, provided the standard servlet request attribute (now "jakarta.servlet.request.X509Certificate") is populated. By default, this flow is configured without support for advanced authentication controls like passive or forced authentication since this is not generally possible with client certificate authentication.
Please re-read that paragraph; the IdP does not do X.509 authentication for you, and it can’t. Only a web server can negotiate mutual TLS with an HTTP client, and the IdP is not a web server. Java containers, while they make decent web servers in some cases, are terrible at this. They can do it, to a point, but they’re very hard to configure and they tend to be very opinionated about certificates they can accept without custom work. Generally using more standard software such as Apache tends to work better for this use case.
The result of this flow is a Java Subject containing an X500Principal derived from the subject of the certificate, and the certificate is optionally added as a public credential of the Subject. Note that no actual "username" is produced; rather, a suitable post-login Subject Canonicalization flow must be enabled/configured to pull a suitable principal name out of the Subject.
This flow is implemented as a special case of the External flow that happens to use a supplied servlet to implement the External contract that supports extraction of the certificate from the request. Rather than customizing this flow, use the External flow directly to do more advanced things that are not already supported by this one.
Note that if you have a web server that is configured to perform the certificate evaluation for you and populate a header or variable with the "username" to use based on the certificate, you almost certainly will want to use the RemoteUser flow instead. This flow pulls in the certificate as the primary result of the authentication and relies on downstream logic (often the x500 subject c14n flow) to get a username out of it.
Enabling Module
Configuring and using this feature requires that you first enable the "idp.authn.X509" module if it isn't already enabled. Systems upgraded from older releases generally come pre-enabled due to the prior state of the configuration tree.
Use authn/authn.properties to configure this flow.
Note for Upgraded Systems
Previous versions of the software relied on settings in web.xml to enable the required servlet and adjust its behavior, but this has been supplanted by an automatic registration process that allows the servlet to be registered at runtime and the settings controlled with Spring, allowing use of properties to control behavior.
Upgraded systems will continue to function as before, but new installs will depend solely on a single <context-param> defined in web.xml to enable the servlet that supports this feature, as discussed below.
Related, the old file conf/authn/x509-authn-config.xml is now supported only for compatibility and generally not installed or needed going forward.
A bean named shibboleth.authn.X509.TrustEngine can be defined to validate the client certificate chain. The best spot to define such a bean is usually conf/global.xml, as it needs to be in the root Spring context for the servlet to access it. Of course, it's often simpler and more common to do this validation using the web server itself, although that's less flexible.
An example of a PKIX-based TrustEngine declaration follows. Other types of trust engines are possible but in practice PKIX is the only practical way to validate end-entity certificates.
The idp.authn.X509.externalAuthnPath property is the flow redirection path to either a JSP page allowing an explicit prompt for certificate authentication (and other messaging to the user), or directly to the authentication servlet, skipping the UI (which is at /Authn/X509). These are context-relative locations, and you can use any JSP page you choose. It can be modified if needed, but in most cases modifying this to anything but one of those two choices means the External flow is likely a better choice to use.
You can make the location dynamic via a bean of type Function<ProfileRequestContext,String> named shibboleth.authn.X509.externalAuthnPathStrategy
Reference
The beans defined, or expected to be defined, in authn/x509-authn-config.xml follow: Bean ID / Type Default Description shibboleth.authn.X509.TrustEngine TrustEngine<X509Credential> Bean ID of a TrustEngine to apply to the certificate; in the absence of this setting, the certificate is accepted with no additional checking shibboleth.authn.X509.externalAuthnPathStrategy Function<ProfileRequestContext,String> A constant function returning the bean value above. A function that returns the redirection expression to use for the protected resource shibboleth.authn.X509.ClassifiedMessageMap Map<String,Collection<String>> Remaps NoCredentials and InvalidCredentials into ReselectFlow for fall-through behavior A map between defined error/warning conditions and events and implementation-specific message fragments to map to them. shibboleth.authn.X509.resultCachingPredicate Predicate<ProfileRequestContext>
An optional bean that can be defined to control whether to preserve the authentication result in an IdP session
The flow-specific properties usable via authn/authn.properties are: Name Default Description idp.authn.X509.externalAuthnPath contextRelative:x509-prompt.jsp Spring Web Flow redirection expression for the protected resource idp.authn.X509.saveCertificateToCredentialSet true Whether to save the certificate in the Subject’s public credential set The general properties configuring this flow via authn/authn.properties are: Name Default Description idp.authn.X509.order 1000 Flow priority relative to other enabled login flows (lower is "higher" in priority) idp.authn.X509.nonBrowserSupported false Whether the flow should handle non-browser request profiles (e.g., ECP) idp.authn.X509.passiveAuthenticationSupported false Whether the flow allows for passive authentication idp.authn.X509.forcedAuthenticationSupported false Whether the flow supports forced authentication idp.authn.X509.proxyRestrictionsEnforced %{idp.authn.enforceProxyRestrictions:true} Whether the flow enforces upstream IdP-imposed restrictions on proxying idp.authn.X509.proxyScopingEnforced false Whether the flow considers itself to be proxying, and therefore enforces SP-signaled restrictions on proxying idp.authn.X509.discoveryRequired false Whether to invoke IdP-discovery prior to running flow idp.authn.X509.lifetime %{idp.authn.defaultLifetime:PT1H} Lifetime of results produced by this flow idp.authn.X509.inactivityTimeout %{idp.authn.defaultTimeout:PT30M} Inactivity timeout of results produced by this flow idp.authn.X509.lifetimeStrategy 5.2 Function returning null Bean ID of Function<ProfileRequestContext,Duration> overriding a specific result’s lifetime idp.authn.X509.inactivityTimeoutStrategy 5.2 Function returning null Bean ID of Function<ProfileRequestContext,Duration> overriding a specific result’s inactivity timeout idp.authn.X509.reuseCondition shibboleth.Conditions.TRUE Bean ID of Predicate<ProfileRequestContext> controlling result reuse for SSO idp.authn.X509.activationCondition shibboleth.Conditions.TRUE Bean ID of Predicate<ProfileRequestContext> determining whether flow is usable for request idp.authn.X509.subjectDecorator Bean ID of BiConsumer<ProfileRequestContext,Subject> for subject customization idp.authn.X509.supportedPrincipals (see below) Comma-delimited list of protocol-specific Principal strings associated with flow idp.authn.X509.addDefaultPrincipals true Whether to auto-attach the preceding set of Principal objects to each Subject produced by this flow idp.authn.X509.c14n.flows 5.2 Comma-delimited list of c14n methods (beans) to run after use of this login flow As a non-password based flow, the supportedPrincipals property defaults to the following XML: <list>
<bean parent="shibboleth.SAML2AuthnContextClassRef"
c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:X509" />
<bean parent="shibboleth.SAML2AuthnContextClassRef"
c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient" />
<bean parent="shibboleth.SAML1AuthenticationMethod"
c:method="urn:ietf:rfc:2246" />
</list> In property form, this is expressed as (note the trailing commas): idp.authn.X509.supportedPrincipals = \
saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:X509, \
saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient, \
saml1/urn:ietf:rfc:2246
To replace the internally defined flow descriptor bean, the following XML is required: <util:list id="shibboleth.AvailableAuthenticationFlows">
<bean p:id="authn/X509" parent="shibboleth.AuthenticationFlow"
p:order="%{idp.authn.X509.order:1000}"
p:nonBrowserSupported="%{idp.authn.X509.nonBrowserSupported:false}"
p:passiveAuthenticationSupported="%{idp.authn.X509.passiveAuthenticationSupported:false}"
p:forcedAuthenticationSupported="%{idp.authn.X509.forcedAuthenticationSupported:false}"
p:proxyRestrictionsEnforced="%{idp.authn.X509.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
p:proxyScopingEnforced="%{idp.authn.X509.proxyScopingEnforced:false}"
p:discoveryRequired="%{idp.authn.X509.discoveryRequired:false}"
p:lifetime="%{idp.authn.X509.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
p:inactivityTimeout="%{idp.authn.X509.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.X509.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.X509.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.X509.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.X509.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.X509.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
c:_0="#{'%{idp.authn.X509.supportedPrincipals:}'.trim()}" />
</property>
</bean>
</util:list> In older versions and upgraded systems, this list is defined in conf/authn/general-authn.xml. In V5, no default version of the list is provided and it may simply be placed in conf/global.xml if needed.
Notes
Note that this flow is configured by default without support for non-browser profiles (namely ECP) because the X509Internal flow is a better choice when a browser isn't required. It eliminates the extra redirects (and the optional HTML UI) used by this flow.
Note that upgraded systems will have alternate, legacy approaches to configuring this feature, as noted above.