UAA SLO with SAML

I am using UAA with SAML authorization and the SLO functionality does not seem to work as expected.
I set all the expected application properties for SAML:

mgmtp.a12.uaa.authentication.cors.enabled=false
spring.security.saml2.relyingparty.registration.uaa.identityprovider.metadata-uri=http://localhost:7073/auth/realms/BupRealm/protocol/saml/descriptor
spring.security.saml2.relyingparty.registration.uaa.entity-id=urn:com:mgm:BupServices
spring.security.saml2.relyingparty.registration.uaa.decryption.credentials[0].private-key-location=classpath:saml/sp_enc.private.encrypted.pem
spring.security.saml2.relyingparty.registration.uaa.decryption.credentials[0].certificate-location=classpath:saml/saml_sp_enc_public.pem
spring.security.saml2.relyingparty.registration.uaa.signing.credentials[0].private-key-location=classpath:saml/sp_sgn.private.encrypted.pem
spring.security.saml2.relyingparty.registration.uaa.signing.credentials[0].certificate-location=classpath:saml/saml_sp_sig_public.pem

Then I configure in keycloak the urn:com:mgm:BupServices client for SLO:


image
The login is working, this means that the configuration of the BupServices client is correct, but when I am logging out from one front end app, it does not automatically log me out from the other front end app.
Also after logging out the user session is still active in keycloak:

The client configuration is:

export const uaaClientConfiguration: UaaClientConfiguration = {
	serverURL: serverBaseUrl,
	serverConnector: createServerConnector(serverBaseUrl),
	additionalResponseFilter: [new ResponseFilter429()],
	automaticallyLogin: true,
	offlineSelfConfigure: {
		uaaBaseUrl: "",
		tokens: [
			{
				authorizationHeaderName: "Authorization",
				generatedTokenExpirationHeaderName: "id_token_expiration",
				generatedTokenHeaderName: "id_token",
				tokenType: "UAABEARER",
				allowCredentials: "include"
			}
		],
		saml: {
			loginRelativeUrl: `${serverBaseUrl}/saml2/authenticate/uaa?uaa_success=${encodeURIComponent(
				decodeURIComponent(window.location.toString())
			)}&uaa_failure=${encodeURIComponent(decodeURIComponent(window.location.toString()))}`,
			logoutMethod: "POST",
			logoutRelativeUrl: "user/logout",
			tokenType: "UAABEARER"
		}
	}
};

And when I click on logout the following method is called:

UaaClient.getSamlClient().logout();

Am I doing anything wrong? I followed the documentation according to:
https://docs.geta12.com/docs/?release=2022.06#content:asciidoc,product:UAA,artifact:uaa-documentation-src,scene:UAA,anchor:redirect-configuration

Hi,
Please try this configuation property

mgmtp.a12.uaa.authentication.saml.idp-logout.enabled=true

I have already set this, there are some application properties that I forgot to paste above:

mgmtp.a12.uaa.authentication.types=SAML,ANONYMOUS
mgmtp.a12.uaa.authentication.unsecured.urls=?????,
mgmtp.a12.uaa.authentication.anonymous.access.urls=?????,
mgmtp.a12.uaa.authentication.jwt.store-user-in-token.enabled=true
mgmtp.a12.uaa.authentication.jwt.secret=???????,
mgmtp.a12.uaa.authentication.jwt.compress-user.enabled=true
mgmtp.a12.uaa.authentication.jwt.expiration-seconds=14400
mgmtp.a12.uaa.authentication.jwt.user-lifetime-seconds=21600
mgmtp.a12.uaa.authentication.saml.login.url=http://localhost:7070/api/saml2/authenticate/uaa
mgmtp.a12.uaa.authentication.saml.force-auth.enabled=true
mgmtp.a12.uaa.authentication.saml.signing-algorithm.url=http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1
mgmtp.a12.uaa.authentication.saml.idp-logout.enabled=true
mgmtp.a12.uaa.authentication.login.redirect.url-pattern=http://localhost:707(1|2).*
mgmtp.a12.uaa.authentication.logout.redirect.url-pattern=http://localhost:707(1|2).*
mgmtp.a12.uaa.authentication.user.access-rights-resource=classpath:/authentication/roles.yaml
mgmtp.a12.uaa.authorization.main-definition-resource=classpath:/BUPAuths.json
mgmtp.a12.uaa.authentication.anonymous.enabled=true

The problem may be that you are using the default implementation SamlAssertionExtractor of UAA, which currently does not set the RelayingPartyRegistration value to SamlUserDetails . You could try implementing SamlAssertionExtractor on your own, as shown below

@Component
public class SamlAssertionExtractorImpl implements SamlAssertionExtractor {

        @Inject
        private SamlGrantedAuthorityConverter samlGrantedAuthorityConverter;

        @Inject
        private UserFactory userFactory;

        @Override
        public SamlUserDetails extractAssertion(ResponseToken samlResponse) {
                Response response = samlResponse.getResponse();
                Assertion assertion = CollectionUtils.firstElement(response.getAssertions());
                Map<String, List<Object>> attributes = SamlAssertionUtils.getAssertionAttributes(assertion);
                String userName = SamlAssertionUtils.getAttributeValue(attributes, "UserID", String.class).get();

                Collection<GrantedAuthority> grantedAuthorities = samlGrantedAuthorityConverter.convert(assertion);

                String registrationId = samlResponse.getToken().getRelyingPartyRegistration().getRegistrationId();
                AbstractExtendedUser<SamlUserDetails> userObject = userFactory.createUser(userName, grantedAuthorities);
                userObject.setRelayingPartyRegistration(registrationId); // Need this one to make logout run
                return userObject;
        }

} 

And in the javadoc of SamlAssertionExtractor interface has

    /**
	 * Extract data from a SAML response token.
	 * 
	 * NOTE: Please set the {@link SamlUserDetails#getRelyingPartyRegistrationId()} otherwise logout request can't be processed.
	 * The value is in the response token {@link ResponseToken} <code>samlResponse.getToken().getRelyingPartyRegistration().getRegistrationId()</code>
	 */

Nice the logout worked! There is one small issue yet, when I am logging out I get an empty screen:


Do I have to configure a redirect URL for after the logout?

Yes, you have to. There are 2 ways:
with configuration properties:

mgmtp.a12.uaa.authentication.client-selfconfiguration.saml.logout-relative.url=user/logout?uaa_success=http://localhost:3000

Or in client self configuration

export const uaaClientConfiguration: UaaClientConfiguration = {
	serverURL: serverBaseUrl,
	serverConnector: createServerConnector(serverBaseUrl),
	additionalResponseFilter: [new ResponseFilter429()],
	automaticallyLogin: true,
	offlineSelfConfigure: {
		uaaBaseUrl: "",
		tokens: [
			{
				authorizationHeaderName: "Authorization",
				generatedTokenExpirationHeaderName: "id_token_expiration",
				generatedTokenHeaderName: "id_token",
				tokenType: "UAABEARER",
				allowCredentials: "include"
			}
		],
		saml: {
			loginRelativeUrl: `${serverBaseUrl}/saml2/authenticate/uaa?uaa_success=${encodeURIComponent(
				decodeURIComponent(window.location.toString())
			)}&uaa_failure=${encodeURIComponent(decodeURIComponent(window.location.toString()))}`,
			logoutMethod: "POST",
			logoutRelativeUrl: "user/logout?uaa_success=http://localhost:3000", // here
			tokenType: "UAABEARER"
		}
	}
};