mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-06 02:32:14 +00:00
SAML 2.0 Single Logout Uses Saml2AuthenticationInfo
This allows SLO to be triggered without the authentication principal needing to implement a given interface. Issue gh-10820
This commit is contained in:
parent
ffd6e3c0f7
commit
36c7b91fb9
@ -33,7 +33,7 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt
|
||||
import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationInfo;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSaml4LogoutRequestValidator;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSaml4LogoutResponseValidator;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSaml5LogoutRequestValidator;
|
||||
@ -531,10 +531,7 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (authentication == null) {
|
||||
return false;
|
||||
}
|
||||
return authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal;
|
||||
return Saml2AuthenticationInfo.fromAuthentication(authentication) != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationInfo;
|
||||
import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
|
||||
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestFilter;
|
||||
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutResponseFilter;
|
||||
@ -236,10 +236,7 @@ final class Saml2LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (authentication == null) {
|
||||
return false;
|
||||
}
|
||||
return authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal;
|
||||
return Saml2AuthenticationInfo.fromAuthentication(authentication) != null;
|
||||
}
|
||||
|
||||
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
|
||||
|
@ -31,7 +31,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Clement Stoquart
|
||||
* @since 5.2.2
|
||||
*/
|
||||
public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal {
|
||||
public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal, Saml2AuthenticationInfo {
|
||||
|
||||
/**
|
||||
* Get the first value of Saml2 token attribute by name
|
||||
@ -72,10 +72,12 @@ public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal {
|
||||
* @return the {@link RelyingPartyRegistration} identifier
|
||||
* @since 5.6
|
||||
*/
|
||||
@Override
|
||||
default String getRelyingPartyRegistrationId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
default List<String> getSessionIndexes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.security.saml2.provider.service.authentication;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.opensaml.saml.saml2.core.SessionIndex;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
|
||||
/**
|
||||
* Additional SAML 2.0 authentication information
|
||||
*
|
||||
* <p>
|
||||
* SAML 2.0 Single Logout requires that the {@link Authentication#getPrincipal()
|
||||
* authenticated principal} or the {@link Authentication} itself implements this
|
||||
* interface.
|
||||
*
|
||||
* @author Christian Schuster
|
||||
*/
|
||||
public interface Saml2AuthenticationInfo {
|
||||
|
||||
/**
|
||||
* Get the {@link RelyingPartyRegistration} identifier
|
||||
* @return the {@link RelyingPartyRegistration} identifier
|
||||
*/
|
||||
String getRelyingPartyRegistrationId();
|
||||
|
||||
/**
|
||||
* Get the {@link SessionIndex} values of the authenticated principal
|
||||
* @return the {@link SessionIndex} values of the authenticated principal
|
||||
*/
|
||||
List<String> getSessionIndexes();
|
||||
|
||||
/**
|
||||
* Try to obtain a {@link Saml2AuthenticationInfo} instance from an
|
||||
* {@link Authentication}
|
||||
*
|
||||
* <p>
|
||||
* The result is either the {@link Authentication#getPrincipal() authenticated
|
||||
* principal}, the {@link Authentication} itself, or {@code null}.
|
||||
*
|
||||
* <p>
|
||||
* Returning {@code null} indicates that the given {@link Authentication} does not
|
||||
* represent a SAML 2.0 authentication.
|
||||
* @param authentication the {@link Authentication}
|
||||
* @return the {@link Saml2AuthenticationInfo} or {@code null} if unavailable
|
||||
*/
|
||||
static Saml2AuthenticationInfo fromAuthentication(Authentication authentication) {
|
||||
if (authentication == null) {
|
||||
return null;
|
||||
}
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof Saml2AuthenticationInfo) {
|
||||
return (Saml2AuthenticationInfo) principal;
|
||||
}
|
||||
if (authentication instanceof Saml2AuthenticationInfo) {
|
||||
return (Saml2AuthenticationInfo) authentication;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -42,7 +42,7 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.saml2.core.OpenSamlInitializationService;
|
||||
import org.springframework.security.saml2.core.Saml2ParameterNames;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationInfo;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
|
||||
@ -149,9 +149,9 @@ final class BaseOpenSamlLogoutRequestResolver implements Saml2LogoutRequestResol
|
||||
NameID nameId = this.nameIdBuilder.buildObject();
|
||||
nameId.setValue(authentication.getName());
|
||||
logoutRequest.setNameID(nameId);
|
||||
if (authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal) {
|
||||
Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) authentication.getPrincipal();
|
||||
for (String index : principal.getSessionIndexes()) {
|
||||
Saml2AuthenticationInfo info = Saml2AuthenticationInfo.fromAuthentication(authentication);
|
||||
if (info != null) {
|
||||
for (String index : info.getSessionIndexes()) {
|
||||
SessionIndex sessionIndex = this.sessionIndexBuilder.buildObject();
|
||||
sessionIndex.setValue(index);
|
||||
logoutRequest.getSessionIndexes().add(sessionIndex);
|
||||
@ -191,12 +191,9 @@ final class BaseOpenSamlLogoutRequestResolver implements Saml2LogoutRequestResol
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Attempting to resolve registrationId from " + authentication);
|
||||
}
|
||||
if (authentication == null) {
|
||||
return null;
|
||||
}
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof Saml2AuthenticatedPrincipal) {
|
||||
return ((Saml2AuthenticatedPrincipal) principal).getRelyingPartyRegistrationId();
|
||||
Saml2AuthenticationInfo info = Saml2AuthenticationInfo.fromAuthentication(authentication);
|
||||
if (info != null) {
|
||||
return info.getRelyingPartyRegistrationId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.saml2.core.OpenSamlInitializationService;
|
||||
import org.springframework.security.saml2.core.Saml2Error;
|
||||
import org.springframework.security.saml2.core.Saml2ParameterNames;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationInfo;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidatorParameters;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
@ -130,11 +130,9 @@ final class BaseOpenSamlLogoutRequestValidatorParametersResolver
|
||||
if (registrationId != null) {
|
||||
return registrationId;
|
||||
}
|
||||
if (authentication == null) {
|
||||
return null;
|
||||
}
|
||||
if (authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal principal) {
|
||||
return principal.getRelyingPartyRegistrationId();
|
||||
Saml2AuthenticationInfo info = Saml2AuthenticationInfo.fromAuthentication(authentication);
|
||||
if (info != null) {
|
||||
return info.getRelyingPartyRegistrationId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ import org.springframework.security.saml2.core.OpenSamlInitializationService;
|
||||
import org.springframework.security.saml2.core.Saml2Error;
|
||||
import org.springframework.security.saml2.core.Saml2ErrorCodes;
|
||||
import org.springframework.security.saml2.core.Saml2ParameterNames;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationInfo;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponse;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||
@ -217,12 +217,9 @@ final class BaseOpenSamlLogoutResponseResolver implements Saml2LogoutResponseRes
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Attempting to resolve registrationId from " + authentication);
|
||||
}
|
||||
if (authentication == null) {
|
||||
return null;
|
||||
}
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof Saml2AuthenticatedPrincipal) {
|
||||
return ((Saml2AuthenticatedPrincipal) principal).getRelyingPartyRegistrationId();
|
||||
Saml2AuthenticationInfo info = Saml2AuthenticationInfo.fromAuthentication(authentication);
|
||||
if (info != null) {
|
||||
return info.getRelyingPartyRegistrationId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.saml2.core.Saml2Error;
|
||||
import org.springframework.security.saml2.core.Saml2ErrorCodes;
|
||||
import org.springframework.security.saml2.core.Saml2ParameterNames;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationInfo;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidator;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidatorParameters;
|
||||
@ -329,11 +329,9 @@ public final class Saml2LogoutRequestFilter extends OncePerRequestFilter {
|
||||
if (registrationId != null) {
|
||||
return registrationId;
|
||||
}
|
||||
if (authentication == null) {
|
||||
return null;
|
||||
}
|
||||
if (authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal principal) {
|
||||
return principal.getRelyingPartyRegistrationId();
|
||||
Saml2AuthenticationInfo info = Saml2AuthenticationInfo.fromAuthentication(authentication);
|
||||
if (info != null) {
|
||||
return info.getRelyingPartyRegistrationId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.saml2.core.OpenSamlInitializationService;
|
||||
import org.springframework.security.saml2.core.Saml2Error;
|
||||
import org.springframework.security.saml2.core.Saml2ParameterNames;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationInfo;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidatorParameters;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
@ -144,11 +144,9 @@ public final class OpenSamlLogoutRequestValidatorParametersResolver
|
||||
if (registrationId != null) {
|
||||
return registrationId;
|
||||
}
|
||||
if (authentication == null) {
|
||||
return null;
|
||||
}
|
||||
if (authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal principal) {
|
||||
return principal.getRelyingPartyRegistrationId();
|
||||
Saml2AuthenticationInfo info = Saml2AuthenticationInfo.fromAuthentication(authentication);
|
||||
if (info != null) {
|
||||
return info.getRelyingPartyRegistrationId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user