Using Keycloak with Spring Boot applications is usually just a matter of a few lines of code when you use Keycloak ‘s adapter integrations. However, most of the integrations require using the OpenID Connect protocol for web-based Single Sign-On (SSO) and sometimes it might be necessary to use SAML instead of OpenID Connect.
In this blog post, you’ll learn how to configure your Spring Boot app to use SSO via SAML with Keycloak.
SAML is a mature standard protocol for authentication and authorization which is heavily used across many industries. Among many other things, it provides powerful Single Sign-On capabilities with the Web SSO profile.
If you want to use SAML in a Java application, you have many options, but the most common ones are using OpenSAML or Spring Security SAML .
Note that if you want to play with SAML, you could also use Shibboleth , but that’s a task for another blog post. 😉
This time we’ll use a Spring-Boot-based app with plain Spring Security SAML without any Keycloak adapters involved as example client.
The code for the spring-boot-security-saml-sample application can be found here .
Note that this example application is based on the Spring Boot Security SAML Sample app by Vincenzo De Notaris.
SAML terminology
In our scenario we have two parties that interact during the SSO handshake. The Spring Boot app acts as a Service Provider (SP)
and offers a service to the user. The Keycloak server plays the role of an Identity Provider (IDP)
and provides means to authenticate a user for a Service Provider.
The SAML Web SSO profile describes a set of messages that get exchanged between the involved parties. Those messages are XML documents that contain information about authentication requests/responses with signatures and used certificates, as well as potentially signed and encrypted user information in the form of SAML assertions.
SAML describes multiple styles of communication between two parties. The most common ones are POST-Binding
and Redirect-Binding
.
With POST-Binding
the two parties exchange SAML messages via HTTP POST requests. Those POST requests are triggered via dynamically generated, automatically submitted HTML forms, which we’ll discuss later.
The nice thing with POST-Binding
is that, since all the information is sent via HTTP POST, no sensitive information can be leaked in web server or proxy logs or browser histories.
Just a quick note about the the Redirect-Binding
. As the name suggests, the Redirect-Binding
makes extensive use of HTTP redirects and transmits SAML messages as base64 encoded URL parameters. Although this might seem much easier than the HTTP-POST-based approach, it can lead to leaking information in the aforementioned logs.
We’ll use POST-Binding
for the remainder of this blog post.
Spring Boot and Spring Security SAML
If you have worked with Spring Security, then you probably know that Spring Security SAML is usually configured via XML.
Thankfully, Vincenzo De Notaris et al. have put in a lot of effort to port the XML config to Java config. Although it’s quite a mouthful of Java config, it’s fairly practical. Still, I’m looking forward to a more bootified Spring Security SAML support in the future. 🙂
An example of what this looks like can be seen in the WebSecurityConfig class in our example app.
The example contains already everything that we need. Well, almost. We need to declare one additional Spring Bean, which we add to the WebSecurityConfig
class
1@Bean
2 @Qualifier("idp-keycloak")
3 public ExtendedMetadataDelegate keycloakExtendedMetadataProvider(Environment env)
4 throws MetadataProviderException {
5 String idpKeycloakMetadataURL = env.getRequiredProperty("keycloak.auth-server-url") + "/protocol/saml/descriptor";
6 HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(
7 this.backgroundTaskTimer, httpClient(), idpKeycloakMetadataURL);
8 httpMetadataProvider.setParserPool(parserPool());
9 ExtendedMetadataDelegate extendedMetadataDelegate =
10 new ExtendedMetadataDelegate(httpMetadataProvider, extendedMetadata());
11 extendedMetadataDelegate.setMetadataTrustCheck(true);
12 extendedMetadataDelegate.setMetadataRequireSignature(false);
13 backgroundTaskTimer.purge();
14 return extendedMetadataDelegate;
15 }
We also need to ensure that the Keycloak IDP definition is automatically picked up by the Spring Security SAML infrastructure. To do this, we modify the metadata
bean to let Spring autowire all available MetadataProvider
instances via the providers
parameter.
1@Bean
2 @Qualifier("metadata")
3 public CachingMetadataManager metadata(List<MetadataProvider> providers) throws MetadataProviderException {
4 return new CachingMetadataManager(providers);
5 }
Keycloak setup
For this blog post, we create a realm with the name demo
.
Note that I tested this with Keycloak 4.8.3.Final.
Also, note that you might need to adapt the URL to your Keycloak server in the application.properties
configuration file of the Spring Boot app or just pass a JVM System Property like:
-Dkeycloak.auth-server-url=http://localhost:8081/auth/realms/demo
In this demo
realm, we need to create a client configuration for our Spring Boot app.
Setup Keycloak Client
Create a new SAML
client in Keycloak with the client-id com:vdenotaris:spring:sp
.
In the client settings
tab configure the following:
- Include AuthnStatement
On
- Include OneTimeUse Condition
Off
- Sign Documents
On
- Optimize REDIRECT signing key lookup
Off
- Sign Assertions
On
- Signature Algorithm
RSA_SHA256
- SAML Signature Key Name
KEY_ID
- Canonicalization Method
EXCLUSIVE
- Encrypt Assertions
Off
- Client Signature Required
On
- Force POST Binding
On
- Front Channel Logout
On
- Force Name ID Format
Off
- Name ID Format
username
- Root URL
http://localhost:8080
- Valid Redirect URIs
/saml/*
- Base URL
/
- Open Fine Grain SAML Endpoint Configuration
- Assertion Consumer Service POST Binding URL
/saml/SSO
- Logout Service POST Binding URL
/saml/logout
In the SAML Keys
tab you need to import the Keystore of the example app.
- Click on
import
- Archive Format
JKS
- Key-Alias
apollo
- Store pass
nalle123
- Select configure the path to
src/main/resources/saml/samlKeystore.jks
Your client is now set up to use the POST-Binding method of the Web SSO SAML Profile.
Playing with the setup: Login and logout
You can now try to log in via Keycloak:
- Browse to
http://localhost:8080
- Click on
Getting started
- Under
Select your Identity Provider
choosehttp://localhost:8081/auth/realms/demo
and clickStart 3rd Party Login
- Login with a user, I named mine
tester
You should now see a nice neon-cat image like
Now click on Global logout
to log out again. As the name implies, this logs instructs Keycloak to propagate the logout to all clients which have an Admin URL
configured or rely on Keycloaks Cookies, such as the Account
app built-in to Keycloak.
SAML messages and protocol flow
Now that everything works, let’s dig a bit deeper and see what’s going on under the hood in your browser. To do that, we install one of the available SAML debugging tools as a browser extension. Since I’m using Chrome, I use SAML Chrome Panel .
If you enable this extension and try to log in again, you’ll see the SAML messages that are exchanged between our app and Keycloak. Note that you might need to enable the extension for incognito mode / private browsing as well.
You should now see a SAML
tab in the devtools
view of your browser. If you click on the SAML
tab and try to log in, you can see the SAML AuthnRequest
request:
1<saml2p:AuthnRequest AssertionConsumerServiceURL="http://localhost:8080/saml/SSO" 2 Destination="http://localhost:8081/auth/realms/demo/protocol/saml" ForceAuthn="false" 3 ID="ai83b34d292de92549iij63i99jgff" IsPassive="false" IssueInstant="2019-02-28T19:58:58.486Z" 4 ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0" 5 xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"> 6 <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">com:vdenotaris:spring:sp</saml2:Issuer> 7 <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 8 <ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 9 <ds:Reference URI="#ai83b34d292de92549iij63i99jgff"> 10 <ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 11 <ds:DigestValue>EAG4ntORN3mgZToX69jKh1WDuL4=</ds:DigestValue> 12 </ds:Reference> 13 </ds:SignedInfo> 14 <ds:SignatureValue>XftgCK5io35hc6FK/er7eLQLNvGqRUeEMX6kyfDxmrDQ97eDS8H+awmYLFmrcS2TIhZNXkhbnCi8VcOUvRpu4XNzhh7wunRGxRZ5dbDewlRoQa+vFzNFXPNbXf0d6NbjiEfQy9a0zC5BTRs7Konh/lzm4EQ1h2GAWc8PEaypFASiV5uJ2kdeIuBeGRNFYqmTZyQm2JgsJ8E7BFwOKqmXnkb6jhywReuFSJZDRebq3iSzsca2wkKX/SvK6iAXPf7HSzMJ4Mz+nOxW8XTi7rRE43r1s4vYNTj3s10BwuNv/ldW3UzXTNRU868unOyk1GuZZA3V/yLpkEovw/U7zfXAig==</ds:SignatureValue> 15 <ds:KeyInfo> 16 <ds:X509Data> 17 <ds:X509Certificate>MIIDUjCCAjqgAwIBAgIEUOLIQTANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJGSTEQMA4GA1UE 18 CBMHVXVzaW1hYTERMA8GA1UEBxMISGVsc2lua2kxGDAWBgNVBAoTD1JNNSBTb2Z0d2FyZSBPeTEM 19 MAoGA1UECwwDUiZEMQ8wDQYDVQQDEwZhcG9sbG8wHhcNMTMwMTAxMTEyODAxWhcNMjIxMjMwMTEy 20 ODAxWjBrMQswCQYDVQQGEwJGSTEQMA4GA1UECBMHVXVzaW1hYTERMA8GA1UEBxMISGVsc2lua2kx 21 GDAWBgNVBAoTD1JNNSBTb2Z0d2FyZSBPeTEMMAoGA1UECwwDUiZEMQ8wDQYDVQQDEwZhcG9sbG8w 22 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXqP0wqL2Ai1haeTj0alwsLafhrDtUt00E 23 5xc7kdD7PISRA270ZmpYMB4W24Uk2QkuwaBp6dI/yRdUvPfOT45YZrqIxMe2451PAQWtEKWF5Z13 24 F0J4/lB71TtrzyH94RnqSHXFfvRN8EY/rzuEzrpZrHdtNs9LRyLqcRTXMMO4z7QghBuxh3K5gu7K 25 qxpHx6No83WNZj4B3gvWLRWv05nbXh/F9YMeQClTX1iBNAhLQxWhwXMKB4u1iPQ/KSaal3R26pON 26 UUmu1qVtU1quQozSTPD8HvsDqGG19v2+/N3uf5dRYtvEPfwXN3wIY+/R93vBA6lnl5nTctZIRsyg 27 0Gv5AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFQwAAYUjso1VwjDc2kypK/RRcB8bMAUUIG0hLGL 28 82IvnKouGixGqAcULwQKIvTs6uGmlgbSG6Gn5ROb2mlBztXqQ49zRvi5qWNRttir6eyqwRFGOM6A 29 8rxj3Jhxi2Vb/MJn7XzeVHHLzA1sV5hwl/2PLnaL2h9WyG9QwBbwtmkMEqUt/dgixKb1Rvby/tBu 30 RogWgPONNSACiW+Z5o8UdAOqNMZQozD/i1gOjBXoF0F5OksjQN7xoQZLj9xXefxCFQ69FPcFDeEW 31 bHwSoBy5hLPNALaEUoa5zPDwlixwRjFQTc5XXaRpgIjy/2gsL8+Y5QRhyXnLqgO67BlLYW/GuHE=</ds:X509Certificate> 32 </ds:X509Data> 33 </ds:KeyInfo> 34 </ds:Signature> 35</saml2p:AuthnRequest>
The AuthnRequest
is quite dense and describes things like involved party (e.g. com:vdenotaris:spring:sp
), communication methods (e.g. urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
) and certificate information.
The AssertionConsumerServiceURL
which is configured as http://localhost:8080/saml/SSO
denotes the endpoint that Keycloak (the IDP) should use to send SAML responses to our app (the SP), whereas the Destination
denotes the SAML protocol endpoint on the Keycloak side which is http://localhost:8081/auth/realms/demo/protocol/saml
.
This is sent via HTTP POST
by your browser to the http://localhost:8081/auth/realms/demo/protocol/saml
endpoint of your Keycloak IDP server, which responds with a browser-redirect to a login form to perform the authentication.
After successful authentication, Keycloak responds with HTTP status 200 and a small HTML document. This document contains the encoded SAML Response
as a form parameter in an embedded HTML form that is automatically submitted via JavaScript by your browser on arrival. If JavaScript is not available, then the user will see a HTML form with a continue button, Progressive enhancement FTW. A simple, but quite effective technique 🙂
1<HTML> 2 <HEAD> 3 <TITLE>SAML HTTP Post Binding</TITLE> 4 </HEAD> 5 <BODY Onload="document.forms[0].submit()"> 6 <FORM METHOD="POST" ACTION="http://localhost:8080/saml/SSO"> 7 <INPUT TYPE="HIDDEN" NAME="SAMLResponse" VALUE="PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhb...Base64 encoded saml response"> 8 <P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P> 9 <INPUT TYPE="SUBMIT" VALUE="CONTINUE"/></NOSCRIPT> 10 </FORM> 11 </BODY> 12</HTML>
The contained SAML Response
looks like this:
1<samlp:Response Destination="http://localhost:8080/saml/SSO" 2 ID="ID_54ee7d80-7037-4f8d-b4c5-b046e1de8ef7" InResponseTo="ai83b34d292de92549iij63i99jgff" 3 IssueInstant="2019-02-28T19:59:23.535Z" Version="2.0" 4 xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 5 xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> 6 <saml:Issuer>http://localhost:8081/auth/realms/demo</saml:Issuer> 7 <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> 8 <dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> 9 <dsig:Reference URI="#ID_54ee7d80-7037-4f8d-b4c5-b046e1de8ef7"> 10 <dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> 11 <dsig:DigestValue>x0cUGoSifrriU1zQuaRy4xkIR75ibzil0Pla9RS8CQ0=</dsig:DigestValue> 12 </dsig:Reference> 13 </dsig:SignedInfo> 14 <dsig:SignatureValue>H7AfRJ+zGf3lVfLiPDnUrDNyqPVaz65A2PWJX/rjI7sPZD8KitY1+NvgGpoR/JLCQccF8HvHzeQO9c9S4tvMxkT+KE3bgufugfAL+aYMlL61/C8XA+2b1vazOv1ftKCeMthxn1iKOQQ0GcB4drGqip25UhSXpcaXeh2lTtfnV3iv2whMGZXCoWisEBH/izMYr0uYngplnJEmXSzX+BAQc8BXA+yLCEJ34Inayg3VnYm7Tx8zh9PAgx28j5HikrNG7AoBEAxF9CCAWvBLLBmx4ebpiLHdzZUHE7TYmEORfL/yJ5KG3k4BlU5w287B9UG5C4IFH8LAUOOQsVR6VRoTpw==</dsig:SignatureValue> 15 <dsig:KeyInfo> 16 <dsig:KeyName>PrmJE0uxLVfFemeO41pwrZ8P3Pxmi8q44V4553olejE</dsig:KeyName> 17 <dsig:X509Data> 18 <dsig:X509Certificate>MIIClzCCAX8CBgFo2/zejjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARkZW1vMB4XDTE5MDIxMTA5NTUwOFoXDTI5MDIxMTA5NTY0OFowDzENMAsGA1UEAwwEZGVtbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANGej7NgaqGe762Z5g2dch/Pr6G2q3fZlN8aUfU1+lzBrgL/kwRrsCr0zeQ4EcXWpfV5ayMl+0Ouc+Q8VMObVr+8+Iq2b6NUaOMR+GiOc3vCcEEtB3zfNVqE3FFeAI6vTDA4u45M0NKUkn1dMtITQj2K2Mmz/pjwmGCo1jh9MS3loZU07om8UjHNrrg/4Tct97EONnTdYgHNetNRS3xsXdzJc64KtovA+Muk93XMhQe1MR8iIdkSX1kIuJg0Ka9Y996dKstDB8nzTUlEQs/vw4iSu6IKu+cOvdrs+HFyvCVUWmqVpqh/AL+MgJxtRcfj7tPWESSe+bukwcz+icogEAUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAult+p9pECxU32gKFaMCUt0bDFsDU00nM3hPpRUijJchJe68NvXn9Pv2DwbIPpSQpYJAsG3xoK36h/S7oTF3SosnZVtrHXhzN+aNWKgoDGcR8d4WtT6kKphI8Mf123qyPPC+5v7CQxDOW6wXd+0XQFRIfHSfyH0gxRsnFoYiapnAgOVftozMCm2F2ZZQmhPtxaigQ6rhVWIDbemhKlwEV49H83Qkh9c/jfngVdYB1yA/MfSsossk6u8w47egSt73FXVAHginX4obHp+HEOOU7C8myOIyKq74nPvesvmffIv7ttgvLoEhdK/S3p7AiHppxgWb1roD/7P1Tk21eqOBW3Q==</dsig:X509Certificate> 19 </dsig:X509Data> 20 <dsig:KeyValue> 21 <dsig:RSAKeyValue> 22 <dsig:Modulus>0Z6Ps2BqoZ7vrZnmDZ1yH8+vobard9mU3xpR9TX6XMGuAv+TBGuwKvTN5DgRxdal9XlrIyX7Q65z5DxUw5tWv7z4irZvo1Ro4xH4aI5ze8JwQS0HfN81WoTcUV4Ajq9MMDi7jkzQ0pSSfV0y0hNCPYrYybP+mPCYYKjWOH0xLeWhlTTuibxSMc2uuD/hNy33sQ42dN1iAc1601FLfGxd3Mlzrgq2i8D4y6T3dcyFB7UxHyIh2RJfWQi4mDQpr1j33p0qy0MHyfNNSURCz+/DiJK7ogq75w692uz4cXK8JVRaapWmqH8Av4yAnG1Fx+Pu09YRJJ75u6TBzP6JyiAQBQ==</dsig:Modulus> 23 <dsig:Exponent>AQAB</dsig:Exponent> 24 </dsig:RSAKeyValue> 25 </dsig:KeyValue> 26 </dsig:KeyInfo> 27 </dsig:Signature> 28 <samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status> 29 <saml:Assertion ID="ID_39d48e94-d0aa-4cb3-8cc9-cce064b141af" IssueInstant="2019-02-28T19:59:23.535Z" 30 Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> 31 <saml:Issuer>http://localhost:8081/auth/realms/demo</saml:Issuer> 32 <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> 33 <dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> 34 <dsig:Reference URI="#ID_39d48e94-d0aa-4cb3-8cc9-cce064b141af"> 35 <dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> 36 <dsig:DigestValue>dF9OWNKEu+czMS9leQHuUPTlJys4s14+5QF2l+4KQLg=</dsig:DigestValue> 37 </dsig:Reference> 38 </dsig:SignedInfo> 39 <dsig:SignatureValue>olNhmQb4wGMgNHg9dMpBNkfV75oLQt2jJYW+R4dYX7CNQOPeFzVN8dMNtPmKIec/ZCYdK5kXzFhcvWsVWj8S0Jdm3B7Ep4dg7urTkqTulz5W9uQFg1bx0X6VzPmwTnynkLptyQv4L21uwdENQNDa+cF8c4dbLtyHgilOPDkpTRU0ZdLNDT3ea7iKClhddPvqX3rC/hepDH+hfYzh+l8EM0xOsjLUA7id4UwFGhWqB/ExzKqnMzxVZsWzZTu4W+sWLsH65dBltJVdPuOH1SM2azTBO8Wyz1cD8FWBXHiHTigkx+iaL3PVgM0znLkikoX+BN+1GTKj8nSVsPih3SQwIA==</dsig:SignatureValue> 40 <dsig:KeyInfo> 41 <dsig:KeyName>PrmJE0uxLVfFemeO41pwrZ8P3Pxmi8q44V4553olejE</dsig:KeyName> 42 <dsig:X509Data> 43 <dsig:X509Certificate>MIIClzCCAX8CBgFo2/zejjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARkZW1vMB4XDTE5MDIxMTA5NTUwOFoXDTI5MDIxMTA5NTY0OFowDzENMAsGA1UEAwwEZGVtbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANGej7NgaqGe762Z5g2dch/Pr6G2q3fZlN8aUfU1+lzBrgL/kwRrsCr0zeQ4EcXWpfV5ayMl+0Ouc+Q8VMObVr+8+Iq2b6NUaOMR+GiOc3vCcEEtB3zfNVqE3FFeAI6vTDA4u45M0NKUkn1dMtITQj2K2Mmz/pjwmGCo1jh9MS3loZU07om8UjHNrrg/4Tct97EONnTdYgHNetNRS3xsXdzJc64KtovA+Muk93XMhQe1MR8iIdkSX1kIuJg0Ka9Y996dKstDB8nzTUlEQs/vw4iSu6IKu+cOvdrs+HFyvCVUWmqVpqh/AL+MgJxtRcfj7tPWESSe+bukwcz+icogEAUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAult+p9pECxU32gKFaMCUt0bDFsDU00nM3hPpRUijJchJe68NvXn9Pv2DwbIPpSQpYJAsG3xoK36h/S7oTF3SosnZVtrHXhzN+aNWKgoDGcR8d4WtT6kKphI8Mf123qyPPC+5v7CQxDOW6wXd+0XQFRIfHSfyH0gxRsnFoYiapnAgOVftozMCm2F2ZZQmhPtxaigQ6rhVWIDbemhKlwEV49H83Qkh9c/jfngVdYB1yA/MfSsossk6u8w47egSt73FXVAHginX4obHp+HEOOU7C8myOIyKq74nPvesvmffIv7ttgvLoEhdK/S3p7AiHppxgWb1roD/7P1Tk21eqOBW3Q==</dsig:X509Certificate> 44 </dsig:X509Data> 45 <dsig:KeyValue> 46 <dsig:RSAKeyValue> 47 <dsig:Modulus>0Z6Ps2BqoZ7vrZnmDZ1yH8+vobard9mU3xpR9TX6XMGuAv+TBGuwKvTN5DgRxdal9XlrIyX7Q65z5DxUw5tWv7z4irZvo1Ro4xH4aI5ze8JwQS0HfN81WoTcUV4Ajq9MMDi7jkzQ0pSSfV0y0hNCPYrYybP+mPCYYKjWOH0xLeWhlTTuibxSMc2uuD/hNy33sQ42dN1iAc1601FLfGxd3Mlzrgq2i8D4y6T3dcyFB7UxHyIh2RJfWQi4mDQpr1j33p0qy0MHyfNNSURCz+/DiJK7ogq75w692uz4cXK8JVRaapWmqH8Av4yAnG1Fx+Pu09YRJJ75u6TBzP6JyiAQBQ==</dsig:Modulus> 48 <dsig:Exponent>AQAB</dsig:Exponent> 49 </dsig:RSAKeyValue> 50 </dsig:KeyValue> 51 </dsig:KeyInfo> 52 </dsig:Signature> 53 <saml:Subject> 54 <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">tester</saml:NameID> 55 <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData InResponseTo="ai83b34d292de92549iij63i99jgff" 56 NotOnOrAfter="2019-02-28T20:04:21.535Z" Recipient="http://localhost:8080/saml/SSO"/></saml:SubjectConfirmation> 57 </saml:Subject> 58 <saml:Conditions NotBefore="2019-02-28T19:59:21.535Z" NotOnOrAfter="2019-02-28T20:00:21.535Z"> 59 <saml:AudienceRestriction> 60 <saml:Audience>com:vdenotaris:spring:sp</saml:Audience> 61 </saml:AudienceRestriction> 62 </saml:Conditions> 63 <saml:AuthnStatement AuthnInstant="2019-02-28T19:59:23.536Z" 64 SessionIndex="c698343d-20a8-485a-82af-93f764804d45::aa87b005-0b74-45f6-a806-e2193a6288ad"> 65 <saml:AuthnContext> 66 <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef> 67 </saml:AuthnContext> 68 </saml:AuthnStatement> 69 <saml:AttributeStatement> 70 <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> 71 <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 72 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">uma_authorization</saml:AttributeValue> 73 </saml:Attribute> 74 <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> 75 <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 76 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">view-profile</saml:AttributeValue> 77 </saml:Attribute> 78 <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> 79 <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 80 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">access</saml:AttributeValue> 81 </saml:Attribute> 82 <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> 83 <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 84 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">manage-account</saml:AttributeValue> 85 </saml:Attribute> 86 <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> 87 <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 88 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">manage-account-links</saml:AttributeValue> 89 </saml:Attribute> 90 <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> 91 <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 92 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">offline_access</saml:AttributeValue> 93 </saml:Attribute> 94 <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> 95 <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 96 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">access</saml:AttributeValue> 97 </saml:Attribute> 98 <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> 99 <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 100 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">user</saml:AttributeValue> 101 </saml:Attribute> 102 </saml:AttributeStatement> 103 </saml:Assertion> 104</samlp:Response>
So what’s in the XML?
- The username: tester
- The role information
- Some restrictions about the response (time limit, audience)
- Signature
SAML logout flow with POST Binding
But let’s see what happens when we log out, so let’s click Global logout
. This triggers an HTTP POST
request to http://localhost:8080/saml/logout
(our Spring Boot) which in turn generates a new auto-submit HTML form, which looks like this:
1<HTML> 2 <HEAD> 3 <TITLE>SAML HTTP Post Binding</TITLE> 4 </HEAD> 5 <BODY Onload="document.forms[0].submit()"> 6 <FORM METHOD="POST" ACTION="http://localhost:8081/auth/realms/demo/protocol/saml"> 7 <INPUT TYPE="HIDDEN" NAME="SAMLResponse" VALUE="PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhb...Base64 encoded SAML LogoutRequest"> 8 <P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P> 9 <INPUT TYPE="SUBMIT" VALUE="CONTINUE"/></NOSCRIPT> 10 </FORM> 11 </BODY> 12</HTML>
This triggers the browser to send an HTTP POST
request to http://localhost:8081/auth/realms/demo/protocol/saml
with the SAML LogoutRequest
in the request body:
1<saml2p:LogoutRequest Destination="http://localhost:8081/auth/realms/demo/protocol/saml" 2 ID="a2065g8i0cf875dj174d7ja6j3d5gbh" IssueInstant="2019-02-28T20:19:06.791Z" Version="2.0" 3 xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"> 4 <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">com:vdenotaris:spring:sp</saml2:Issuer> 5 <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 6 <ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 7 <ds:Reference URI="#a2065g8i0cf875dj174d7ja6j3d5gbh"> 8 <ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 9 <ds:DigestValue>ERsgSFrLFUpkbfEvYJ97eQgg3RQ=</ds:DigestValue> 10 </ds:Reference> 11 </ds:SignedInfo> 12 <ds:SignatureValue>U/zrNEk4eJk7CXxYYaj5MUaWmAgqo8bve1wEVLFCenpGgCAKmYHhQdoLdiDDnoIqxhNTyDBEPCDMWcoDyS6SNY3luubMdPHmrBCOXjV+k3vbORHk/w6O72aUHZ4UwLeJmna8H0dDM+oXaX8tQ5y5unY57bFLEvbZGj0hQVVbphU9B+vFaBD6UPHJCSFORUayhAYWr7MNRUgz4vCM4pB0zkFXBzusKMl5VAOH5fnVvDy4k06QU4i1VGpB4dHWEdIINdUgURPj2COyRQV8TSzy+1+lGCgoubIishYSbtuhCc2Xex4Spiaxe3Z67j5xSAabRY1J3BYwt1z4bkIxfl8sKA==</ds:SignatureValue> 13 <ds:KeyInfo> 14 <ds:X509Data> 15 <ds:X509Certificate>MIIDUjCCAjqgAwIBAgIEUOLIQTANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJGSTEQMA4GA1UE 16 CBMHVXVzaW1hYTERMA8GA1UEBxMISGVsc2lua2kxGDAWBgNVBAoTD1JNNSBTb2Z0d2FyZSBPeTEM 17 MAoGA1UECwwDUiZEMQ8wDQYDVQQDEwZhcG9sbG8wHhcNMTMwMTAxMTEyODAxWhcNMjIxMjMwMTEy 18 ODAxWjBrMQswCQYDVQQGEwJGSTEQMA4GA1UECBMHVXVzaW1hYTERMA8GA1UEBxMISGVsc2lua2kx 19 GDAWBgNVBAoTD1JNNSBTb2Z0d2FyZSBPeTEMMAoGA1UECwwDUiZEMQ8wDQYDVQQDEwZhcG9sbG8w 20 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXqP0wqL2Ai1haeTj0alwsLafhrDtUt00E 21 5xc7kdD7PISRA270ZmpYMB4W24Uk2QkuwaBp6dI/yRdUvPfOT45YZrqIxMe2451PAQWtEKWF5Z13 22 F0J4/lB71TtrzyH94RnqSHXFfvRN8EY/rzuEzrpZrHdtNs9LRyLqcRTXMMO4z7QghBuxh3K5gu7K 23 qxpHx6No83WNZj4B3gvWLRWv05nbXh/F9YMeQClTX1iBNAhLQxWhwXMKB4u1iPQ/KSaal3R26pON 24 UUmu1qVtU1quQozSTPD8HvsDqGG19v2+/N3uf5dRYtvEPfwXN3wIY+/R93vBA6lnl5nTctZIRsyg 25 0Gv5AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFQwAAYUjso1VwjDc2kypK/RRcB8bMAUUIG0hLGL 26 82IvnKouGixGqAcULwQKIvTs6uGmlgbSG6Gn5ROb2mlBztXqQ49zRvi5qWNRttir6eyqwRFGOM6A 27 8rxj3Jhxi2Vb/MJn7XzeVHHLzA1sV5hwl/2PLnaL2h9WyG9QwBbwtmkMEqUt/dgixKb1Rvby/tBu 28 RogWgPONNSACiW+Z5o8UdAOqNMZQozD/i1gOjBXoF0F5OksjQN7xoQZLj9xXefxCFQ69FPcFDeEW 29 bHwSoBy5hLPNALaEUoa5zPDwlixwRjFQTc5XXaRpgIjy/2gsL8+Y5QRhyXnLqgO67BlLYW/GuHE=</ds:X509Certificate> 30 </ds:X509Data> 31 </ds:KeyInfo> 32 </ds:Signature> 33 <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" 34 xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">tester</saml2:NameID> 35 <saml2p:SessionIndex>220f505a-1928-4855-8251-1036b0f95e82::aa87b005-0b74-45f6-a806-e2193a6288ad</saml2p:SessionIndex> 36</saml2p:LogoutRequest>
to which the Keycloak IDP responds with:
1<HTML> 2 <HEAD> 3 <TITLE>SAML HTTP Post Binding</TITLE> 4 </HEAD> 5 <BODY Onload="document.forms[0].submit()"> 6 <FORM METHOD="POST" ACTION="http://localhost:8080/saml/logout"> 7 <INPUT TYPE="HIDDEN" NAME="SAMLResponse" VALUE="PHNhbWxwOkxvZ291d... Base64 encoded LogoutResponse"/> 8 <NOSCRIPT> 9 <P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P> 10 <INPUT TYPE="SUBMIT" VALUE="CONTINUE"/> 11 </NOSCRIPT> 12 </FORM> 13 </BODY> 14</HTML>
…which contains the SAML LogoutResponse
:
1<samlp:LogoutResponse Destination="http://localhost:8080/saml/logout" 2 ID="ID_c413b65d-02fe-4620-85bc-b6607ccfa90a" InResponseTo="a270a944ih90jb024di4j3cfddd98e5" 3 IssueInstant="2019-02-28T20:01:24.735Z" Version="2.0" 4 xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> 5 <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8081/auth/realms/demo</saml:Issuer> 6 <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> 7 <dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> 8 <dsig:Reference URI="#ID_c413b65d-02fe-4620-85bc-b6607ccfa90a"> 9 <dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> 10 <dsig:DigestValue>ZDg030QoeKzEkLUrhCKC1uBIaIDc/ucdnaCXSWEYH0I=</dsig:DigestValue> 11 </dsig:Reference> 12 </dsig:SignedInfo> 13 <dsig:SignatureValue>pnNC4Xh+XdBDdW6YQj+ZgmxgETYOOvrEfuAZsP/xTQXoTTksu+RGWSnIhNU/QFaDXCGRosfGyLWh6t7SFxUgkQ95E0VVGC7MKCsQ9cCg5sdXzxRzcPpRodPrkIp02DWv4PiMmjzLoxHKhTsLgII9JCuFTEay2U1L41/U5IiweHdYbavG946Vo7bshNOIQ9FtIZUBGh4OyQXwPJKE1G19w8bu5sGnXRnBlrfBiZYG6NuPV7zyLlhmunx4ZUBAFT0vOq4gDPe9UocOQRe3dFKFEj33DHOIv9x+wFt/VQwFbrxTkRePNp916p8+UXFjs5KM3mlOhjnqZq3dH1eYq49G3A==</dsig:SignatureValue> 14 <dsig:KeyInfo> 15 <dsig:KeyName>PrmJE0uxLVfFemeO41pwrZ8P3Pxmi8q44V4553olejE</dsig:KeyName> 16 <dsig:X509Data> 17 <dsig:X509Certificate>MIIClzCCAX8CBgFo2/zejjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARkZW1vMB4XDTE5MDIxMTA5NTUwOFoXDTI5MDIxMTA5NTY0OFowDzENMAsGA1UEAwwEZGVtbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANGej7NgaqGe762Z5g2dch/Pr6G2q3fZlN8aUfU1+lzBrgL/kwRrsCr0zeQ4EcXWpfV5ayMl+0Ouc+Q8VMObVr+8+Iq2b6NUaOMR+GiOc3vCcEEtB3zfNVqE3FFeAI6vTDA4u45M0NKUkn1dMtITQj2K2Mmz/pjwmGCo1jh9MS3loZU07om8UjHNrrg/4Tct97EONnTdYgHNetNRS3xsXdzJc64KtovA+Muk93XMhQe1MR8iIdkSX1kIuJg0Ka9Y996dKstDB8nzTUlEQs/vw4iSu6IKu+cOvdrs+HFyvCVUWmqVpqh/AL+MgJxtRcfj7tPWESSe+bukwcz+icogEAUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAult+p9pECxU32gKFaMCUt0bDFsDU00nM3hPpRUijJchJe68NvXn9Pv2DwbIPpSQpYJAsG3xoK36h/S7oTF3SosnZVtrHXhzN+aNWKgoDGcR8d4WtT6kKphI8Mf123qyPPC+5v7CQxDOW6wXd+0XQFRIfHSfyH0gxRsnFoYiapnAgOVftozMCm2F2ZZQmhPtxaigQ6rhVWIDbemhKlwEV49H83Qkh9c/jfngVdYB1yA/MfSsossk6u8w47egSt73FXVAHginX4obHp+HEOOU7C8myOIyKq74nPvesvmffIv7ttgvLoEhdK/S3p7AiHppxgWb1roD/7P1Tk21eqOBW3Q==</dsig:X509Certificate> 18 </dsig:X509Data> 19 <dsig:KeyValue> 20 <dsig:RSAKeyValue> 21 <dsig:Modulus>0Z6Ps2BqoZ7vrZnmDZ1yH8+vobard9mU3xpR9TX6XMGuAv+TBGuwKvTN5DgRxdal9XlrIyX7Q65z5DxUw5tWv7z4irZvo1Ro4xH4aI5ze8JwQS0HfN81WoTcUV4Ajq9MMDi7jkzQ0pSSfV0y0hNCPYrYybP+mPCYYKjWOH0xLeWhlTTuibxSMc2uuD/hNy33sQ42dN1iAc1601FLfGxd3Mlzrgq2i8D4y6T3dcyFB7UxHyIh2RJfWQi4mDQpr1j33p0qy0MHyfNNSURCz+/DiJK7ogq75w692uz4cXK8JVRaapWmqH8Av4yAnG1Fx+Pu09YRJJ75u6TBzP6JyiAQBQ==</dsig:Modulus> 22 <dsig:Exponent>AQAB</dsig:Exponent> 23 </dsig:RSAKeyValue> 24 </dsig:KeyValue> 25 </dsig:KeyInfo> 26 </dsig:Signature> 27 <samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status> 28</samlp:LogoutResponse>
…which is then finally posted to the http://localhost:8080/saml/logout
endpoint of the Spring Boot app to conclude the logout process. The Spring Boot app then sends a redirect back to the base URL where the user can log in again.
Enabling encryption of SAML assertions
Wow, that was already quite a lot to ingest, right? But we missed one important thing, encryption!
Let’s quickly configure encryption support in the Keycloak client and see how it affects the SAML messages. To enable encryption for our SAML client, we need to adjust the client configuration.
In the client settings
tab, configure the following:
- Encrypt Assertions:
On
In the SAML Keys
tab, configure in the Encryption Key
section
- Click on
import
- Archive Format
JKS
- Key-Alias
apollo
- Store pass
nalle123
- Select configure the path to
src/main/resources/saml/samlKeystore.jks
- Click
Import
Your client is now properly configured to use encryption. Let’s have a look at the SAML Response
messages with the SAML Chrome Panel
.
After another login, we can see that our SAML response looks different now:
1<samlp:Response Destination="http://localhost:8080/saml/SSO" 2 ID="ID_8d649c98-460c-4b98-82e5-90f2c11981c5" InResponseTo="a9e038agg66a512eh5h2141731e97" 3 IssueInstant="2019-02-28T20:42:13.260Z" Version="2.0" 4 xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 5 xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> 6 <saml:Issuer>http://localhost:8081/auth/realms/demo</saml:Issuer> 7 <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> 8 <dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> 9 <dsig:Reference URI="#ID_8d649c98-460c-4b98-82e5-90f2c11981c5"> 10 <dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> 11 <dsig:DigestValue>CHBO9/ggJS0Cc4zphZK5a4CWYg8gqW3Um6S9P8xB4zA=</dsig:DigestValue> 12 </dsig:Reference> 13 </dsig:SignedInfo> 14 <dsig:SignatureValue>MxIerokHeAVEv1Ag9HmIl0F8ZtKbDOVz1mUCiLGe3xGWUksUyOuvcLZFdtfx+o/TgQhnuRB0lSbUxUk642hqHcC3RvXqITbzENZ0ZyjTwxFJGF6mzZ6YOEIStApZJB8z2YvhvhcWU1eH1F1vE78w/78EgSEytkkfoAcC9ESdYpsK82iQn0/d9FxPdF7u7jkxALoh3I4MNuAqtrWL4Q4U8OqeO3Xjyr11g6gSlyiW9GlEflqKR7hTb50W2rVFS9JdB6iWTVJHrLyuiFYYLZv0kBUucM40+27QQ1eK82VCyBOJMNMNnbty6jkmKPRrqWICkkgSiKzmJ1JzyG3FV+DveA==</dsig:SignatureValue> 15 <dsig:KeyInfo> 16 <dsig:KeyName>PrmJE0uxLVfFemeO41pwrZ8P3Pxmi8q44V4553olejE</dsig:KeyName> 17 <dsig:X509Data> 18 <dsig:X509Certificate>MIIClzCCAX8CBgFo2/zejjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARkZW1vMB4XDTE5MDIxMTA5NTUwOFoXDTI5MDIxMTA5NTY0OFowDzENMAsGA1UEAwwEZGVtbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANGej7NgaqGe762Z5g2dch/Pr6G2q3fZlN8aUfU1+lzBrgL/kwRrsCr0zeQ4EcXWpfV5ayMl+0Ouc+Q8VMObVr+8+Iq2b6NUaOMR+GiOc3vCcEEtB3zfNVqE3FFeAI6vTDA4u45M0NKUkn1dMtITQj2K2Mmz/pjwmGCo1jh9MS3loZU07om8UjHNrrg/4Tct97EONnTdYgHNetNRS3xsXdzJc64KtovA+Muk93XMhQe1MR8iIdkSX1kIuJg0Ka9Y996dKstDB8nzTUlEQs/vw4iSu6IKu+cOvdrs+HFyvCVUWmqVpqh/AL+MgJxtRcfj7tPWESSe+bukwcz+icogEAUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAult+p9pECxU32gKFaMCUt0bDFsDU00nM3hPpRUijJchJe68NvXn9Pv2DwbIPpSQpYJAsG3xoK36h/S7oTF3SosnZVtrHXhzN+aNWKgoDGcR8d4WtT6kKphI8Mf123qyPPC+5v7CQxDOW6wXd+0XQFRIfHSfyH0gxRsnFoYiapnAgOVftozMCm2F2ZZQmhPtxaigQ6rhVWIDbemhKlwEV49H83Qkh9c/jfngVdYB1yA/MfSsossk6u8w47egSt73FXVAHginX4obHp+HEOOU7C8myOIyKq74nPvesvmffIv7ttgvLoEhdK/S3p7AiHppxgWb1roD/7P1Tk21eqOBW3Q==</dsig:X509Certificate> 19 </dsig:X509Data> 20 <dsig:KeyValue> 21 <dsig:RSAKeyValue> 22 <dsig:Modulus>0Z6Ps2BqoZ7vrZnmDZ1yH8+vobard9mU3xpR9TX6XMGuAv+TBGuwKvTN5DgRxdal9XlrIyX7Q65z5DxUw5tWv7z4irZvo1Ro4xH4aI5ze8JwQS0HfN81WoTcUV4Ajq9MMDi7jkzQ0pSSfV0y0hNCPYrYybP+mPCYYKjWOH0xLeWhlTTuibxSMc2uuD/hNy33sQ42dN1iAc1601FLfGxd3Mlzrgq2i8D4y6T3dcyFB7UxHyIh2RJfWQi4mDQpr1j33p0qy0MHyfNNSURCz+/DiJK7ogq75w692uz4cXK8JVRaapWmqH8Av4yAnG1Fx+Pu09YRJJ75u6TBzP6JyiAQBQ==</dsig:Modulus> 23 <dsig:Exponent>AQAB</dsig:Exponent> 24 </dsig:RSAKeyValue> 25 </dsig:KeyValue> 26 </dsig:KeyInfo> 27 </dsig:Signature> 28 <samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status> 29 <saml:EncryptedAssertion> 30 <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" 31 xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/> 32 <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 33 <xenc:EncryptedKey><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/> 34 <xenc:CipherData> 35 <xenc:CipherValue>QE3rdGu27xzELvm9qaPUHJY+gdD4lflVps8FRkEsJUYcpK24djhM56CJGFF66DMGDtZBrXtcPgRRnm2feNMVhx9AYi+r6iS6rS8NXst/c1qcFCNE80oW4w1AtxZ/Pz9MGT/Jlor2V973RZMBrvF4suqBj00xN93KWlxLhb+d99zfiLXok/QYhFqitmJnODBaqta5dwJClbbGy2ZrjyN/oYHQw+n/Qu46tIOogxb2l7Mqk298oJrR88e2gk0rEZvfkH6MPQ2ySWCCOmGJUCE6Wf/rO0f1RfGWmXiwwYbZLvBIltnt424wDUc+9oH9ivVLHDOYjpL4NGlOV64sH19bkQ==</xenc:CipherValue> 36 </xenc:CipherData> 37 </xenc:EncryptedKey> 38 </ds:KeyInfo> 39 <xenc:CipherData> 40 <xenc:CipherValue>a7KxLQXevbgy5tHOXQF7xjDUSd9x0EO276NokLlfQgSio3KZFjU+BzeNMnz6w4sYjUyHgzJ/42P.... Base64 encoded cipher value</xenc:CipherValue> 41 </xenc:CipherData> 42 </xenc:EncryptedData> 43 </saml:EncryptedAssertion> 44</samlp:Response>
Instead of an saml:Assertion
element we now see saml:EncryptedAssertion
which contains the data from our previous assertion in encrypted form.
Besides the various browser extensions, there is also a useful Burp extension called SAMLRaider , which can be used to inspect and manipulate SAML messages.
This concludes our quick tour of SAML interactions with our example application. I hope you enjoyed the ride and learned something new.
Hope to see you next time. 🙂
More articles
fromThomas Darimont
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Thomas Darimont
Principal IAM Consultant
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.