Continuing from last year, this year I will write an Advent Calendar centered on the members of NRI Open Standia. Last year, we focused on Keycloak, but this year we will write in the frame of open source, not limited to Keycloak (although Keycloak will appear on the first day). Well then, thank you.
What are you guys making applications for these days? How do you make the certification? I think there are various options these days. The project requirements I was involved in this time were as follows (I think it is a common configuration in recent enterprise projects).
--Application development by Spring Framework 5 is assumed --Authentication information and attribute information are stored in the existing authentication server --The existing authentication server supports SAML, and SAML can be used for authentication linkage to the application.
So, inevitably, Spring Security SAML was selected as a candidate and verified. I would like to write about what I learned in this process.
Currently, Spring operates on 22 main projects, 2 community projects and 3 Attic projects. This time, the Spring Security SAML to be handled is being developed as a subproject in Spring Security, which is one of the main projects.
So, I'm going to introduce Spring Security SAML. As of this writing, 1.0.3 has been released as GA.
: information_source: GitHub and [Maven Repository](https://mvnrepository.com/ artifact / org.springframework.security.extensions / spring-security-saml2-core / 1.0.4.RELEASE), [Spring site post](https://spring.io/blog/2018/03/16/spring- security-saml-1-0-4-released) has announced the release of 1.0.4, but Spring Security SAML Official Site Since 1.0.3 is still like GA, we will proceed with verification with 1.0.3 this time.
You can install the library by adding the dependencies published above and building it, but this time we will run the sample application listed in the official guide and verify the operation.
Here is the official guide to Spring Security SAML.
There is no doubt that you should read the whole thing, but first of all, the minimum required part to operate the sample application is [4. Quick start guide](https://docs.spring.io/spring-security] -saml / docs / 1.0.x / reference / htmlsingle / index.html # chapter-quick-start). Below are the steps I took when I verified it. Please read as appropriate according to your environment. Also, idp.ssocircle.com, which is an IdP introduced in the official guide, seems to have a limited number of times you can log in with a free tier. Therefore, it is recommended to prepare and verify Keycloak or an IdP that will be built immediately (the following is also the verification procedure with Keycloak).
Then, follow 4. Quick start guide I will continue to do.
Java 1.6+ SDK Apache Maven
This time, we are verifying with the following version.
$ java -version
java version "1.8.0_181"
$ mvn -version
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T03:33:14+09:00)
4.2. Installation steps 4.2.1. Downloading sample application First, download the 1.0.3 GA version binary including the sample application from the following and extract it.
4.2.2. Configuration of IDP metadata The sample application is designed to dynamically acquire metadata from the IdP when the SP is started. Since Keycloak is used for IdP this time, specify the metadata acquisition URL provided by the IdP you use. This time, specify as follows to set up Keycloak on localhost using port 8180 with the realm name openstandia.
\sample\src\main\webapp\WEB-INF\securityContext.xml(Excerpt)
<bean class="org.opensaml.saml2.metadata.provider.HTTPMetadataProvider">
<!-- URL containing the metadata -->
<constructor-arg>
<value type="java.lang.String">http://localhost:8180/auth/realms/openstandia/protocol/saml/descriptor</value>
</constructor-arg>
<!-- Timeout for metadata loading in ms -->
<constructor-arg>
<value type="int">15000</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
4.2.3. Generation of SP metadata Modify as follows to specify the entityId to be used by yourself.
\sample\src\main\webapp\WEB-INF\securityContext.xml(Excerpt)
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="urn:test:hiroshiaida:yokohama"/>
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="idpDiscoveryEnabled" value="true"/>
</bean>
</property>
</bean>
4.2.4. Compilation
Package with the mvn command, but before that, modify some pom.xml
. Despite pom.xml
included in Spring Security SAML 1.0.3, there is a part where the description is 1.0.0, so correct it.
pom.xml
$ diff -u ../../spring-security-saml-1.0.3.RELEASE/sample/pom.xml pom.xml
--- ../../spring-security-saml-1.0.3.RELEASE/sample/pom.xml 2017-12-20 17:34:40.000000000 +0900
+++ pom.xml 2018-12-01 03:30:02.783266900 +0900
@@ -5,7 +5,7 @@
<groupId>org.springframework.security.extensions</groupId>
<artifactId>spring-security-saml2-sample</artifactId>
<packaging>war</packaging>
- <version>1.0.0.RELEASE-SNAPSHOT</version>
+ <version>1.0.3.RELEASE-SNAPSHOT</version>
<name>Spring Security SAML v2 sample webapp</name>
<description>Spring Security SAML v2 sample webapp</description>
<url>https://github.com/SpringSource/spring-security-saml</url>
@@ -119,7 +119,7 @@
<dependency>
<groupId>org.springframework.security.extensions</groupId>
<artifactId>spring-security-saml2-core</artifactId>
- <version>1.0.0.RELEASE</version>
+ <version>1.0.3.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
After making the above modifications, package with the following mvn command.
$ mvn package
4.2.5. Deployment Start the sample application on Tomcat with the following command.
$ mvn tomcat7:run
It will start successfully, but you will probably get an Exception like the one below.
(Excerpt)
- Error retrieving metadata from http://localhost:8180/auth/realms/openstandia/protocol/saml/descriptor
java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
This error is as expected because Keycloak hasn't started yet, so proceed.
4.2.6. Uploading of SP metadata to the IDP
Download current SP metadata: Next, upload the SP metadata to the IdP (Keycloak). Spring Security SAML SP metadata can be obtained by directly accessing the URL below.
If spring_saml_metadata.xml` can be downloaded, the acquisition is successful.
Upload SP metadata to the IDP: Upload the metadata obtained above to Keycloak. For Keycloak, you can easily add SAML settings by following the steps below (Keycloak is described assuming that it is in Japanese).
(Screens for implementation of 2. and 3. above)
Basic settings related to SAML connection can be done above, but it is necessary to change Keycloak settings according to cooperation requirements such as user attribute mapping. The Keycloak settings and key settings used in this verification are shown in the capture at the end of this article. Please refer to it as appropriate.
4.3. Testing single sign-on and single logout Since the settings on the IdP side have been completed, restart the SP side and check the operation of single sign-on and single log-out. If the screen transition is successful as shown below, it is operating normally.
Go to http: // localhost: 8080 / spring-security-saml2-sample /. The Spring Security SAML sample application top screen is displayed. After selecting the check box of http: // localhost: 8180 / auth / realms / openstandia, press "Start single sign -on". The Keycloak login screen is displayed. After entering the ID / password, press the login button. After authentication, the Spring Security SAML sample application login screen will be displayed automatically. Click "Metadata Administration". The login screen for the Spring Security SAML sample application Administrator is displayed. After entering the ID / password, press the login button. After authentication, the Spring Security SAML sample application Administrator login screen will be displayed.
Up to this point, we have confirmed the operation of the Spring Security SAML sample application. I mentioned it briefly in the first "What I wanted to achieve", but this time, the original requirement was to run Spring Security SAML on Spring Framework 5. In fact, Spring Security SAML is based on Spring Framework 3 by the method described in the above procedure. You can see this by looking at the mvn command or the packaged war.
(Excerpt)
$ mvn dependency:tree
(Omitted)
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ spring-security-saml2-sample ---
[INFO] org.springframework.security.extensions:spring-security-saml2-sample:war:1.0.3.RELEASE-SNAPSHOT
[INFO] +- javax.servlet:jstl:jar:1.2:compile
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.6.3:compile
[INFO] | +- org.slf4j:slf4j-api:jar:1.6.3:compile
[INFO] | \- log4j:log4j:jar:1.2.16:compile
[INFO] +- org.springframework.security.extensions:spring-security-saml2-core:jar:1.0.3.RELEASE:compile
[INFO] | +- org.opensaml:opensaml:jar:2.6.1:compile
[INFO] | | +- org.opensaml:openws:jar:1.5.1:compile
[INFO] | | | +- org.opensaml:xmltooling:jar:1.4.1:compile
[INFO] | | | | +- org.bouncycastle:bcprov-jdk15:jar:1.46:compile
[INFO] | | | | \- ca.juliusdavies:not-yet-commons-ssl:jar:0.3.9:compile
[INFO] | | | +- commons-httpclient:commons-httpclient:jar:3.1:compile
[INFO] | | | \- org.apache.santuario:xmlsec:jar:1.5.6:compile
[INFO] | | +- commons-codec:commons-codec:jar:1.7:compile
[INFO] | | +- commons-collections:commons-collections:jar:3.2.1:compile
[INFO] | | +- commons-lang:commons-lang:jar:2.6:compile
[INFO] | | +- org.apache.velocity:velocity:jar:1.7:compile
[INFO] | | +- org.owasp.esapi:esapi:jar:2.0.1:compile
[INFO] | | +- joda-time:joda-time:jar:2.2:compile
[INFO] | | +- xerces:xercesImpl:jar:2.10.0:runtime
[INFO] | | +- xalan:serializer:jar:2.7.1:runtime
[INFO] | | +- xml-resolver:xml-resolver:jar:1.2:runtime
[INFO] | | \- xalan:xalan:jar:2.7.1:runtime
[INFO] | +- org.springframework.security:spring-security-core:jar:3.1.2.RELEASE:compile
[INFO] | +- org.springframework.security:spring-security-web:jar:3.1.2.RELEASE:compile
[INFO] | \- xml-apis:xml-apis:jar:1.4.01:runtime
[INFO] +- org.springframework.security:spring-security-config:jar:3.1.2.RELEASE:compile
[INFO] | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] +- org.springframework:spring-core:jar:3.1.2.RELEASE:compile
[INFO] | +- org.springframework:spring-asm:jar:3.1.2.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] +- org.springframework:spring-beans:jar:3.1.2.RELEASE:compile
[INFO] +- org.springframework:spring-context:jar:3.1.2.RELEASE:compile
[INFO] | \- org.springframework:spring-expression:jar:3.1.2.RELEASE:compile
[INFO] +- org.springframework:spring-aop:jar:3.1.2.RELEASE:compile
[INFO] +- org.springframework:spring-web:jar:3.1.2.RELEASE:compile
[INFO] +- org.springframework:spring-webmvc:jar:3.1.2.RELEASE:compile
[INFO] | \- org.springframework:spring-context-support:jar:3.1.2.RELEASE:compile
[INFO] +- javax.servlet:jsp-api:jar:2.0:provided
[INFO] | \- javax.servlet:servlet-api:jar:2.4:provided
[INFO] \- junit:junit:jar:4.4:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Spring Security SAML seems to be compatible with Spring Framework 5 in the release notes and reference guide,
On behalf of the community, I’m pleased to announce the release of Spring Security SAML 1.0.3.RELEASE which makes some minor changes to work with Spring Framework 5.0.0+ while keeping backward compatibility.
The current version of SAML Extension has been tested to work with Spring 3.1.2, Spring Security 3.1.2 and OpenSAML 2.6.1. Later versions of these libraries are likely to be compatible without need for modifications.
Since there are some uneasy descriptions such as "likely to be compatible", this time I tried running the Spring Security SAML sample application with Spring Framework 5 using the following approach.
This time, I rewrote the version of the dependent jar specified in pom.xml of the Spring Security SAML sample application to the version of Spring Framework 5.
--With the EOL announcement of Spring IO Platform, it is recommended to use spring-boot-starter-parent and spring-boot-dependencies (Spring IO Platform end-of-life announcement / blog / 2018/04/09 / spring-io-platform-end-of-life-announcement)), but if it doesn't work this time, I wanted to specify jar dependencies one by one and try and error, so the above I took an approach like this. --Because of the relationship with the Spring Framework version that was originally intended to be incorporated, this time the Spring IO Platform [Cairo SR1](https://spring.io/blog/2018/05/10/spring-io-platform-cairo- The version is specified according to sr1). In Cairo SR1, Spring Security related version is 5.0.5, Spring Framework related version is 5.0. It is .6. --If you do not specify spring-security-core and spring-security-web, 3 systems will come in, so explicitly specify 5.0.5.
The modified parts of pom.xml
are as follows.
pom.xml
$ diff -u ../../spring-security-saml-1.0.3.RELEASE_Keycloak/sample/pom.xml pom.xml
--- ../../spring-security-saml-1.0.3.RELEASE_Keycloak/sample/pom.xml 2018-12-01 03:30:02.783266900 +0900
+++ pom.xml 2018-12-01 04:34:36.179213100 +0900
@@ -113,7 +113,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
- <version>1.6.3</version>
+ <version>1.7.25</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -125,43 +125,55 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
- <version>3.1.2.RELEASE</version>
+ <version>5.0.5.RELEASE</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ <version>5.0.5.RELEASE</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-web</artifactId>
+ <version>5.0.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
- <version>3.1.2.RELEASE</version>
+ <version>5.0.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
- <version>3.1.2.RELEASE</version>
+ <version>5.0.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
- <version>3.1.2.RELEASE</version>
+ <version>5.0.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
- <version>3.1.2.RELEASE</version>
+ <version>5.0.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
- <version>3.1.2.RELEASE</version>
+ <version>5.0.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
- <version>3.1.2.RELEASE</version>
+ <version>5.0.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -173,7 +185,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.4</version>
+ <version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
Check the operation in the above environment. It didn't work at first, but in conclusion, it worked just by modifying the settings and code in the sample application. Since it worked with only the following changes, there was no particular library conflict, and we have determined that the Spring Security SAML 1.0.3 sample application simply did not support Spring Framework 5.
In the SAML POST binding method, the SAML Response is POSTed to the SP, but the above CSRF measures are also effective for the SAML endpoint, so if the sample application is operated as it is, the request will result in a 403 error. (Although it is proof that CSRF measures are effective). This time, referring to the URL below, we have separated the SAML endpoint and the normal endpoint.
The other, easier is to define Spring SAML endpoints in a separate http configuration which will not have the csrf protection enabled.
\sample\src\main\webapp\WEB-INF\securityContext.xml modification(Excerpt)
<!-- Secured pages with SAML as entry point -->
- <security:http entry-point-ref="samlEntryPoint" use-expressions="false">
+ <security:http pattern="/saml/**" entry-point-ref="samlEntryPoint" use-expressions="false">
+ <security:csrf disabled="true"/>
+ <security:intercept-url pattern="/saml/**" access="IS_AUTHENTICATED_FULLY"/>
+ <security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
+ <security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
+ </security:http>
+
+ <!-- Secured pages with Not SAML as entry point -->
+ <security:http pattern="/**" entry-point-ref="samlEntryPoint" use-expressions="false">
+ <security:csrf disabled="false"/>
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
<security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
Spring Security has been changed so that CSRF measures are enabled by default when it goes up from 3 to 4.
As Spring Security 4.0+ CSRF Protection is now enabled by default.
Therefore, applications that do not take CSRF measures are inevitably required to take measures. Since POST is used to log in to the screen for Administrator in the sample application of Spring Security SAML 1.0.3, it is necessary to take measures to embed the CSRF token as shown below.
\sample\src\main\webapp\WEB-INF\security\adminLogin.Modification of jsp(Excerpt)
+ <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</div>
</div>
In Spring Security, the parameter name at the time of form login is changed at the timing of going up from 3 to 4.
If the
is being used within an application, then some of the default attributes have changed.
Since j_username and j_password are used in the sample application, they also need to be changed.
\sample\src\main\webapp\WEB-INF\security\adminLogin.Modification of jsp(Excerpt)
<table>
<tr>
<td><label for="username">User:</label></td>
- <td><input type='text' name='j_username' id="username" class="text" value='admin'></td>
+ <td><input type='text' name='username' id="username" class="text" value='admin'></td>
</tr>
<tr>
<td><label for="password">Password:</label></td>
- <td><input type='password' name='j_password' id="password" class="text" value="admin"/></td>
+ <td><input type='password' name='password' id="password" class="text" value="admin"/></td>
</tr>
<tr>
<td></td>
<td><input name="submit" class="button" type="submit" value="Login"/></td>
</tr>
</table>
The handling of the password encoder has also changed due to the change in Spring Security 4 → 5.
In the sample application, password encoding is not performed and the raw password is described in the configuration file, so change it to use BCryptPasswordEncoder.
\sample\src\main\webapp\WEB-INF\securityContext.xml modification(Excerpt)
+ <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
+
<security:authentication-manager alias="authenticationManager">
<!-- Register authentication manager for SAML provider -->
<security:authentication-provider ref="samlAuthenticationProvider"/>
<!-- Register authentication manager for administration UI -->
<security:authentication-provider>
+ <security:password-encoder ref="passwordEncoder"/>
<security:user-service id="adminInterfaceService">
- <security:user name="admin" password="admin" authorities="ROLE_ADMIN"/>
+ <security:user name="admin" password="$2a$10$ozKJfV0iGFKuK4J8Rm.3nuCtpe9dxK0fb/05WfoDejxQXxUcAjNzm" authorities="ROLE_ADMIN"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
This is the effect of the Spring MVC upgrade. There are places where commandName is used on various screens, but it is necessary to replace all with modelAttribute.
\sample\src\main\webapp\WEB-INF\security\metadataGenerator.Modification of jsp(Excerpt)
<div class="post-body">
<p><a href="<c:url value="/saml/web/metadata"/>"><< Back</a></p>
- <form:form commandName="metadata" action="create">
+ <form:form modelAttribute="metadata" action="create">
<table>
<tr>
<td><label for="store">Store for the current session:</label></td>
: information_source: metadataView.jsp and providerView.jsp also need to be modified.
The operation check of the sample application is completed by the above. After this, the following measures are required when embedding in the actual application.
Actually, from here, various design patterns can be considered depending on the structure and framework of the existing application, standardization guidelines, and so on. The guide provides a way to extend the SAMLUserDetailsService, and I think there is also a way to create parts according to the project standardization guidelines.
The sample application is undeveloped, but we have confirmed that Spring Security SAML 1.0.3 works with Spring Framework 5. SAML is an old protocol that is still often used even though it is said to be old, and I think it is inevitable that Spring will be centered on the 5th system in the future. We hope that this article will be helpful to those who will use it in the future.
: information_source: Currently, Spring Security SAML is being developed at:
-Qiita --Try using SAML with Keycloak (WordPress) -[Notes on challenging SAML authentication using Spring Security SAML](https://hotchpotchj37.wordpress.com/2018/07/23/spring-security-saml%E3%82%92%E4%BD%BF% E3% 81% A3% E3% 81% A6saml% E8% AA% 8D% E8% A8% BC% E3% 81% AB% E3% 83% 81% E3% 83% A3% E3% 83% AC% E3% 83% B3% E3% 82% B8% E3% 81% 97% E3% 81% 9F% E3% 83% A1% E3% 83% A2 /)
Recommended Posts