├── .gitignore ├── LICENSE ├── README.md ├── pom.xml ├── spring-boot-security-saml-demo-auth0 ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── Dockerfile ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml ├── run.sh └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── ulisesbocchio │ │ │ └── demo │ │ │ ├── Auth0SSODemoApplication.java │ │ │ └── controller │ │ │ ├── HomeController.java │ │ │ └── IdPSelectionController.java │ └── resources │ │ ├── KeyStore.jks │ │ ├── application.properties │ │ ├── idp-auth0-new.xml │ │ ├── idp-auth0.xml │ │ ├── localhost.cert │ │ ├── localhost.jks │ │ ├── localhost.key.der │ │ ├── logback.xml │ │ └── templates │ │ ├── help.html │ │ ├── home.html │ │ ├── idpselection.html │ │ ├── index.html │ │ └── protected.html │ └── test │ └── java │ └── com │ └── github │ └── ulisesbocchio │ └── demo │ └── SpringBootSecuritySamlDemoApplicationTests.java ├── spring-boot-security-saml-demo-dsl ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── ulisesbocchio │ │ │ └── demo │ │ │ ├── EnableSAMLSSOWhenNotInTest.java │ │ │ ├── SpringBootSecuritySAMLDemoApplication.java │ │ │ └── controller │ │ │ ├── HomeController.java │ │ │ └── IdPSelectionController.java │ └── resources │ │ ├── application.properties │ │ ├── idp-ssocircle.xml │ │ ├── localhost.cert │ │ ├── localhost.key.der │ │ ├── logback.xml │ │ └── templates │ │ ├── afterlogout.html │ │ ├── home.html │ │ ├── idpselection.html │ │ ├── index.html │ │ └── protected.html │ └── test │ └── java │ └── com │ └── github │ └── ulisesbocchio │ └── demo │ └── SpringBootSecuritySamlDemoApplicationTests.java ├── spring-boot-security-saml-demo-okta ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── ulisesbocchio │ │ │ └── demo │ │ │ ├── OktaSSODemoApplication.java │ │ │ └── controller │ │ │ ├── HomeController.java │ │ │ └── IdPSelectionController.java │ └── resources │ │ ├── application.properties │ │ ├── idp-okta.xml │ │ ├── localhost.cert │ │ ├── localhost.key.der │ │ ├── logback.xml │ │ └── templates │ │ ├── help.html │ │ ├── home.html │ │ ├── idpselection.html │ │ ├── index.html │ │ └── protected.html │ └── test │ └── java │ └── com │ └── github │ └── ulisesbocchio │ └── demo │ └── SpringBootSecuritySamlDemoApplicationTests.java ├── spring-boot-security-saml-demo-okta2 ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── ulisesbocchio │ │ │ └── demo │ │ │ ├── OktaSSODemoApplication2.java │ │ │ └── controller │ │ │ ├── HomeController.java │ │ │ └── IdPSelectionController.java │ └── resources │ │ ├── application.properties │ │ ├── idp-okta.xml │ │ ├── localhost.cert │ │ ├── localhost.key.der │ │ ├── logback.xml │ │ └── templates │ │ ├── help.html │ │ ├── home.html │ │ ├── idpselection.html │ │ ├── index.html │ │ └── protected.html │ └── test │ └── java │ └── com │ └── github │ └── ulisesbocchio │ └── demo │ └── SpringBootSecuritySamlDemoApplicationTests.java ├── spring-boot-security-saml-demo-props ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── ulisesbocchio │ │ │ └── demo │ │ │ ├── SpringBootSecuritySAMLDemoApplication.java │ │ │ └── controller │ │ │ ├── HomeController.java │ │ │ └── IdPSelectionController.java │ └── resources │ │ ├── application.properties │ │ ├── idp-ssocircle.xml │ │ ├── localhost.cert │ │ ├── localhost.key.der │ │ ├── logback.xml │ │ └── templates │ │ ├── home.html │ │ ├── idpselection.html │ │ ├── index.html │ │ └── protected.html │ └── test │ └── java │ └── com │ └── github │ └── ulisesbocchio │ └── demo │ └── SpringBootSecuritySamlDemoApplicationTests.java ├── spring-boot-security-saml-demo-static-metadata ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── ulisesbocchio │ │ │ └── demo │ │ │ ├── SpringBootSecuritySAMLDemoApplication.java │ │ │ └── controller │ │ │ ├── HomeController.java │ │ │ └── IdPSelectionController.java │ └── resources │ │ ├── application.properties │ │ ├── idp-ssocircle.xml │ │ ├── idp.ssocircle.com.cer │ │ ├── idp.ssocircle.com.pem │ │ ├── localhost.cert │ │ ├── localhost.jks │ │ ├── localhost.key.der │ │ ├── localhost.key.pem │ │ ├── localhost.p12 │ │ ├── logback.xml │ │ ├── sp-ssocircle.xml │ │ └── templates │ │ ├── home.html │ │ ├── idpselection.html │ │ ├── index.html │ │ └── protected.html │ └── test │ └── java │ └── com │ └── github │ └── ulisesbocchio │ └── demo │ └── SpringBootSecuritySamlDemoApplicationTests.java └── spring-security-saml-sample ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── ulisesbocchio │ │ └── security │ │ └── saml │ │ ├── SamlServiceProviderApplication.java │ │ ├── certificate │ │ └── KeystoreFactory.java │ │ ├── config │ │ ├── FilterCleanupConfig.java │ │ ├── MvcConfig.java │ │ ├── SAMLConfig.java │ │ ├── SAMLConfigDefaults.java │ │ └── WebSecurityConfig.java │ │ └── spring │ │ ├── SpringResourceWrapperOpenSAMLResource.java │ │ ├── mvc │ │ ├── HomeController.java │ │ ├── IdPSelectionController.java │ │ └── SAMLUser.java │ │ └── security │ │ ├── SAMLUserDetails.java │ │ └── SAMLUserDetailsServiceImpl.java └── resources │ ├── application.yml │ ├── idp-okta.xml │ ├── idp-onelogin.xml │ ├── idp-pingone.xml │ ├── idp-ssocircle.xml │ ├── localhost.cert │ ├── localhost.key │ ├── localhost.key.der │ ├── logback.xml │ └── templates │ ├── home.html │ ├── idpselection.html │ ├── index.html │ └── protected.html └── test └── java └── com └── ulisesbocchio └── security └── saml └── SamlSpSampleApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | 14 | **/target/ 15 | *.iml 16 | .DS_Store 17 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Sergio Ulises Bocchio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spring-boot-security-saml-samples 2 | Samples using spring-security-saml 3 | # License 4 | Lincensed under [MIT License](http://opensource.org/licenses/MIT) 5 | # Auth0 Sample 6 | Thanks [@arcseldon](https://github.com/arcseldon) for a [great sample](https://github.com/auth0-samples/auth0-java-springboot-security-saml-idp-client/tree/master/src/main/java/com/auth0/sample) using [Auth0](https://auth0.com/) 7 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM lwieske/java-8:jdk-8u77-slim 2 | EXPOSE 8080 3 | VOLUME /tmp 4 | ADD target/spring-boot-security-saml-demo-auth0-1.3-SNAPSHOT.jar app.jar 5 | RUN sh -c 'touch /app.jar' 6 | ENV JAVA_OPTS="" 7 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/README.md: -------------------------------------------------------------------------------- 1 | ## Spring Boot Security SAML Sample with Auth0 as IDP ## 2 | 3 | Run using the run script to run in docker container: 4 | 5 | ```bash 6 | ./run.sh 7 | ``` -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | spring-boot-security-saml-demo-auth0 6 | jar 7 | 8 | Spring Boot Security SAML Demo with Auth0 IDP 9 | Demo project for Spring Boot 10 | 11 | 12 | com.github.ulisesbocchio 13 | spring-boot-security-saml-samples-parent 14 | 1.3-SNAPSHOT 15 | 16 | 17 | 18 | UTF-8 19 | 1.8 20 | com.github.ulisesbocchio.demo.Auth0SSODemoApplication 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | 1.16.6 28 | 29 | 30 | com.github.ulisesbocchio 31 | spring-boot-security-saml 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-thymeleaf 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mvn package 4 | docker build . -t auth0-demo 5 | docker kill auth0-demo > /dev/null 2>&1 6 | docker rm -f auth0-demo > /dev/null 2>&1 7 | docker run -t -p 8080:8080 --rm --name auth0-demo auth0-demo -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/java/com/github/ulisesbocchio/demo/Auth0SSODemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.EnableSAMLSSO; 4 | import com.github.ulisesbocchio.spring.boot.security.saml.configurer.ServiceProviderBuilder; 5 | import com.github.ulisesbocchio.spring.boot.security.saml.configurer.ServiceProviderConfigurerAdapter; 6 | import com.github.ulisesbocchio.spring.boot.security.saml.user.SAMLUserDetails; 7 | import org.opensaml.saml2.core.Attribute; 8 | import org.opensaml.xml.security.BasicSecurityConfiguration; 9 | import org.opensaml.xml.signature.SignatureConstants; 10 | import org.springframework.beans.BeansException; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 13 | import org.springframework.boot.SpringApplication; 14 | import org.springframework.boot.autoconfigure.SpringBootApplication; 15 | import org.springframework.context.annotation.Bean; 16 | import org.springframework.context.annotation.Configuration; 17 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 18 | import org.springframework.security.core.GrantedAuthority; 19 | import org.springframework.security.core.userdetails.UserDetails; 20 | import org.springframework.security.core.userdetails.UserDetailsService; 21 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 22 | import org.springframework.security.saml.SAMLBootstrap; 23 | import org.springframework.security.saml.SAMLCredential; 24 | import org.springframework.security.saml.userdetails.SAMLUserDetailsService; 25 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 26 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 27 | 28 | import java.util.Collection; 29 | import java.util.Map; 30 | import java.util.Optional; 31 | import java.util.stream.Collectors; 32 | 33 | @SpringBootApplication 34 | @EnableSAMLSSO 35 | public class Auth0SSODemoApplication { 36 | 37 | public static void main(String[] args) { 38 | SpringApplication.run(Auth0SSODemoApplication.class, args); 39 | } 40 | 41 | @Configuration 42 | public static class MvcConfig implements WebMvcConfigurer { 43 | 44 | @Override 45 | public void addViewControllers(ViewControllerRegistry registry) { 46 | registry.addViewController("/").setViewName("index"); 47 | registry.addViewController("/protected").setViewName("protected"); 48 | registry.addViewController("/unprotected/help").setViewName("help"); 49 | 50 | } 51 | } 52 | 53 | static class CustomSAMLBootstrap extends SAMLBootstrap { 54 | @Override 55 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 56 | super.postProcessBeanFactory(beanFactory); 57 | BasicSecurityConfiguration config = (BasicSecurityConfiguration) org.opensaml.Configuration.getGlobalSecurityConfiguration(); 58 | config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); 59 | config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256); 60 | } 61 | } 62 | 63 | @Bean 64 | public SAMLUserDetailsService userDetailsService() { 65 | return new SAMLUserDetailsService() { 66 | @Override 67 | public Object loadUserBySAML(SAMLCredential samlCredential) throws UsernameNotFoundException { 68 | return new SAMLUserDetails(samlCredential) { 69 | @Override 70 | public Map getAttributes() { 71 | return samlCredential.getAttributes().stream() 72 | .collect(Collectors.toMap(Attribute::getName, this::getValue)); 73 | } 74 | 75 | private String getValue(Attribute attribute) { 76 | return Optional.ofNullable(getAttribute(attribute.getName())).orElse(""); 77 | } 78 | }; 79 | } 80 | }; 81 | } 82 | 83 | @Bean 84 | public static SAMLBootstrap SAMLBootstrap() { 85 | return new CustomSAMLBootstrap(); 86 | } 87 | 88 | @Configuration 89 | public static class MyServiceProviderConfig extends ServiceProviderConfigurerAdapter { 90 | 91 | @Autowired 92 | SAMLUserDetailsService userDetailsService; 93 | 94 | @Override 95 | public void configure(HttpSecurity http) throws Exception { 96 | // @formatter:off 97 | http.authorizeRequests() 98 | .antMatchers("/unprotected/**") 99 | .permitAll() 100 | .and() 101 | .anonymous(); 102 | // @formatter:on 103 | } 104 | 105 | @Override 106 | public void configure(ServiceProviderBuilder serviceProvider) throws Exception { 107 | // @formatter:off 108 | serviceProvider 109 | .metadataGenerator() 110 | .entityId("localhost-demo") 111 | .bindingsSSO("post") 112 | .and() 113 | .sso() 114 | .defaultSuccessURL("/home") 115 | .idpSelectionPageURL("/idpselection") 116 | .and() 117 | .metadataManager() 118 | .metadataLocations("classpath:/idp-auth0-new.xml") 119 | .refreshCheckInterval(0) 120 | .and() 121 | .extendedMetadata() 122 | .idpDiscoveryEnabled(true)//set to false for no IDP Selection page. 123 | .and() 124 | .keyManager() 125 | .storeLocation("classpath:/KeyStore.jks") 126 | .storePass("123456") 127 | .defaultKey("localhost") 128 | .keyPassword("localhost", "123456") 129 | .and() 130 | .authenticationProvider() 131 | .userDetailsService(userDetailsService); 132 | // @formatter:on 133 | 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/java/com/github/ulisesbocchio/demo/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.SAMLUser; 8 | import com.github.ulisesbocchio.spring.boot.security.saml.user.SAMLUserDetails; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | @Controller 14 | public class HomeController { 15 | 16 | @RequestMapping("/home") 17 | public ModelAndView home(@SAMLUser SAMLUserDetails user) { 18 | ModelAndView homeView = new ModelAndView("home"); 19 | homeView.addObject("userId", user.getUsername()); 20 | homeView.addObject("samlAttributes", user.getAttributes()); 21 | return homeView; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/java/com/github/ulisesbocchio/demo/controller/IdPSelectionController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.authentication.AuthenticationServiceException; 9 | import org.springframework.security.saml.SAMLConstants; 10 | import org.springframework.security.saml.SAMLDiscovery; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.servlet.ModelAndView; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import java.util.Collections; 17 | 18 | @Controller 19 | @RequestMapping("/idpselection") 20 | @Slf4j 21 | public class IdPSelectionController { 22 | 23 | @RequestMapping 24 | public ModelAndView idpSelection(HttpServletRequest request) { 25 | 26 | if (comesFromDiscoveryFilter(request)) { 27 | ModelAndView idpSelection = new ModelAndView("idpselection"); 28 | idpSelection.addObject(SAMLDiscovery.RETURN_URL, request.getAttribute(SAMLDiscovery.RETURN_URL)); 29 | idpSelection.addObject(SAMLDiscovery.RETURN_PARAM, request.getAttribute(SAMLDiscovery.RETURN_PARAM)); 30 | idpSelection.addObject("idpNameAliasMap", Collections.singletonMap("urn:ulisesbocchio.auth0.com", "Auth0")); 31 | return idpSelection; 32 | } 33 | throw new AuthenticationServiceException("SP Discovery flow not detected"); 34 | } 35 | 36 | private boolean comesFromDiscoveryFilter(HttpServletRequest request) { 37 | return request.getAttribute(SAMLConstants.LOCAL_ENTITY_ID) != null && 38 | request.getAttribute(SAMLDiscovery.RETURN_URL) != null && 39 | request.getAttribute(SAMLDiscovery.RETURN_PARAM) != null; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/KeyStore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-auth0/src/main/resources/KeyStore.jks -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | security.user.name=user 2 | security.user.password=password 3 | logging.level.org.springframework.security.saml= DEBUG -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/idp-auth0-new.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | MIIC9jCCAd6gAwIBAgIJNrKFCkHWDRQWMA0GCSqGSIb3DQEBCwUAMCIxIDAeBgNVBAMTF3VsaXNlc2JvY2NoaW8uYXV0aDAuY29tMB4XDTE3MDMwMzEyNTY0NVoXDTMwMTExMDEyNTY0NVowIjEgMB4GA1UEAxMXdWxpc2VzYm9jY2hpby5hdXRoMC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZNXivxdRqrnnmwLG4msH4tU2e+hXAS/CCXh1KAF9loBzzrGgG/fM6/KffpNKlEmrX1MdEVlCZLMkXg/F/riC5OkkERyl18A+BSsOOxBBVf5VwnYX3g2o4WQmPGBqUCHUK2VgCqRvTE2dyAgEvvhcD5b8MZ7KpTxt2WE34MtvD5rGERkVUVUcnq9RICMQSjf16nOip/XXXvM5Yx+fJGVs0/4Bz8HnedQZlBdOrqBh1UJb2Z3f4tIhktjavSllCOhKGgTMiHpuXoZtsc36UMjQdfUD5ejxrRhs8JPLBlHRz3oANTdk1fuEHT77CJjyS8MrAeymFgN6DUTg3WJ5G2+AdAgMBAAGjLzAtMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFI2587DMoucJtI6F0AVTLdKufEVfMA0GCSqGSIb3DQEBCwUAA4IBAQAWaB6NQNIkJhukz/GhqyAzQFr5z+PzzOQI5/mXV8iX95juoM8BKPXWoZL1GNol2D7ruMB1U5jGklE2nlPFvbepoTW3N6xrN9hw48IloA1BbbvQlHFgFwP27Hm9XcM9CGOpswCKyogs/rOSGekehw5tjAtaZZmuNq74YzI3LZK20Dp/kDtKawZb6bqTMDBaFJooHycRvcaPFDXjoceTKiPC2LNjU5zniSXQDg8J6obxMWsY4VixG32Y+YElErij/Llfj9EbF7SeLZeC3mgcozlmqGRVWXrR3fAAuQZR3sla3BFMVQVvyJwAWi7IPCa8i7+jzsD5pPBtx5wKoepBIkeF 7 | 8 | 9 | 10 | 11 | 12 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress 13 | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent 14 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/idp-auth0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | MIIC9jCCAd6gAwIBAgIJAGE1wODgykkSMA0GCSqGSIb3DQEBBQUAMCIxIDAeBgNVBAMTF3VsaXNlc2JvY2NoaW8uYXV0aDAuY29tMB4XDTE3MDEyMjAzNTgwMFoXDTMwMTAwMTAzNTgwMFowIjEgMB4GA1UEAxMXdWxpc2VzYm9jY2hpby5hdXRoMC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDoKTJgvsDDDlAjOdREP/azN+Ba+yjVxVP0Qh/VMgbQBEkOfRhjLVCo5G34dUhn0S1ltEYS+NJTW9+Wwog88Lu6KBZsOeBOzSDgCBLAALCMl/V6fG7OR0Vn76fT9pxhnOnLsX/CpXui2c8w71z6kQ/lpA9g052RkB9QW3Lpb7O4wrYavS46hOznr2aSDiFBTUExjPKPvmRDtDItx4wMpKJOgjuDNEokmU0aZUIDD4OBiT5D31nnyd7WQVPkvXfc07NNDcG9OEldafn25A1GXtjjAXjMZQGmrh/nhLwY4fcVO8zZyQpTWMjyGb3nUV2S5Nk1QatQF9gwWphXweEn2MTVAgMBAAGjLzAtMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFD2x4FRsBryW/4mjkWkjlmAe77NTMA0GCSqGSIb3DQEBBQUAA4IBAQCaqA+hlGdeX/eWFee5QXAcGosdjRC7F0E4KZuQ9FUQ1KyKKzavBZWCskW1V01u0D+MLwEYLL6WAvjMcL/RJA4eDMaQzHl8WM4FUKWlPzV74q+KXfAQhnzTubnkpDTx0iKFdJT8D1RWO5Cm557o7KGTbob3Ip4JVQTNV1wIlsDhi72FugFUzUxSgAecknMV4ernrGmVNh00tNTFOV/jSJcKNZfxCpboOGiWaOjeiGJykT8fyABHwFuJSgyMVOxJ2GNRhSCBLYG42eGRMpQHCU/v8/YlRrkPyeFapWG0z5ILJt0q6HF1nVxjjN1Ph1Z2fneCKpGeKUJ7f3fLor6Wg6Ce 7 | 8 | 9 | 10 | 11 | 12 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress 13 | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent 14 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/localhost.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQx 4 | EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7UFATYOYQZzIxsD9AtnXPh67uVkZTI 6 | oK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf75tKbem3pON2NlYW 7 | wIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup/cSL 8 | W4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+ 9 | e81R+u2UbNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHD 10 | jtf6gwwbdg3g9GvyqIJnRqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs3 11 | 5gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaAFMNtl5fAchs35gZS4EF8/0C7QfBQMAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADVL8LgYGlmaHlyrKyKfsQF 13 | TVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLbLbRNPXS+ 14 | qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1Bc 15 | oLRzMeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpS 16 | bbSR6XNgsPA0XLWlleuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB 17 | 9H10x+zy1nFWvqoa+K66EA4u7DpEoHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/localhost.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-auth0/src/main/resources/localhost.jks -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/localhost.key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-auth0/src/main/resources/localhost.key.der -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/templates/help.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Help Page 6 | 7 | 8 |

Help Page

9 |

10 | This is an UNPROTECTED Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Home Page 6 | 7 | 8 |

This is the Home Page

9 | 10 |

Current User: unknown

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
SAML Attributes
Attribute NameAttribute Value
keyvalue
26 |

27 | Idp Single Logout - Local Logout 28 |

29 | 30 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/templates/idpselection.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | IdP Selection 6 | 7 | 8 | Select an IdP: 9 |
10 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sample SAML Spring Boot Application 6 | 7 | 8 |

Hi, Click here to start the Single Sign On process

9 | 10 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/main/resources/templates/protected.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Protected Resource 6 | 7 | 8 |

Protected Resource

9 |

10 | This is a Protected Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-auth0/src/test/java/com/github/ulisesbocchio/demo/SpringBootSecuritySamlDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | import org.springframework.test.context.web.WebAppConfiguration; 8 | 9 | @RunWith(SpringJUnit4ClassRunner.class) 10 | @SpringBootTest(classes = Auth0SSODemoApplication.class) 11 | @WebAppConfiguration 12 | public class SpringBootSecuritySamlDemoApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | spring-boot-security-saml-demo-dsl 6 | jar 7 | 8 | Spring Boot Security SAML Demo with Java DSL 9 | Demo project for Spring Boot 10 | 11 | 12 | com.github.ulisesbocchio 13 | spring-boot-security-saml-samples-parent 14 | 1.3-SNAPSHOT 15 | 16 | 17 | 18 | UTF-8 19 | 1.8 20 | com.github.ulisesbocchio.demo.SpringBootSecuritySAMLDemoApplication 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | 1.16.6 28 | 29 | 30 | com.github.ulisesbocchio 31 | spring-boot-security-saml 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-thymeleaf 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/java/com/github/ulisesbocchio/demo/EnableSAMLSSOWhenNotInTest.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.EnableSAMLSSO; 4 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | @ConditionalOnMissingClass("org.junit.Test") 12 | @EnableSAMLSSO 13 | @Target(ElementType.TYPE) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface EnableSAMLSSOWhenNotInTest { 16 | } 17 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/java/com/github/ulisesbocchio/demo/SpringBootSecuritySAMLDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import com.github.ulisesbocchio.spring.boot.security.saml.configurer.ServiceProviderBuilder; 4 | import com.github.ulisesbocchio.spring.boot.security.saml.configurer.ServiceProviderConfigurerAdapter; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 10 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 11 | 12 | @SpringBootApplication 13 | @EnableSAMLSSOWhenNotInTest 14 | public class SpringBootSecuritySAMLDemoApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(SpringBootSecuritySAMLDemoApplication.class, args); 18 | } 19 | 20 | @Configuration 21 | public static class MvcConfig implements WebMvcConfigurer { 22 | 23 | @Override 24 | public void addViewControllers(ViewControllerRegistry registry) { 25 | registry.addViewController("/").setViewName("index"); 26 | registry.addViewController("/protected").setViewName("protected"); 27 | registry.addViewController("/afterlogout").setViewName("afterlogout"); 28 | 29 | } 30 | } 31 | 32 | @Configuration 33 | public static class MyServiceProviderConfig extends ServiceProviderConfigurerAdapter { 34 | 35 | @Override 36 | public void configure(HttpSecurity http) throws Exception { 37 | http.authorizeRequests() 38 | .regexMatchers("/") 39 | .permitAll(); 40 | } 41 | 42 | @Override 43 | public void configure(ServiceProviderBuilder serviceProvider) throws Exception { 44 | // @formatter:off 45 | serviceProvider 46 | .metadataGenerator() 47 | .entityId("localhost-demo") 48 | .and() 49 | .sso() 50 | .defaultSuccessURL("/home") 51 | .idpSelectionPageURL("/idpselection") 52 | .and() 53 | .logout() 54 | .defaultTargetURL("/afterlogout") 55 | .and() 56 | .metadataManager() 57 | .metadataLocations("classpath:/idp-ssocircle.xml") 58 | .refreshCheckInterval(0) 59 | .and() 60 | .extendedMetadata() 61 | .idpDiscoveryEnabled(true) 62 | .and() 63 | .keyManager() 64 | .privateKeyDERLocation("classpath:/localhost.key.der") 65 | .publicKeyPEMLocation("classpath:/localhost.cert") 66 | .and() 67 | .samlContextProviderLb() 68 | .scheme("http") 69 | .contextPath("/") 70 | .serverName("localhost") 71 | .serverPort(8080) 72 | .includeServerPortInRequestURL(true) 73 | .and(); 74 | // @formatter:on 75 | 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/java/com/github/ulisesbocchio/demo/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.SAMLUser; 8 | import com.github.ulisesbocchio.spring.boot.security.saml.user.SAMLUserDetails; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | @Controller 14 | public class HomeController { 15 | 16 | @RequestMapping("/home") 17 | public ModelAndView home(@SAMLUser SAMLUserDetails user) { 18 | ModelAndView homeView = new ModelAndView("home"); 19 | homeView.addObject("userId", user.getUsername()); 20 | homeView.addObject("samlAttributes", user.getAttributes()); 21 | return homeView; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/java/com/github/ulisesbocchio/demo/controller/IdPSelectionController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.authentication.AuthenticationServiceException; 9 | import org.springframework.security.saml.SAMLConstants; 10 | import org.springframework.security.saml.SAMLDiscovery; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.servlet.ModelAndView; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import java.util.Collections; 17 | 18 | @Controller 19 | @RequestMapping("/idpselection") 20 | @Slf4j 21 | public class IdPSelectionController { 22 | 23 | @RequestMapping 24 | public ModelAndView idpSelection(HttpServletRequest request) { 25 | 26 | if (comesFromDiscoveryFilter(request)) { 27 | ModelAndView idpSelection = new ModelAndView("idpselection"); 28 | idpSelection.addObject(SAMLDiscovery.RETURN_URL, request.getAttribute(SAMLDiscovery.RETURN_URL)); 29 | idpSelection.addObject(SAMLDiscovery.RETURN_PARAM, request.getAttribute(SAMLDiscovery.RETURN_PARAM)); 30 | idpSelection.addObject("idpNameAliasMap", Collections.singletonMap("http://idp.ssocircle.com", "SSO Circle")); 31 | return idpSelection; 32 | } 33 | throw new AuthenticationServiceException("SP Discovery flow not detected"); 34 | } 35 | 36 | private boolean comesFromDiscoveryFilter(HttpServletRequest request) { 37 | return request.getAttribute(SAMLConstants.LOCAL_ENTITY_ID) != null && 38 | request.getAttribute(SAMLDiscovery.RETURN_URL) != null && 39 | request.getAttribute(SAMLDiscovery.RETURN_PARAM) != null; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | security.user.name=user 2 | security.user.password=password 3 | logging.level.org.springframework.security.saml= DEBUG 4 | # Alternatively use below properties to configure the LB context provider 5 | #saml.sso.context-provider.lb.context-path=/ 6 | #saml.sso.context-provider.lb.include-server-port-in-request-url=true 7 | #saml.sso.context-provider.lb.scheme=http 8 | #saml.sso.context-provider.lb.server-name=localhost 9 | #saml.sso.context-provider.lb.server-port=8080 -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/localhost.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQx 4 | EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7UFATYOYQZzIxsD9AtnXPh67uVkZTI 6 | oK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf75tKbem3pON2NlYW 7 | wIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup/cSL 8 | W4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+ 9 | e81R+u2UbNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHD 10 | jtf6gwwbdg3g9GvyqIJnRqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs3 11 | 5gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaAFMNtl5fAchs35gZS4EF8/0C7QfBQMAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADVL8LgYGlmaHlyrKyKfsQF 13 | TVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLbLbRNPXS+ 14 | qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1Bc 15 | oLRzMeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpS 16 | bbSR6XNgsPA0XLWlleuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB 17 | 9H10x+zy1nFWvqoa+K66EA4u7DpEoHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/localhost.key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-dsl/src/main/resources/localhost.key.der -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/templates/afterlogout.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sample SAML Spring Boot Application 6 | 7 | 8 |

Goodbye! Click here if you wanna log back in

9 | 10 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Home Page 6 | 7 | 8 |

This is the Home Page

9 | 10 |

Current User: unknown

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
SAML Attributes
Attribute NameAttribute Value
keyvalue
26 |

27 | Idp Single Logout - Local Logout 28 |

29 | 30 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/templates/idpselection.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | IdP Selection 6 | 7 | 8 | Select an IdP: 9 |
10 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sample SAML Spring Boot Application 6 | 7 | 8 |

Hi, Click here to start the Single Sign On process

9 | 10 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/main/resources/templates/protected.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Protected Resource 6 | 7 | 8 |

Protected Resource

9 |

10 | This is a Protected Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-dsl/src/test/java/com/github/ulisesbocchio/demo/SpringBootSecuritySamlDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | import org.springframework.test.context.web.WebAppConfiguration; 8 | 9 | @RunWith(SpringJUnit4ClassRunner.class) 10 | @SpringBootTest(classes = SpringBootSecuritySAMLDemoApplication.class) 11 | @WebAppConfiguration 12 | public class SpringBootSecuritySamlDemoApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/README.md: -------------------------------------------------------------------------------- 1 | ## Spring Boot Security SAML Sample with OKTA as IDP ## 2 | 3 | Simply run the Spring Boot app and login with the following credentials: 4 | 5 | - user: dough1234321@gmail.com pass: Test1234! -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | spring-boot-security-saml-demo-okta 6 | jar 7 | 8 | Spring Boot Security SAML Demo with Okta IDP 9 | Demo project for Spring Boot 10 | 11 | 12 | com.github.ulisesbocchio 13 | spring-boot-security-saml-samples-parent 14 | 1.3-SNAPSHOT 15 | 16 | 17 | 18 | UTF-8 19 | 1.8 20 | com.github.ulisesbocchio.demo.OktaSSODemoApplication 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | 1.16.6 28 | 29 | 30 | com.github.ulisesbocchio 31 | spring-boot-security-saml 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-thymeleaf 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/java/com/github/ulisesbocchio/demo/OktaSSODemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.EnableSAMLSSO; 4 | import com.github.ulisesbocchio.spring.boot.security.saml.configurer.ServiceProviderConfigurerAdapter; 5 | import com.github.ulisesbocchio.spring.boot.security.saml.configurer.ServiceProviderBuilder; 6 | 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 12 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 13 | 14 | @SpringBootApplication 15 | @EnableSAMLSSO 16 | public class OktaSSODemoApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(OktaSSODemoApplication.class, args); 20 | } 21 | 22 | @Configuration 23 | public static class MvcConfig implements WebMvcConfigurer { 24 | 25 | @Override 26 | public void addViewControllers(ViewControllerRegistry registry) { 27 | registry.addViewController("/").setViewName("index"); 28 | registry.addViewController("/protected").setViewName("protected"); 29 | registry.addViewController("/unprotected/help").setViewName("help"); 30 | 31 | } 32 | } 33 | 34 | @Configuration 35 | public static class MyServiceProviderConfig extends ServiceProviderConfigurerAdapter { 36 | 37 | @Override 38 | public void configure(HttpSecurity http) throws Exception { 39 | // @formatter:off 40 | http.authorizeRequests() 41 | .antMatchers("/unprotected/**") 42 | .permitAll() 43 | .and() 44 | .anonymous(); 45 | // @formatter:on 46 | } 47 | 48 | @Override 49 | public void configure(ServiceProviderBuilder serviceProvider) throws Exception { 50 | // @formatter:off 51 | serviceProvider 52 | .metadataGenerator() 53 | .entityId("localhost-demo") 54 | .bindingsSSO("artifact", "post", "paos") 55 | .and() 56 | .ecpProfile() 57 | .and() 58 | .sso() 59 | .defaultSuccessURL("/home") 60 | .idpSelectionPageURL("/idpselection") 61 | .and() 62 | .metadataManager() 63 | .metadataLocations("classpath:/idp-okta.xml") 64 | .refreshCheckInterval(0) 65 | .and() 66 | .extendedMetadata() 67 | .ecpEnabled(true) 68 | .idpDiscoveryEnabled(true)//set to false for no IDP Selection page. 69 | .and() 70 | .keyManager() 71 | .privateKeyDERLocation("classpath:/localhost.key.der") 72 | .publicKeyPEMLocation("classpath:/localhost.cert"); 73 | // @formatter:on 74 | 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/java/com/github/ulisesbocchio/demo/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.SAMLUser; 8 | import com.github.ulisesbocchio.spring.boot.security.saml.user.SAMLUserDetails; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | @Controller 14 | public class HomeController { 15 | 16 | @RequestMapping("/home") 17 | public ModelAndView home(@SAMLUser SAMLUserDetails user) { 18 | ModelAndView homeView = new ModelAndView("home"); 19 | homeView.addObject("userId", user.getUsername()); 20 | homeView.addObject("samlAttributes", user.getAttributes()); 21 | return homeView; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/java/com/github/ulisesbocchio/demo/controller/IdPSelectionController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.authentication.AuthenticationServiceException; 9 | import org.springframework.security.saml.SAMLConstants; 10 | import org.springframework.security.saml.SAMLDiscovery; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.servlet.ModelAndView; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import java.util.Collections; 17 | 18 | @Controller 19 | @RequestMapping("/idpselection") 20 | @Slf4j 21 | public class IdPSelectionController { 22 | 23 | @RequestMapping 24 | public ModelAndView idpSelection(HttpServletRequest request) { 25 | 26 | if (comesFromDiscoveryFilter(request)) { 27 | ModelAndView idpSelection = new ModelAndView("idpselection"); 28 | idpSelection.addObject(SAMLDiscovery.RETURN_URL, request.getAttribute(SAMLDiscovery.RETURN_URL)); 29 | idpSelection.addObject(SAMLDiscovery.RETURN_PARAM, request.getAttribute(SAMLDiscovery.RETURN_PARAM)); 30 | idpSelection.addObject("idpNameAliasMap", Collections.singletonMap("http://www.okta.com/exk62w7tqv0xkRl9p0h7", "Okta")); 31 | return idpSelection; 32 | } 33 | throw new AuthenticationServiceException("SP Discovery flow not detected"); 34 | } 35 | 36 | private boolean comesFromDiscoveryFilter(HttpServletRequest request) { 37 | return request.getAttribute(SAMLConstants.LOCAL_ENTITY_ID) != null && 38 | request.getAttribute(SAMLDiscovery.RETURN_URL) != null && 39 | request.getAttribute(SAMLDiscovery.RETURN_PARAM) != null; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | security.user.name=user 2 | security.user.password=password 3 | logging.level.org.springframework.security.saml= DEBUG -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/idp-okta.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 9 | MIIDpDCCAoygAwIBAgIGAVO669oLMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG 10 | A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU 11 | MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi04MzkyMjgxHDAaBgkqhkiG9w0BCQEW 12 | DWluZm9Ab2t0YS5jb20wHhcNMTYwMzI4MDE1MTEyWhcNMjYwMzI4MDE1MjEyWjCBkjELMAkGA1UE 13 | BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNV 14 | BAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtODM5MjI4MRwwGgYJ 15 | KoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 16 | 0H9hcvueaxQsH+GjDBPJdQ3FotGgPFOyFuZFvDwBeXiTMPAMoB8s+9Ey7ugYoAvLJMm7ryXAhOGa 17 | tblP4BcxPWrFJx+Tddswkb9pmM9rbmfrBBW3gsiwPQ/bEuwnvNxICIaeWD7h50Qej8UgrSunqmEq 18 | pBYi530/mWy7fdyRWniC0NtqlGDc+7jM4itchIjxuJXm0MX8BTzUkk8yU/Ul/YwNCwTAZNwispES 19 | ADsU9Mc+qcI6Fc68NC8pzPTpV4XEIiDwK8bfdQa1kwM3teL+1cHTXkEMvfhzBLZLedaB7b2Ictp+ 20 | /mPtX/m9+zu/oqeZs1ZfCPfOpaNQCw4ug/G7PQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAxlYaA 21 | PPB8kvNZgLX1V/WGxfpQTZMVLJGCfVA50I7wzRn+bDgkLhl2L3Rn7V7epQ7yOGYoIZ2QZGqu8fto 22 | xyXLmbx+gKvrejPp8QGCDl4Ga9UppIRtvdnLpXKeBw1m2GbLbgIlMmCbSGo05YSxBM7m6C7ZBDbA 23 | Sn8kNrM+77jWPs+uRO/Oe9UlMGIMIvxaUyy7H9TpUNHAMQKwYPiua/32T53iv9TZ6YYgdK1b2haA 24 | N3ESCsNEmU5BRZBQgBMRiw1qfWt5tGpAxjCKkVFEwR6gQwqH5QhAnzA9lyVAq8FGr7HDxMyLoObB 25 | avSvuMAJ1fZFZh4v3XJussihq2MjHH3g 26 | 27 | 28 | 29 | 30 | 32 | 34 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress 35 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified 36 | 38 | 40 | 41 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/localhost.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQx 4 | EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7UFATYOYQZzIxsD9AtnXPh67uVkZTI 6 | oK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf75tKbem3pON2NlYW 7 | wIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup/cSL 8 | W4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+ 9 | e81R+u2UbNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHD 10 | jtf6gwwbdg3g9GvyqIJnRqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs3 11 | 5gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaAFMNtl5fAchs35gZS4EF8/0C7QfBQMAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADVL8LgYGlmaHlyrKyKfsQF 13 | TVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLbLbRNPXS+ 14 | qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1Bc 15 | oLRzMeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpS 16 | bbSR6XNgsPA0XLWlleuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB 17 | 9H10x+zy1nFWvqoa+K66EA4u7DpEoHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/localhost.key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-okta/src/main/resources/localhost.key.der -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/templates/help.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Help Page 6 | 7 | 8 |

Help Page

9 |

10 | This is an UNPROTECTED Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Home Page 6 | 7 | 8 |

This is the Home Page

9 | 10 |

Current User: unknown

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
SAML Attributes
Attribute NameAttribute Value
keyvalue
26 |

27 | Idp Single Logout - Local Logout 28 |

29 | 30 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/templates/idpselection.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | IdP Selection 6 | 7 | 8 | Select an IdP: 9 |
10 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sample SAML Spring Boot Application 6 | 7 | 8 |

Hi, Click here to start the Single Sign On process

9 | 10 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/main/resources/templates/protected.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Protected Resource 6 | 7 | 8 |

Protected Resource

9 |

10 | This is a Protected Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta/src/test/java/com/github/ulisesbocchio/demo/SpringBootSecuritySamlDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | import org.springframework.test.context.web.WebAppConfiguration; 8 | 9 | @RunWith(SpringJUnit4ClassRunner.class) 10 | @SpringBootTest(classes = OktaSSODemoApplication.class) 11 | @WebAppConfiguration 12 | public class SpringBootSecuritySamlDemoApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/README.md: -------------------------------------------------------------------------------- 1 | ## Spring Boot Security SAML Sample with OKTA as IDP ## 2 | 3 | Simply run the Spring Boot app and login with the following credentials: 4 | 5 | - user: dough1234321@gmail.com pass: Test1234! 6 | 7 | This sample showcases the use of SAMLConfigurerBean instead of ServiceProviderConfigurer -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | spring-boot-security-saml-demo-okta2 6 | jar 7 | 8 | Spring Boot Security SAML Demo with Okta IDP 2 9 | Demo project for Spring Boot 10 | 11 | 12 | com.github.ulisesbocchio 13 | spring-boot-security-saml-samples-parent 14 | 1.3-SNAPSHOT 15 | 16 | 17 | 18 | UTF-8 19 | 1.8 20 | com.github.ulisesbocchio.demo.OktaSSODemoApplication2 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | 1.16.6 28 | 29 | 30 | com.github.ulisesbocchio 31 | spring-boot-security-saml 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-thymeleaf 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/java/com/github/ulisesbocchio/demo/OktaSSODemoApplication2.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.EnableSAMLSSO; 4 | import com.github.ulisesbocchio.spring.boot.security.saml.bean.SAMLConfigurerBean; 5 | 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.security.authentication.AuthenticationManager; 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 12 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 14 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 15 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 16 | 17 | @SpringBootApplication 18 | @EnableSAMLSSO 19 | public class OktaSSODemoApplication2 { 20 | 21 | public static void main(String[] args) { 22 | SpringApplication.run(OktaSSODemoApplication2.class, args); 23 | } 24 | 25 | @Configuration 26 | public static class MvcConfig implements WebMvcConfigurer { 27 | 28 | @Override 29 | public void addViewControllers(ViewControllerRegistry registry) { 30 | registry.addViewController("/").setViewName("index"); 31 | registry.addViewController("/protected").setViewName("protected"); 32 | registry.addViewController("/unprotected/help").setViewName("help"); 33 | 34 | } 35 | } 36 | 37 | @Configuration 38 | public static class MyServiceProviderConfig extends WebSecurityConfigurerAdapter { 39 | 40 | public MyServiceProviderConfig() { 41 | super(false); 42 | } 43 | 44 | @Bean 45 | SAMLConfigurerBean saml() { 46 | return new SAMLConfigurerBean(); 47 | } 48 | 49 | @Override 50 | public void configure(WebSecurity web) throws Exception { 51 | super.configure(web); 52 | } 53 | 54 | @Bean 55 | public AuthenticationManager authenticationManagerBean() throws Exception { 56 | return super.authenticationManagerBean(); 57 | } 58 | 59 | @Override 60 | protected void configure(HttpSecurity http) throws Exception { 61 | // @formatter:off 62 | http.authorizeRequests() 63 | .antMatchers("/unprotected/**") 64 | .permitAll() 65 | .and() 66 | .httpBasic() 67 | .disable() 68 | .csrf() 69 | .disable() 70 | .anonymous() 71 | .and() 72 | .apply(saml()) 73 | .serviceProvider() 74 | .metadataGenerator() 75 | .entityId("localhost-demo") 76 | .bindingsSSO("artifact", "post", "paos") 77 | .and() 78 | .ecpProfile() 79 | .and() 80 | .sso() 81 | .defaultSuccessURL("/home") 82 | .idpSelectionPageURL("/idpselection") 83 | .and() 84 | .metadataManager() 85 | .metadataLocations("classpath:/idp-okta.xml") 86 | .refreshCheckInterval(0) 87 | .and() 88 | .extendedMetadata() 89 | .ecpEnabled(true) 90 | .idpDiscoveryEnabled(true)//set to false for no IDP Selection page. 91 | .and() 92 | .keyManager() 93 | .privateKeyDERLocation("classpath:/localhost.key.der") 94 | .publicKeyPEMLocation("classpath:/localhost.cert") 95 | .and() 96 | .http() 97 | .authorizeRequests() 98 | .requestMatchers(saml().endpointsMatcher()).permitAll() 99 | .and() 100 | .authorizeRequests() 101 | .anyRequest() 102 | .authenticated(); 103 | // @formatter:on 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/java/com/github/ulisesbocchio/demo/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.SAMLUser; 8 | import com.github.ulisesbocchio.spring.boot.security.saml.user.SAMLUserDetails; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | @Controller 14 | public class HomeController { 15 | 16 | @RequestMapping("/home") 17 | public ModelAndView home(@SAMLUser SAMLUserDetails user) { 18 | ModelAndView homeView = new ModelAndView("home"); 19 | homeView.addObject("userId", user.getUsername()); 20 | homeView.addObject("samlAttributes", user.getAttributes()); 21 | return homeView; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/java/com/github/ulisesbocchio/demo/controller/IdPSelectionController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.authentication.AuthenticationServiceException; 9 | import org.springframework.security.saml.SAMLConstants; 10 | import org.springframework.security.saml.SAMLDiscovery; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.servlet.ModelAndView; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import java.util.Collections; 17 | 18 | @Controller 19 | @RequestMapping("/idpselection") 20 | @Slf4j 21 | public class IdPSelectionController { 22 | 23 | @RequestMapping 24 | public ModelAndView idpSelection(HttpServletRequest request) { 25 | 26 | if (comesFromDiscoveryFilter(request)) { 27 | ModelAndView idpSelection = new ModelAndView("idpselection"); 28 | idpSelection.addObject(SAMLDiscovery.RETURN_URL, request.getAttribute(SAMLDiscovery.RETURN_URL)); 29 | idpSelection.addObject(SAMLDiscovery.RETURN_PARAM, request.getAttribute(SAMLDiscovery.RETURN_PARAM)); 30 | idpSelection.addObject("idpNameAliasMap", Collections.singletonMap("http://www.okta.com/exk62w7tqv0xkRl9p0h7", "Okta")); 31 | return idpSelection; 32 | } 33 | throw new AuthenticationServiceException("SP Discovery flow not detected"); 34 | } 35 | 36 | private boolean comesFromDiscoveryFilter(HttpServletRequest request) { 37 | return request.getAttribute(SAMLConstants.LOCAL_ENTITY_ID) != null && 38 | request.getAttribute(SAMLDiscovery.RETURN_URL) != null && 39 | request.getAttribute(SAMLDiscovery.RETURN_PARAM) != null; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | security.user.name=user 2 | security.user.password=password 3 | logging.level.org.springframework.security.saml= DEBUG -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/idp-okta.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 9 | MIIDpDCCAoygAwIBAgIGAVO669oLMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG 10 | A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU 11 | MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi04MzkyMjgxHDAaBgkqhkiG9w0BCQEW 12 | DWluZm9Ab2t0YS5jb20wHhcNMTYwMzI4MDE1MTEyWhcNMjYwMzI4MDE1MjEyWjCBkjELMAkGA1UE 13 | BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNV 14 | BAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtODM5MjI4MRwwGgYJ 15 | KoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 16 | 0H9hcvueaxQsH+GjDBPJdQ3FotGgPFOyFuZFvDwBeXiTMPAMoB8s+9Ey7ugYoAvLJMm7ryXAhOGa 17 | tblP4BcxPWrFJx+Tddswkb9pmM9rbmfrBBW3gsiwPQ/bEuwnvNxICIaeWD7h50Qej8UgrSunqmEq 18 | pBYi530/mWy7fdyRWniC0NtqlGDc+7jM4itchIjxuJXm0MX8BTzUkk8yU/Ul/YwNCwTAZNwispES 19 | ADsU9Mc+qcI6Fc68NC8pzPTpV4XEIiDwK8bfdQa1kwM3teL+1cHTXkEMvfhzBLZLedaB7b2Ictp+ 20 | /mPtX/m9+zu/oqeZs1ZfCPfOpaNQCw4ug/G7PQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAxlYaA 21 | PPB8kvNZgLX1V/WGxfpQTZMVLJGCfVA50I7wzRn+bDgkLhl2L3Rn7V7epQ7yOGYoIZ2QZGqu8fto 22 | xyXLmbx+gKvrejPp8QGCDl4Ga9UppIRtvdnLpXKeBw1m2GbLbgIlMmCbSGo05YSxBM7m6C7ZBDbA 23 | Sn8kNrM+77jWPs+uRO/Oe9UlMGIMIvxaUyy7H9TpUNHAMQKwYPiua/32T53iv9TZ6YYgdK1b2haA 24 | N3ESCsNEmU5BRZBQgBMRiw1qfWt5tGpAxjCKkVFEwR6gQwqH5QhAnzA9lyVAq8FGr7HDxMyLoObB 25 | avSvuMAJ1fZFZh4v3XJussihq2MjHH3g 26 | 27 | 28 | 29 | 30 | 32 | 34 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress 35 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified 36 | 38 | 40 | 41 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/localhost.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQx 4 | EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7UFATYOYQZzIxsD9AtnXPh67uVkZTI 6 | oK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf75tKbem3pON2NlYW 7 | wIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup/cSL 8 | W4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+ 9 | e81R+u2UbNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHD 10 | jtf6gwwbdg3g9GvyqIJnRqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs3 11 | 5gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaAFMNtl5fAchs35gZS4EF8/0C7QfBQMAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADVL8LgYGlmaHlyrKyKfsQF 13 | TVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLbLbRNPXS+ 14 | qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1Bc 15 | oLRzMeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpS 16 | bbSR6XNgsPA0XLWlleuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB 17 | 9H10x+zy1nFWvqoa+K66EA4u7DpEoHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/localhost.key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-okta2/src/main/resources/localhost.key.der -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/templates/help.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Help Page 6 | 7 | 8 |

Help Page

9 |

10 | This is an UNPROTECTED Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Home Page 6 | 7 | 8 |

This is the Home Page

9 | 10 |

Current User: unknown

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
SAML Attributes
Attribute NameAttribute Value
keyvalue
26 |

27 | Idp Single Logout - Local Logout 28 |

29 | 30 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/templates/idpselection.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | IdP Selection 6 | 7 | 8 | Select an IdP: 9 |
10 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sample SAML Spring Boot Application 6 | 7 | 8 |

Hi, Click here to start the Single Sign On process

9 | 10 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/main/resources/templates/protected.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Protected Resource 6 | 7 | 8 |

Protected Resource

9 |

10 | This is a Protected Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-okta2/src/test/java/com/github/ulisesbocchio/demo/SpringBootSecuritySamlDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | import org.springframework.test.context.web.WebAppConfiguration; 8 | 9 | @RunWith(SpringJUnit4ClassRunner.class) 10 | @SpringBootTest(classes = OktaSSODemoApplication2.class) 11 | @WebAppConfiguration 12 | public class SpringBootSecuritySamlDemoApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | spring-boot-security-saml-demo-props 6 | jar 7 | 8 | Spring Boot Security SAML Demo wiht Properties 9 | Demo project for Spring Boot 10 | 11 | 12 | com.github.ulisesbocchio 13 | spring-boot-security-saml-samples-parent 14 | 1.3-SNAPSHOT 15 | 16 | 17 | 18 | UTF-8 19 | 1.8 20 | com.github.ulisesbocchio.demo.SpringBootSecuritySAMLDemoApplication 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | 1.16.6 28 | 29 | 30 | com.github.ulisesbocchio 31 | spring-boot-security-saml 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-thymeleaf 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/java/com/github/ulisesbocchio/demo/SpringBootSecuritySAMLDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.EnableSAMLSSO; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | @SpringBootApplication 11 | @EnableSAMLSSO 12 | public class SpringBootSecuritySAMLDemoApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(SpringBootSecuritySAMLDemoApplication.class, args); 16 | } 17 | 18 | @Configuration 19 | public static class MvcConfig implements WebMvcConfigurer { 20 | 21 | @Override 22 | public void addViewControllers(ViewControllerRegistry registry) { 23 | registry.addViewController("/").setViewName("index"); 24 | registry.addViewController("/protected").setViewName("protected"); 25 | 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/java/com/github/ulisesbocchio/demo/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.SAMLUser; 8 | import com.github.ulisesbocchio.spring.boot.security.saml.user.SAMLUserDetails; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | @Controller 14 | public class HomeController { 15 | 16 | @RequestMapping("/home") 17 | public ModelAndView home(@SAMLUser SAMLUserDetails user) { 18 | ModelAndView homeView = new ModelAndView("home"); 19 | homeView.addObject("userId", user.getUsername()); 20 | homeView.addObject("samlAttributes", user.getAttributes()); 21 | return homeView; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/java/com/github/ulisesbocchio/demo/controller/IdPSelectionController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.authentication.AuthenticationServiceException; 9 | import org.springframework.security.saml.SAMLConstants; 10 | import org.springframework.security.saml.SAMLDiscovery; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.servlet.ModelAndView; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import java.util.Collections; 17 | 18 | @Controller 19 | @RequestMapping("/idpselection") 20 | @Slf4j 21 | public class IdPSelectionController { 22 | 23 | @RequestMapping 24 | public ModelAndView idpSelection(HttpServletRequest request) { 25 | 26 | if (comesFromDiscoveryFilter(request)) { 27 | ModelAndView idpSelection = new ModelAndView("idpselection"); 28 | idpSelection.addObject(SAMLDiscovery.RETURN_URL, request.getAttribute(SAMLDiscovery.RETURN_URL)); 29 | idpSelection.addObject(SAMLDiscovery.RETURN_PARAM, request.getAttribute(SAMLDiscovery.RETURN_PARAM)); 30 | idpSelection.addObject("idpNameAliasMap", Collections.singletonMap("http://idp.ssocircle.com", "SSO Circle")); 31 | return idpSelection; 32 | } 33 | throw new AuthenticationServiceException("SP Discovery flow not detected"); 34 | } 35 | 36 | private boolean comesFromDiscoveryFilter(HttpServletRequest request) { 37 | return request.getAttribute(SAMLConstants.LOCAL_ENTITY_ID) != null && 38 | request.getAttribute(SAMLDiscovery.RETURN_URL) != null && 39 | request.getAttribute(SAMLDiscovery.RETURN_PARAM) != null; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | security.user.name=user 2 | security.user.password=password 3 | logging.level.org.springframework.security.saml= DEBUG 4 | 5 | saml.sso.metadata-generator.entity-id=localhost-demo 6 | saml.sso.default-success-url=/home 7 | saml.sso.idp-selection-page-url=/idpselection 8 | saml.sso.logout.default-target-url=/ 9 | saml.sso.idp.metadata-location=classpath:/idp-ssocircle.xml 10 | saml.sso.metadata-manager.refresh-check-interval=0 11 | saml.sso.extended-metadata.idp-discovery-enabled=true 12 | saml.sso.key-manager.private-key-der-location=classpath:/localhost.key.der 13 | saml.sso.key-manager.public-key-pem-location=classpath:/localhost.cert 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/resources/localhost.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQx 4 | EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7UFATYOYQZzIxsD9AtnXPh67uVkZTI 6 | oK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf75tKbem3pON2NlYW 7 | wIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup/cSL 8 | W4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+ 9 | e81R+u2UbNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHD 10 | jtf6gwwbdg3g9GvyqIJnRqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs3 11 | 5gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaAFMNtl5fAchs35gZS4EF8/0C7QfBQMAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADVL8LgYGlmaHlyrKyKfsQF 13 | TVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLbLbRNPXS+ 14 | qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1Bc 15 | oLRzMeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpS 16 | bbSR6XNgsPA0XLWlleuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB 17 | 9H10x+zy1nFWvqoa+K66EA4u7DpEoHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/resources/localhost.key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-props/src/main/resources/localhost.key.der -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Home Page 6 | 7 | 8 |

This is the Home Page

9 | 10 |

Current User: unknown

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
SAML Attributes
Attribute NameAttribute Value
keyvalue
26 |

27 | Idp Single Logout - Local Logout 28 |

29 | 30 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/resources/templates/idpselection.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | IdP Selection 6 | 7 | 8 | Select an IdP: 9 |
10 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sample SAML Spring Boot Application 6 | 7 | 8 |

Hi, Click here to start the Single Sign On process

9 | 10 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/main/resources/templates/protected.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Protected Resource 6 | 7 | 8 |

Protected Resource

9 |

10 | This is a Protected Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-props/src/test/java/com/github/ulisesbocchio/demo/SpringBootSecuritySamlDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | import org.springframework.test.context.web.WebAppConfiguration; 8 | 9 | @RunWith(SpringJUnit4ClassRunner.class) 10 | @SpringBootTest(classes = SpringBootSecuritySAMLDemoApplication.class) 11 | @WebAppConfiguration 12 | public class SpringBootSecuritySamlDemoApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | spring-boot-security-saml-demo-static-metadata 6 | jar 7 | 8 | Spring Boot Security SAML Demo with static metadata 9 | Demo project for Spring Boot 10 | 11 | 12 | com.github.ulisesbocchio 13 | spring-boot-security-saml-samples-parent 14 | 1.3-SNAPSHOT 15 | 16 | 17 | 18 | UTF-8 19 | 1.8 20 | com.github.ulisesbocchio.demo.SpringBootSecuritySAMLDemoApplication 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | 1.16.6 28 | 29 | 30 | com.github.ulisesbocchio 31 | spring-boot-security-saml 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-thymeleaf 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/java/com/github/ulisesbocchio/demo/SpringBootSecuritySAMLDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.EnableSAMLSSO; 4 | import com.github.ulisesbocchio.spring.boot.security.saml.configurer.ServiceProviderBuilder; 5 | import com.github.ulisesbocchio.spring.boot.security.saml.configurer.ServiceProviderConfigurerAdapter; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 10 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 11 | 12 | @SpringBootApplication 13 | @EnableSAMLSSO 14 | public class SpringBootSecuritySAMLDemoApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(SpringBootSecuritySAMLDemoApplication.class, args); 18 | } 19 | 20 | @Configuration 21 | public static class MvcConfig implements WebMvcConfigurer { 22 | 23 | @Override 24 | public void addViewControllers(ViewControllerRegistry registry) { 25 | registry.addViewController("/").setViewName("index"); 26 | registry.addViewController("/protected").setViewName("protected"); 27 | 28 | } 29 | } 30 | 31 | @Configuration 32 | public static class MyServiceProviderConfig extends ServiceProviderConfigurerAdapter { 33 | @Override 34 | public void configure(ServiceProviderBuilder serviceProvider) throws Exception { 35 | // @formatter:off 36 | serviceProvider 37 | .metadataGenerator() 38 | .entityId("localhost-demo") 39 | .and() 40 | .sso() 41 | .defaultSuccessURL("/home") 42 | .idpSelectionPageURL("/idpselection") 43 | .and() 44 | .logout() 45 | .defaultTargetURL("/") 46 | .and() 47 | .metadataManager() 48 | .metadataLocations("classpath:/idp-ssocircle.xml") 49 | .localMetadataLocation("classpath:/sp-ssocircle.xml") 50 | .refreshCheckInterval(0) 51 | .and() 52 | .extendedMetadata() 53 | .idpDiscoveryEnabled(true) 54 | .and() 55 | .localExtendedMetadata() 56 | .securityProfile("metaiop") 57 | .sslSecurityProfile("pkix") 58 | .signMetadata(true) 59 | .signingKey("localhost") 60 | .encryptionKey("localhost") 61 | .requireArtifactResolveSigned(false) 62 | .requireLogoutRequestSigned(false) 63 | .idpDiscoveryEnabled(true) 64 | .and() 65 | //This Keystore contains also the public key of idp.ssocircle.com 66 | .keyManager() 67 | .storeLocation("classpath:/localhost.jks") 68 | .storePass("foobar") 69 | .defaultKey("localhost") 70 | .keyPassword("localhost", "foobar"); 71 | // @formatter:on 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/java/com/github/ulisesbocchio/demo/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import com.github.ulisesbocchio.spring.boot.security.saml.annotation.SAMLUser; 8 | import com.github.ulisesbocchio.spring.boot.security.saml.user.SAMLUserDetails; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | @Controller 14 | public class HomeController { 15 | 16 | @RequestMapping("/home") 17 | public ModelAndView home(@SAMLUser SAMLUserDetails user) { 18 | ModelAndView homeView = new ModelAndView("home"); 19 | homeView.addObject("userId", user.getUsername()); 20 | homeView.addObject("samlAttributes", user.getAttributes()); 21 | return homeView; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/java/com/github/ulisesbocchio/demo/controller/IdPSelectionController.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo.controller; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.authentication.AuthenticationServiceException; 9 | import org.springframework.security.saml.SAMLConstants; 10 | import org.springframework.security.saml.SAMLDiscovery; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.servlet.ModelAndView; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import java.util.Collections; 17 | 18 | @Controller 19 | @RequestMapping("/idpselection") 20 | @Slf4j 21 | public class IdPSelectionController { 22 | 23 | @RequestMapping 24 | public ModelAndView idpSelection(HttpServletRequest request) { 25 | 26 | if (comesFromDiscoveryFilter(request)) { 27 | ModelAndView idpSelection = new ModelAndView("idpselection"); 28 | idpSelection.addObject(SAMLDiscovery.RETURN_URL, request.getAttribute(SAMLDiscovery.RETURN_URL)); 29 | idpSelection.addObject(SAMLDiscovery.RETURN_PARAM, request.getAttribute(SAMLDiscovery.RETURN_PARAM)); 30 | idpSelection.addObject("idpNameAliasMap", Collections.singletonMap("http://idp.ssocircle.com", "SSO Circle")); 31 | return idpSelection; 32 | } 33 | throw new AuthenticationServiceException("SP Discovery flow not detected"); 34 | } 35 | 36 | private boolean comesFromDiscoveryFilter(HttpServletRequest request) { 37 | return request.getAttribute(SAMLConstants.LOCAL_ENTITY_ID) != null && 38 | request.getAttribute(SAMLDiscovery.RETURN_URL) != null && 39 | request.getAttribute(SAMLDiscovery.RETURN_PARAM) != null; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | security.user.name=user 2 | security.user.password=password 3 | logging.level.org.springframework.security.saml= DEBUG -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/idp.ssocircle.com.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-static-metadata/src/main/resources/idp.ssocircle.com.cer -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/idp.ssocircle.com.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFBjCCA+6gAwIBAgISA9yR8yaG/Xf8oUS21yNFGZv3MA0GCSqGSIb3DQEBCwUA 3 | MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD 4 | ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNjEyMDUwODE0MDBaFw0x 5 | NzAzMDUwODE0MDBaMBwxGjAYBgNVBAMTEWlkcC5zc29jaXJjbGUuY29tMIIBIjAN 6 | BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+6ROg4GNOw90IX3Ufvy7SsFJNEif 7 | bF4Con/7K473obrQfhc2kc5HrWDXhdmxN+R9dtlnPjtoizGl2AscuZn1V16tPWWq 8 | HaaG4+BikzWFBxG3b4PibiQ/9+vHvO9colR72NdKR3ZELyWXmWUWqBmEcCnthCq4 9 | Z1P7JzVW94xZ/lfjH/YMJtf1zXAZXUSX3ZLRSpRC030CCJbuLmrF1PXeqI2f3tYF 10 | OQK6k+hnWf0OnZzbOBBsesn2PFDuY5dmwY7PUMF7yfdEifPDr69uC91Dt1YoxsmA 11 | 5t728ZDArhn+mT9eFbxzrKQxlFZe8/osj7WU+bye7xlJxw+NvyeQEJKpGwIDAQAB 12 | o4ICEjCCAg4wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr 13 | BgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSzxM1upXhdoqep9J74YGLP 14 | snt5STAfBgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBwBggrBgEFBQcB 15 | AQRkMGIwLwYIKwYBBQUHMAGGI2h0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlw 16 | dC5vcmcvMC8GCCsGAQUFBzAChiNodHRwOi8vY2VydC5pbnQteDMubGV0c2VuY3J5 17 | cHQub3JnLzAcBgNVHREEFTATghFpZHAuc3NvY2lyY2xlLmNvbTCB/gYDVR0gBIH2 18 | MIHzMAgGBmeBDAECATCB5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0 19 | dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMg 20 | Q2VydGlmaWNhdGUgbWF5IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQ 21 | YXJ0aWVzIGFuZCBvbmx5IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNh 22 | dGUgUG9saWN5IGZvdW5kIGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9z 23 | aXRvcnkvMA0GCSqGSIb3DQEBCwUAA4IBAQBZx+VeJpYirkWDAglodWLqpul7Rkbv 24 | RPLRTbLtZmaD3MULCtwf92TT1gpxRNFskiEWcAoN1Ooc4bAM3VRBoFJCGCaQtodh 25 | WGayQaIOhBDuCCqWi7jPx5wCt4rx3MuRznzDP3HUiuIt2ciD6jRrh66fV8Iwiu2L 26 | ivT6l1xYyu9GSwsWaIgoEgU/YAhRhkh5EEV6QVugLkEJ+LPOXLWykzR40ndSClRl 27 | 9PuZqIOf/boHpdlmNotcJpKQiEZ2iXinQyYuU9kUTR/NL8YtTELo/ijZfzfZAQ2L 28 | MeC3M2CbSVYLHzU6Ue7YdxitDNTFZs5BdGhrtzAb7PmcOfLEgIIK7AER 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/localhost.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQx 4 | EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7UFATYOYQZzIxsD9AtnXPh67uVkZTI 6 | oK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf75tKbem3pON2NlYW 7 | wIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup/cSL 8 | W4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+ 9 | e81R+u2UbNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHD 10 | jtf6gwwbdg3g9GvyqIJnRqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs3 11 | 5gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaAFMNtl5fAchs35gZS4EF8/0C7QfBQMAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADVL8LgYGlmaHlyrKyKfsQF 13 | TVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLbLbRNPXS+ 14 | qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1Bc 15 | oLRzMeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpS 16 | bbSR6XNgsPA0XLWlleuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB 17 | 9H10x+zy1nFWvqoa+K66EA4u7DpEoHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/localhost.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-static-metadata/src/main/resources/localhost.jks -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/localhost.key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-static-metadata/src/main/resources/localhost.key.der -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/localhost.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEA3U07cv/IIJv4xgWTKm8ldyOVC7JEbtQUBNg5hBnMjGwP0C2d 3 | c+Hru5WRlMigrs+zlfhrmpUBG1034YIVn8hNqGUCUjHyuZWxvP7tc9akY9/vm0pt 4 | 6bek43Y2VhbAgRCrK5VqVkcNQyAhc90YgBl416NW7uBgwsnCJIy0HS4Ezr2m3OCK 5 | Alxue6n9xItbh8GHhyTmSPRJWZfnySd9qLOtV/6CEbI0WFr1fL4OiKUKh/HAUilW 6 | yS/+FzNnkv57zVH67ZRs3NHB/yloXl91XBoc8Ys5hIEaNKbvVUN0mqW8qskIGgJA 7 | 4OG2Yk6YMcOO1/qDDBt2DeD0a/KogmdGoE73TwIDAQABAoIBAQDG0OH9+OnU0gt3 8 | 6/5A+0XPeTooHen5H7M0fwV9Nqhb56F1R+XS/D8Kcd8uqegh5RvUOjCB2if6a48O 9 | nA3NVOjfxo+FRLZqIKBjySuPDGD4EXF0NDP26zPJ3qQGR75+tXjyWPQFuyOhELa9 10 | Hv8p5rh4EpjBVvfXR+eRao9OP8+142Sedn5yKobQ6Qe9h4TIgBoCi1XCs86ySChr 11 | 7ITG3vEeB3Eq5hSbeN255m+VGjDySeeXsKHmnDHEq0ayLa8LbmD0XLmiLTrbV8IO 12 | Zy7qDxxnlIxjAmmbQj42orNNhDQwoGzy1wa8Yh5/3gwdxGXhufo7ItkkeRnCKCmh 13 | ThP0GSqBAoGBAPZNtNEHDxo5Getm4DbywTHYv+XBlWfLDkJSRjMSTCKzv9MemoX4 14 | vE5sx4ax8oLRcz4pQnfbXQeDePvvLyWApS6qhWbS9qf8oaIt2exPolqmCJibdGpM 15 | Y0Xk3ZFpUA7a+2jPK1PbrwLj/w7zNmFU8Rh/8RZS0QmBIcxovPH7kZ7vAoGBAOYD 16 | jXGVxcxsTdK8Ns6hltVPEE+XmWGfInCVfpAvECN+plwna1abdXafYnMXlmg/tC4q 17 | 2Ufkcw3PEtFKCAMQ1P0n8jSKXpjj1Lxlrunj2404eH93uHJih6zYE2gb/P+7jm49 18 | 377SQOObrueWZUy4mIIZmbT6464rq6sKP6tb1i2hAoGBAIQG31f0yrmpxiUTPjj2 19 | I21O3H6SKD488GXIqGyT8E/hvn+yte3+iSIY2VNwa6iIEZhOkZyh79opNV8GtWUK 20 | 8oBzU5Lsnt8pYpMGtPwhK8wfmBgFrH+Wdthud/6MTyfHZmCmPHl1FvkbsgsXgBzo 21 | ZVxWqKrotbi8iZuCwVWNHl/tAoGAEms2aGIV9Mi3cqifuuw1p98s7zK0lZyopVtT 22 | Rzh9kloR+E8vyT+pqFYbDBxXbwGq7AeCXr9sdy6d0ySaf6RZaexI+OwbpyKXZn6+ 23 | Avy8GBLtk0eC/aXmN3EWHMAhAlmCjlFmGWG80H0nBGSGuB4QGFr0dAmjMc9Nb+Ti 24 | NFamUAECgYEA7uPN2cpwvVlt4Q4BHxjvvo1XDRe5c+RwDVa/dYkLu85HVvRd42SJ 25 | QgIdcZR9kLRXuOFCWv1shFmfHPqfmH0q6hn39TgVnUyHxzBlAbP5Dx/n4FRs8EP8 26 | qqNS0ft5Mqoy1UuJL6N5iDYY+i8Is90bsC9mMPj007kfFcyJcRULrSA= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/localhost.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-boot-security-saml-demo-static-metadata/src/main/resources/localhost.p12 -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/sp-ssocircle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNVBAMMCWxvY2Fs 14 | aG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQxEjAQBgNVBAMMCWxvY2FsaG9z 15 | dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7U 16 | FATYOYQZzIxsD9AtnXPh67uVkZTIoK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf 17 | 75tKbem3pON2NlYWwIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup 18 | /cSLW4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+e81R+u2U 19 | bNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHDjtf6gwwbdg3g9GvyqIJn 20 | RqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs35gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaA 21 | FMNtl5fAchs35gZS4EF8/0C7QfBQMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADV 22 | L8LgYGlmaHlyrKyKfsQFTVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLb 23 | LbRNPXS+qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1BcoLRz 24 | MeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpSbbSR6XNgsPA0XLWl 25 | leuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB9H10x+zy1nFWvqoa+K66EA4u7DpE 26 | oHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNVBAMMCWxvY2Fs 35 | aG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQxEjAQBgNVBAMMCWxvY2FsaG9z 36 | dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7U 37 | FATYOYQZzIxsD9AtnXPh67uVkZTIoK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf 38 | 75tKbem3pON2NlYWwIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup 39 | /cSLW4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+e81R+u2U 40 | bNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHDjtf6gwwbdg3g9GvyqIJn 41 | RqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs35gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaA 42 | FMNtl5fAchs35gZS4EF8/0C7QfBQMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADV 43 | L8LgYGlmaHlyrKyKfsQFTVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLb 44 | LbRNPXS+qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1BcoLRz 45 | MeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpSbbSR6XNgsPA0XLWl 46 | leuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB9H10x+zy1nFWvqoa+K66EA4u7DpE 47 | oHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 48 | 49 | 50 | 51 | 52 | 54 | 56 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress 57 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient 58 | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent 59 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified 60 | urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName 61 | 63 | 65 | 67 | 68 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Home Page 6 | 7 | 8 |

This is the Home Page

9 | 10 |

Current User: unknown

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
SAML Attributes
Attribute NameAttribute Value
keyvalue
26 |

27 | Idp Single Logout - Local Logout 28 |

29 | 30 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/templates/idpselection.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | IdP Selection 6 | 7 | 8 | Select an IdP: 9 |
10 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sample SAML Spring Boot Application 6 | 7 | 8 |

Hi, Click here to start the Single Sign On process

9 | 10 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/main/resources/templates/protected.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Protected Resource 6 | 7 | 8 |

Protected Resource

9 |

10 | This is a Protected Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-security-saml-demo-static-metadata/src/test/java/com/github/ulisesbocchio/demo/SpringBootSecuritySamlDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.ulisesbocchio.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | import org.springframework.test.context.web.WebAppConfiguration; 8 | 9 | @RunWith(SpringJUnit4ClassRunner.class) 10 | @SpringBootTest(classes = SpringBootSecuritySAMLDemoApplication.class) 11 | @WebAppConfiguration 12 | public class SpringBootSecuritySamlDemoApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /spring-security-saml-sample/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip -------------------------------------------------------------------------------- /spring-security-saml-sample/README.md: -------------------------------------------------------------------------------- 1 | ## Spring Security SAML Sample with Spring Boot ## 2 | This sample uses the plain old spring-security-saml library to add SP capabilities to a Spring Boot app, allowing it to authenticate against different IdPs. 3 | The main purpose of this module is to expose the extensive configuration required to use Spring Security SAML, in comparison with the `spring-boot-security-saml` plugin for Spring Boot, that deals with all this complexities internally. 4 | 5 | ### Availabe IdPs #### 6 | 7 | - [SSO Circle](http://www.ssocircle.com/en/) 8 | - [OneLogin](https://www.onelogin.com/) 9 | - [Ping One Clound] (https://www.pingidentity.com/en/products/pingone.html) 10 | - [OKTA](https://www.okta.com) 11 | 12 | ### Credentials ### 13 | 14 | Use the following credentials: 15 | 16 | - *SSO Circle:* Register with [SSO Circle] (http://www.ssocircle.com/en/) and use those credentials to login in the application. 17 | - *OneLogin:* The user must be created in your OneLogin account. See below. 18 | - *Ping One:* user: dough1234321@gmail.com pass: Test1234! 19 | - *OKTA:* user: dough1234321@gmail.com pass: Test1234! 20 | 21 | ### OneLogin configuration ### 22 | 23 | To use OneLogin with this sample application, you'll have to: 24 | - Create an [OneLogin developers account](https://www.onelogin.com/developer-signup) 25 | - Add a SAML Test Connector (IdP) 26 | - Configure the OneLogin application with: 27 | - *RelayState:* You can use anything here. 28 | - *Audience:* localhost-demo 29 | - *Recipient:* http://localhost:8080/saml/SSO 30 | - *ACS (Consumer) URL Validator:* ^http://localhost:8080/saml/SSO.*$ 31 | - *ACS (Consumer) URL:* http://localhost:8080/saml/SSO 32 | - *Single Logout URL:* http://localhost:8080/saml/SingleLogout 33 | - *Parameters:* You can add additional parameters like firstName, lastName. 34 | - In the SSO tab: 35 | - *X.509 Certificate:* Copy-paste the existing X.509 PEM cerficate into idp-onelogin.xml (ds:X509Certificate). 36 | - *SAML Signature algorythm:* Use the SHA-256, although SHA-1 will still work. 37 | - *Issuer URL:* Replace the entityID in the idp-onelogin.xml with this value. 38 | - *SAML 2.0 Endpoint (HTTP):* Replace the location for the HTTP-Redirect and HTTP-POST binding in the idp-onelogin.xml with this value. 39 | - *SLO Endpoint (HTTP):* Replace the location for the HTTP-Redirect binding in the idp-onelogin.xml with this value. 40 | -------------------------------------------------------------------------------- /spring-security-saml-sample/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% -------------------------------------------------------------------------------- /spring-security-saml-sample/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | spring-security-saml-sample 6 | jar 7 | 8 | Spring Security SAML Sample 9 | Demo project for Spring Boot 10 | 11 | 12 | com.github.ulisesbocchio 13 | spring-boot-security-saml-samples-parent 14 | 1.3-SNAPSHOT 15 | 16 | 17 | 18 | 1.8 19 | com.ulisesbocchio.security.saml.SamlServiceProviderApplication 20 | 21 | 22 | 23 | 24 | ch.qos.logback 25 | logback-access 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-thymeleaf 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-security 38 | 39 | 40 | org.springframework.security.extensions 41 | spring-security-saml2-core 42 | 1.0.9.RELEASE 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-actuator 47 | 48 | 49 | com.google.guava 50 | guava 51 | 27.1-jre 52 | 53 | 54 | org.projectlombok 55 | lombok 56 | provided 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-test 61 | test 62 | 63 | 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-maven-plugin 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/SamlServiceProviderApplication.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author Ulises Bocchio 8 | */ 9 | @SpringBootApplication 10 | public class SamlServiceProviderApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(SamlServiceProviderApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/certificate/KeystoreFactory.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.certificate; 2 | 3 | import lombok.SneakyThrows; 4 | import org.springframework.core.io.DefaultResourceLoader; 5 | import org.springframework.core.io.Resource; 6 | import org.springframework.core.io.ResourceLoader; 7 | import org.springframework.util.StreamUtils; 8 | 9 | import java.security.KeyFactory; 10 | import java.security.KeyStore; 11 | import java.security.cert.Certificate; 12 | import java.security.cert.CertificateFactory; 13 | import java.security.cert.X509Certificate; 14 | import java.security.interfaces.RSAPrivateKey; 15 | import java.security.spec.PKCS8EncodedKeySpec; 16 | 17 | /** 18 | * @author Ulises Bocchio 19 | */ 20 | public class KeystoreFactory { 21 | 22 | private ResourceLoader resourceLoader; 23 | 24 | public KeystoreFactory() { 25 | resourceLoader = new DefaultResourceLoader(); 26 | } 27 | 28 | public KeystoreFactory(ResourceLoader resourceLoader) { 29 | this.resourceLoader = resourceLoader; 30 | } 31 | 32 | @SneakyThrows 33 | public KeyStore loadKeystore(String certResourceLocation, String privateKeyResourceLocation, String alias, String keyPassword) { 34 | KeyStore keystore = createEmptyKeystore(); 35 | X509Certificate cert = loadCert(certResourceLocation); 36 | RSAPrivateKey privateKey = loadPrivateKey(privateKeyResourceLocation); 37 | addKeyToKeystore(keystore, cert, privateKey, alias, keyPassword); 38 | return keystore; 39 | } 40 | 41 | @SneakyThrows 42 | public void addKeyToKeystore(KeyStore keyStore, X509Certificate cert, RSAPrivateKey privateKey, String alias, String password) { 43 | KeyStore.PasswordProtection pass = new KeyStore.PasswordProtection(password.toCharArray()); 44 | Certificate[] certificateChain = {cert}; 45 | keyStore.setEntry(alias, new KeyStore.PrivateKeyEntry(privateKey, certificateChain), pass); 46 | } 47 | 48 | @SneakyThrows 49 | public KeyStore createEmptyKeystore() { 50 | KeyStore keyStore = KeyStore.getInstance("JKS"); 51 | keyStore.load(null, "".toCharArray()); 52 | return keyStore; 53 | } 54 | 55 | @SneakyThrows 56 | public X509Certificate loadCert(String certLocation) { 57 | CertificateFactory cf = CertificateFactory.getInstance("X509"); 58 | Resource certRes = resourceLoader.getResource(certLocation); 59 | X509Certificate cert = (X509Certificate) cf.generateCertificate(certRes.getInputStream()); 60 | return cert; 61 | } 62 | 63 | @SneakyThrows 64 | public RSAPrivateKey loadPrivateKey(String privateKeyLocation) { 65 | Resource keyRes = resourceLoader.getResource(privateKeyLocation); 66 | byte[] keyBytes = StreamUtils.copyToByteArray(keyRes.getInputStream()); 67 | PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(keyBytes); 68 | KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 69 | RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec); 70 | return privateKey; 71 | } 72 | 73 | public void setResourceLoader(DefaultResourceLoader resourceLoader) { 74 | this.resourceLoader = resourceLoader; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/config/FilterCleanupConfig.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.config; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.springframework.beans.BeansException; 5 | import org.springframework.beans.factory.config.BeanDefinition; 6 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 7 | import org.springframework.beans.factory.support.BeanDefinitionBuilder; 8 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 9 | import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; 10 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 11 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 12 | import org.springframework.boot.web.servlet.ServletRegistrationBean; 13 | import org.springframework.context.annotation.Bean; 14 | import org.springframework.context.annotation.Configuration; 15 | 16 | import java.util.Arrays; 17 | import java.util.Set; 18 | 19 | /** 20 | * @author Ulises Bocchio 21 | */ 22 | @Configuration 23 | public class FilterCleanupConfig { 24 | @Bean 25 | public static BeanDefinitionRegistryPostProcessor removeUnwantedAutomaticFilterRegistration() { 26 | return new BeanDefinitionRegistryPostProcessor() { 27 | @Override 28 | public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { 29 | } 30 | 31 | @Override 32 | public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException { 33 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) bf; 34 | Set filtersToDisable = ImmutableSet.of("samlEntryPoint", "samlFilter", "samlIDPDiscovery", "metadataDisplayFilter", 35 | "samlWebSSOHoKProcessingFilter", "samlWebSSOProcessingFilter", 36 | "samlLogoutProcessingFilter", "samlLogoutFilter", "metadataGeneratorFilter"); 37 | Arrays.stream(beanFactory.getBeanNamesForType(javax.servlet.Filter.class)) 38 | .filter(filtersToDisable::contains) 39 | .forEach(name -> { 40 | BeanDefinition definition = BeanDefinitionBuilder 41 | .genericBeanDefinition(FilterRegistrationBean.class) 42 | .setScope(BeanDefinition.SCOPE_SINGLETON) 43 | .addConstructorArgReference(name) 44 | .addConstructorArgValue(new ServletRegistrationBean[]{}) 45 | .addPropertyValue("enabled", false) 46 | .getBeanDefinition(); 47 | beanFactory.registerBeanDefinition(name + "FilterRegistrationBean", definition); 48 | }); 49 | } 50 | }; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/config/MvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | /** 8 | * @author Ulises Bocchio 9 | */ 10 | @Configuration 11 | public class MvcConfig implements WebMvcConfigurer { 12 | 13 | @Override 14 | public void addViewControllers(ViewControllerRegistry registry) { 15 | registry.addViewController("/").setViewName("index"); 16 | registry.addViewController("/protected").setViewName("protected"); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/config/SAMLConfigDefaults.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.config; 2 | 3 | import org.opensaml.saml2.metadata.provider.MetadataProvider; 4 | import org.opensaml.saml2.metadata.provider.MetadataProviderException; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.security.saml.SAMLBootstrap; 8 | import org.springframework.security.saml.context.SAMLContextProviderImpl; 9 | import org.springframework.security.saml.log.SAMLDefaultLogger; 10 | import org.springframework.security.saml.metadata.CachingMetadataManager; 11 | import org.springframework.security.saml.parser.ParserPoolHolder; 12 | import org.springframework.security.saml.websso.*; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * @author Ulises Bocchio 18 | */ 19 | @Configuration 20 | public class SAMLConfigDefaults { 21 | @Bean 22 | public static SAMLBootstrap sAMLBootstrap() { 23 | return new SAMLBootstrap(); 24 | } 25 | 26 | @Bean 27 | public ParserPoolHolder parserPoolHolder() { 28 | return new ParserPoolHolder(); 29 | } 30 | 31 | @Bean 32 | public SAMLContextProviderImpl contextProvider() { 33 | return new SAMLContextProviderImpl(); 34 | } 35 | 36 | @Bean 37 | public SAMLDefaultLogger samlLogger() { 38 | return new SAMLDefaultLogger(); 39 | } 40 | 41 | @Bean 42 | public WebSSOProfileConsumer webSSOprofileConsumer() { 43 | return new WebSSOProfileConsumerImpl(); 44 | } 45 | 46 | @Bean 47 | public WebSSOProfileConsumerHoKImpl hokWebSSOprofileConsumer() { 48 | return new WebSSOProfileConsumerHoKImpl(); 49 | } 50 | 51 | @Bean 52 | public WebSSOProfile webSSOprofile() { 53 | return new WebSSOProfileImpl(); 54 | } 55 | 56 | @Bean 57 | public WebSSOProfileECPImpl ecpProfile() { 58 | return new WebSSOProfileECPImpl(); 59 | } 60 | 61 | @Bean 62 | public WebSSOProfileHoKImpl hokWebSSOProfile() { 63 | return new WebSSOProfileHoKImpl(); 64 | } 65 | 66 | @Bean 67 | public SingleLogoutProfile logoutProfile() { 68 | return new SingleLogoutProfileImpl(); 69 | } 70 | 71 | @Bean 72 | public CachingMetadataManager metadataManager(List metadataProviders) throws MetadataProviderException { 73 | return new CachingMetadataManager(metadataProviders); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.authentication.AuthenticationManager; 6 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.saml.*; 12 | import org.springframework.security.saml.metadata.MetadataDisplayFilter; 13 | import org.springframework.security.saml.metadata.MetadataGeneratorFilter; 14 | import org.springframework.security.web.authentication.logout.LogoutFilter; 15 | import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; 16 | import org.springframework.security.web.context.HttpSessionSecurityContextRepository; 17 | 18 | /** 19 | * @author Ulises Bocchio 20 | */ 21 | @Configuration 22 | @EnableWebSecurity 23 | @EnableGlobalMethodSecurity(securedEnabled = true) 24 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 25 | 26 | @Autowired 27 | private SAMLLogoutFilter samlLogoutFilter; 28 | 29 | @Autowired 30 | private SAMLLogoutProcessingFilter samlLogoutProcessingFilter; 31 | 32 | @Autowired 33 | private MetadataDisplayFilter metadataDisplayFilter; 34 | 35 | @Autowired 36 | private MetadataGeneratorFilter metadataGeneratorFilter; 37 | 38 | @Autowired 39 | private SAMLProcessingFilter samlWebSSOProcessingFilter; 40 | 41 | @Autowired 42 | private SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter; 43 | 44 | @Autowired 45 | private SAMLEntryPoint samlEntryPoint; 46 | 47 | @Autowired 48 | private SAMLDiscovery samlIDPDiscovery; 49 | 50 | @Autowired 51 | private AuthenticationManager authenticationManager; 52 | 53 | 54 | @Override 55 | public void init(WebSecurity web) throws Exception { 56 | super.init(web); 57 | } 58 | 59 | 60 | /** 61 | * Defines the web based security configuration. 62 | * 63 | * @param http It allows configuring web based security for specific http requests. 64 | */ 65 | @Override 66 | protected void configure(HttpSecurity http) throws Exception { 67 | HttpSessionSecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository(); 68 | securityContextRepository.setSpringSecurityContextKey("SPRING_SECURITY_CONTEXT_SAML"); 69 | http 70 | .securityContext() 71 | .securityContextRepository(securityContextRepository); 72 | http 73 | .httpBasic() 74 | .disable(); 75 | http 76 | .csrf() 77 | .disable(); 78 | http 79 | .addFilterAfter(metadataGeneratorFilter, BasicAuthenticationFilter.class) 80 | .addFilterAfter(metadataDisplayFilter, MetadataGeneratorFilter.class) 81 | .addFilterAfter(samlEntryPoint, MetadataDisplayFilter.class) 82 | .addFilterAfter(samlWebSSOProcessingFilter, SAMLEntryPoint.class) 83 | .addFilterAfter(samlWebSSOHoKProcessingFilter, SAMLProcessingFilter.class) 84 | .addFilterAfter(samlLogoutProcessingFilter, SAMLWebSSOHoKProcessingFilter.class) 85 | .addFilterAfter(samlIDPDiscovery, SAMLLogoutProcessingFilter.class) 86 | .addFilterAfter(samlLogoutFilter, LogoutFilter.class); 87 | http 88 | .authorizeRequests() 89 | .antMatchers("/", "/error", "/saml/**", "/idpselection").permitAll() 90 | .anyRequest().authenticated(); 91 | http 92 | .exceptionHandling() 93 | .authenticationEntryPoint(samlEntryPoint); 94 | http 95 | .logout() 96 | .disable(); 97 | } 98 | 99 | @Override 100 | protected AuthenticationManager authenticationManager() throws Exception { 101 | return authenticationManager; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/spring/SpringResourceWrapperOpenSAMLResource.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.spring; 2 | 3 | import lombok.SneakyThrows; 4 | import org.joda.time.DateTime; 5 | import org.opensaml.util.resource.ResourceException; 6 | import org.springframework.core.io.Resource; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | 11 | /** 12 | * @author Ulises Bocchio 13 | */ 14 | public class SpringResourceWrapperOpenSAMLResource implements org.opensaml.util.resource.Resource { 15 | 16 | private Resource springDelegate; 17 | 18 | public SpringResourceWrapperOpenSAMLResource(Resource springDelegate) throws ResourceException { 19 | this.springDelegate = springDelegate; 20 | exists(); 21 | } 22 | 23 | @Override 24 | @SneakyThrows 25 | public String getLocation() { 26 | return springDelegate.getURL().toString(); 27 | } 28 | 29 | @Override 30 | public boolean exists() throws ResourceException { 31 | return springDelegate.exists(); 32 | } 33 | 34 | @Override 35 | public InputStream getInputStream() throws ResourceException { 36 | try { 37 | return springDelegate.getInputStream(); 38 | } catch (IOException e) { 39 | throw new ResourceException(e); 40 | } 41 | } 42 | 43 | @Override 44 | public DateTime getLastModifiedTime() throws ResourceException { 45 | try { 46 | return new DateTime(springDelegate.lastModified()); 47 | } catch (IOException e) { 48 | throw new ResourceException(e); 49 | } 50 | } 51 | 52 | public int hashCode() { 53 | return getLocation().hashCode(); 54 | } 55 | 56 | public boolean equals(Object o) { 57 | if (o == this) { 58 | return true; 59 | } 60 | 61 | if (o instanceof SpringResourceWrapperOpenSAMLResource) { 62 | return getLocation().equals(((SpringResourceWrapperOpenSAMLResource) o).getLocation()); 63 | } 64 | 65 | return false; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/spring/mvc/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.spring.mvc; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import com.ulisesbocchio.security.saml.spring.security.SAMLUserDetails; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.servlet.ModelAndView; 11 | 12 | @Controller 13 | public class HomeController { 14 | 15 | @RequestMapping("/home") 16 | public ModelAndView home(@SAMLUser SAMLUserDetails user) { 17 | ModelAndView homeView = new ModelAndView("home"); 18 | homeView.addObject("userId", user.getUsername()); 19 | homeView.addObject("samlAttributes", user.getAttributes()); 20 | return homeView; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/spring/mvc/IdPSelectionController.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.spring.mvc; 2 | 3 | /** 4 | * @author Ulises Bocchio 5 | */ 6 | 7 | import lombok.SneakyThrows; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.authentication.AuthenticationServiceException; 11 | import org.springframework.security.saml.SAMLConstants; 12 | import org.springframework.security.saml.SAMLDiscovery; 13 | import org.springframework.security.saml.metadata.MetadataManager; 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.servlet.ModelAndView; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | import java.util.Map; 20 | 21 | import static java.util.function.Function.identity; 22 | import static java.util.stream.Collectors.toMap; 23 | 24 | @Controller 25 | @RequestMapping("/idpselection") 26 | @Slf4j 27 | public class IdPSelectionController { 28 | 29 | @Autowired 30 | private MetadataManager metadataManager; 31 | 32 | @RequestMapping 33 | public ModelAndView idpSelection(HttpServletRequest request) { 34 | 35 | if (comesFromDiscoveryFilter(request)) { 36 | ModelAndView idpSelection = new ModelAndView("idpselection"); 37 | idpSelection.addObject(SAMLDiscovery.RETURN_URL, request.getAttribute(SAMLDiscovery.RETURN_URL)); 38 | idpSelection.addObject(SAMLDiscovery.RETURN_PARAM, request.getAttribute(SAMLDiscovery.RETURN_PARAM)); 39 | Map idpNameAliasMap = metadataManager.getIDPEntityNames().stream() 40 | .collect(toMap(identity(), this::getAlias)); 41 | idpSelection.addObject("idpNameAliasMap", idpNameAliasMap); 42 | return idpSelection; 43 | } 44 | throw new AuthenticationServiceException("SP Discovery flow not detected"); 45 | } 46 | 47 | @SneakyThrows 48 | private String getAlias(String entityId) { 49 | return metadataManager.getExtendedMetadata(entityId).getAlias(); 50 | } 51 | 52 | private boolean comesFromDiscoveryFilter(HttpServletRequest request) { 53 | return request.getAttribute(SAMLConstants.LOCAL_ENTITY_ID) != null && 54 | request.getAttribute(SAMLDiscovery.RETURN_URL) != null && 55 | request.getAttribute(SAMLDiscovery.RETURN_PARAM) != null; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/spring/mvc/SAMLUser.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.spring.mvc; 2 | 3 | import org.springframework.security.core.annotation.AuthenticationPrincipal; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * @author Ulises Bocchio 9 | */ 10 | @Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | @AuthenticationPrincipal 14 | public @interface SAMLUser { 15 | } 16 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/spring/security/SAMLUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.spring.security; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import java.util.Map; 6 | import java.util.stream.Collectors; 7 | 8 | import org.opensaml.saml2.core.Attribute; 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | import org.springframework.security.saml.SAMLCredential; 13 | import org.springframework.security.saml.userdetails.SAMLUserDetailsService; 14 | 15 | /** 16 | * Default Implementation of {@link UserDetails} for Spring Boot Security SAML. This simple implementation hardly covers all security aspects since it's mostly 17 | * hardcoded. I.E. accounts are never locked, expired, or disabled, and always eturn the same granted authority "ROLE_USER". Consider implementing your own 18 | * {@link UserDetails} and {@link SAMLUserDetailsService}. 19 | * 20 | * @author Ulises Bocchio 21 | */ 22 | public class SAMLUserDetails implements UserDetails { 23 | 24 | private SAMLCredential samlCredential; 25 | 26 | public SAMLUserDetails(SAMLCredential samlCredential) { 27 | this.samlCredential = samlCredential; 28 | } 29 | 30 | @Override 31 | public Collection getAuthorities() { 32 | return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); 33 | } 34 | 35 | @Override 36 | public String getPassword() { 37 | return ""; 38 | } 39 | 40 | @Override 41 | public String getUsername() { 42 | return samlCredential.getNameID().getValue(); 43 | } 44 | 45 | @Override 46 | public boolean isAccountNonExpired() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean isAccountNonLocked() { 52 | return true; 53 | } 54 | 55 | @Override 56 | public boolean isCredentialsNonExpired() { 57 | return true; 58 | } 59 | 60 | @Override 61 | public boolean isEnabled() { 62 | return true; 63 | } 64 | 65 | public String getAttribute(String name) { 66 | return samlCredential.getAttributeAsString(name); 67 | } 68 | 69 | public String[] getAttributeArray(String name) { 70 | return samlCredential.getAttributeAsStringArray(name); 71 | } 72 | 73 | public Map getAttributes() { 74 | return samlCredential.getAttributes().stream() 75 | .collect(Collectors.toMap(Attribute::getName, this::getString)); 76 | } 77 | 78 | private String getString(Attribute attribute) { 79 | String value = getValue(attribute); 80 | return value == null ? "" : value; 81 | } 82 | 83 | public Map getAttributesArrays() { 84 | return samlCredential.getAttributes().stream() 85 | .collect(Collectors.toMap(Attribute::getName, this::getValueArray)); 86 | } 87 | 88 | private String getValue(Attribute attribute) { 89 | return getAttribute(attribute.getName()); 90 | } 91 | 92 | private String[] getValueArray(Attribute attribute) { 93 | return getAttributeArray(attribute.getName()); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/java/com/ulisesbocchio/security/saml/spring/security/SAMLUserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml.spring.security; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 7 | import org.springframework.security.core.userdetails.User; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.security.saml.SAMLCredential; 10 | import org.springframework.security.saml.userdetails.SAMLUserDetailsService; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * @author Ulises Bocchio 18 | */ 19 | @Slf4j 20 | @Service 21 | public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService { 22 | 23 | public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException { 24 | log.info("Login received for user {}", credential.getNameID().getValue()); 25 | return new SAMLUserDetails(credential); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | security: 3 | enabled: false 4 | context-path: "/manage" 5 | 6 | logging.level.org.springframework.security.saml: DEBUG -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/idp-okta.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 9 | MIIDpDCCAoygAwIBAgIGAVO669oLMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG 10 | A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU 11 | MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi04MzkyMjgxHDAaBgkqhkiG9w0BCQEW 12 | DWluZm9Ab2t0YS5jb20wHhcNMTYwMzI4MDE1MTEyWhcNMjYwMzI4MDE1MjEyWjCBkjELMAkGA1UE 13 | BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNV 14 | BAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtODM5MjI4MRwwGgYJ 15 | KoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 16 | 0H9hcvueaxQsH+GjDBPJdQ3FotGgPFOyFuZFvDwBeXiTMPAMoB8s+9Ey7ugYoAvLJMm7ryXAhOGa 17 | tblP4BcxPWrFJx+Tddswkb9pmM9rbmfrBBW3gsiwPQ/bEuwnvNxICIaeWD7h50Qej8UgrSunqmEq 18 | pBYi530/mWy7fdyRWniC0NtqlGDc+7jM4itchIjxuJXm0MX8BTzUkk8yU/Ul/YwNCwTAZNwispES 19 | ADsU9Mc+qcI6Fc68NC8pzPTpV4XEIiDwK8bfdQa1kwM3teL+1cHTXkEMvfhzBLZLedaB7b2Ictp+ 20 | /mPtX/m9+zu/oqeZs1ZfCPfOpaNQCw4ug/G7PQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAxlYaA 21 | PPB8kvNZgLX1V/WGxfpQTZMVLJGCfVA50I7wzRn+bDgkLhl2L3Rn7V7epQ7yOGYoIZ2QZGqu8fto 22 | xyXLmbx+gKvrejPp8QGCDl4Ga9UppIRtvdnLpXKeBw1m2GbLbgIlMmCbSGo05YSxBM7m6C7ZBDbA 23 | Sn8kNrM+77jWPs+uRO/Oe9UlMGIMIvxaUyy7H9TpUNHAMQKwYPiua/32T53iv9TZ6YYgdK1b2haA 24 | N3ESCsNEmU5BRZBQgBMRiw1qfWt5tGpAxjCKkVFEwR6gQwqH5QhAnzA9lyVAq8FGr7HDxMyLoObB 25 | avSvuMAJ1fZFZh4v3XJussihq2MjHH3g 26 | 27 | 28 | 29 | 30 | 32 | 34 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress 35 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified 36 | 38 | 40 | 41 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/idp-onelogin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | MIIEKTCCAxGgAwIBAgIUMZQydOi0ZordvxMyczVbCIvGGpgwDQYJKoZIhvcNAQEF 9 | BQAwXjELMAkGA1UEBhMCVVMxFzAVBgNVBAoMDlVsaXNlcyBCb2NjaGlvMRUwEwYD 10 | VQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODA5 11 | NDAwHhcNMTYwMzI2MTY0NDExWhcNMjEwMzI3MTY0NDExWjBeMQswCQYDVQQGEwJV 12 | UzEXMBUGA1UECgwOVWxpc2VzIEJvY2NoaW8xFTATBgNVBAsMDE9uZUxvZ2luIElk 13 | UDEfMB0GA1UEAwwWT25lTG9naW4gQWNjb3VudCA4MDk0MDCCASIwDQYJKoZIhvcN 14 | AQEBBQADggEPADCCAQoCggEBAKjdXtawZwsmmtrb9Z82Yov9uqmiNh8QyyQ+cpW2 15 | f4IgfQygEDJoAvb2W1mHPB6W3DsMjorvXlCp5+Yn2w54eLHUfExB2uCeEJY+myY/ 16 | hyyQzdHH5uC6hWerz1V4JjVGDcxs2U8Suclc8m0ge8tXaJU4ByLeB3yMjS/qneWl 17 | iFqxcZ4gUpdCRcSXnezwC8QPIy1wMZfJyQOqnuavqkpnB31MHGfjOwE0PMyBTWaC 18 | onZ7dsTAAX0/PSaZcT+BA7Qeol0GGUwgVMuuvf0ymiHaHN2Y88RVm3kPwKr5C3Bt 19 | yVlC3IZM9VhxoaxgmSIEKfwKZgRTbbmjjt8w6J1CkIq6ClMCAwEAAaOB3jCB2zAM 20 | BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTX8TN/N7vhy/hHsAFaJ1+VOR9cxzCBmwYD 21 | VR0jBIGTMIGQgBTX8TN/N7vhy/hHsAFaJ1+VOR9cx6FipGAwXjELMAkGA1UEBhMC 22 | VVMxFzAVBgNVBAoMDlVsaXNlcyBCb2NjaGlvMRUwEwYDVQQLDAxPbmVMb2dpbiBJ 23 | ZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODA5NDCCFDGUMnTotGaK3b8T 24 | MnM1WwiLxhqYMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAQEAGk2m 25 | COTJa4N3iIWpspUTxVeaev4Bxjpmoe+1OQnQqvHYdXO4xZwQIj56B7mErXZJ9XGH 26 | 6t28Kw0yq8UZYCVdjkyV5KmaoTIDBhKr2+mjbtlZH9RYA6VvOxupFt/Rf7cax5vq 27 | 7RneWhT1dL/u49r5eUMNFJbeR3FE2SUp/9qhqOQkexfRgGHPDTEv4nYIiXWkk2qj 28 | ZfEP8eCIZp0yJcL0k4Ulo/CxusWVYhNNTNBdcmmYZbWUjQlr9toBVMQa/YcJs24b 29 | EUEb/XLDntIXEmjhUI1bYB+lU9V1lW+8YHIvtZKCoSCkYU8qlZSkoBOMPMVyrhw3 30 | zsJ4ayogap7/2aUL2g== 31 | 32 | 33 | 34 | 35 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified 36 | 38 | 40 | 42 | 44 | 45 | 46 | Support 47 | support@onelogin.com 48 | 49 | 50 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/idp-pingone.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | MIIDbjCCAlagAwIBAgIGAVO7a/mHMA0GCSqGSIb3DQEBCwUAMHgxCzAJBgNVBAYTAlVTMQswCQYD 9 | VQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRYwFAYDVQQKEw1QaW5nIElkZW50aXR5MTMwMQYDVQQD 10 | EypodHRwc3BpbmdvbmVjb21pZHBjZDYxNzYxMjExMnVsaXNlc2JvY2NoaW8wHhcNMTYwMzI4MDQx 11 | MjA4WhcNMTkwMzI4MDQxMjA4WjB4MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ08xDzANBgNVBAcT 12 | BkRlbnZlcjEWMBQGA1UEChMNUGluZyBJZGVudGl0eTEzMDEGA1UEAxMqaHR0cHNwaW5nb25lY29t 13 | aWRwY2Q2MTc2MTIxMTJ1bGlzZXNib2NjaGlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 14 | AQEAhjQMpQYdTErsPdJ2iLVpKXVnAlr/W2vHXxwVEi/P4dilEP2svWPVfTYr0omM28mOPh1DZkl9 15 | KQvSxJCKWy/ronG+FS5hQ2SeKb0vnQMG/ipWaA9IsLZDx9QM0R456AKqe+D+ioYltgQxqvR3TeFb 16 | /xlOnUs3/MNRbhS+BPi9DSkpADMEkfadk3U7GX3Imna3Jj+SV4gAOwqjS+Q2bmWrv96d7RXQKAKT 17 | DjO1CVH+n5ku0l6+WzQKAeLp4daB0JKSJfaeCTI1gO5b2nq0U6/0ilNbMzGXSgu9yFhk59PF7CwK 18 | JNxTKQuvoTayUvlXOzwcNj1phiUtn48TNy1ZdEBsMQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAb 19 | 9hZQ9yaWDW1/x5TwMx7xiKpQzYNv1y1Ftwj1DrJMC4NvtZzurOYeya81fqoPKGtIn5PMaZu4bl5g 20 | ytyWlqtRhwbI2Vrwyy1RUQml+il94W5u83e1FXV7PY7xJXHJ+KE2z3Pyeo5sDBnXDVnT+ytNDtam 21 | 0IDZXzQ81tCMQ/rcieIqbihtMPf9qMTB6Xv5EwlAeSWMCD0PvWx5Ng2Y1bp95kiwp5YU/8j7PwOJ 22 | 1mRrjju+S6ixQeD+VJrF4y6vMhORUrJXqEU7EKMuqeQB5fzDX7VNsnePnRqBifqDTt9QnafeIJ8u 23 | XCtHy2m5UXZ8eDEAbo9jWhkZC+6IVbgSoeFa 24 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 35 | 38 | 40 | 42 | 43 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/idp-ssocircle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MIICjDCCAXSgAwIBAgIFAJRvxcMwDQYJKoZIhvcNAQEEBQAwLjELMAkGA1UEBhMCREUxEjAQBgNV 9 | BAoTCVNTT0NpcmNsZTELMAkGA1UEAxMCQ0EwHhcNMTEwNTE3MTk1NzIxWhcNMTYwODE3MTk1NzIx 10 | WjBLMQswCQYDVQQGEwJERTESMBAGA1UEChMJU1NPQ2lyY2xlMQwwCgYDVQQLEwNpZHAxGjAYBgNV 11 | BAMTEWlkcC5zc29jaXJjbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbzDRkudC/ 12 | aC2gMqRVVaLdPJJEwpFB4o71fR5bnNd2ocnnNzJ/W9CoCargzKx+EJ4Nm3vWmX/IZRCFvrvy9C78 13 | fP1cmt6Sa091K9luaMAyWn7oC8h/YBXH7rB42tdvWLY4Kl9VJy6UCclvasyrfKx+SR4KU6zCsM62 14 | 2Kvp5wW67QIDAQABoxgwFjAUBglghkgBhvhCAQEBAf8EBAMCBHAwDQYJKoZIhvcNAQEEBQADggEB 15 | AJ0heua7mFO3QszdGu1NblGaTDXtf6Txte0zpYIt+8YUcza2SaZXXvCLb9DvGxW1TJWaZpPGpHz5 16 | tLXJbdYQn7xTAnL4yQOKN6uNqUA/aTVgyyUJkWZt2giwEsWUvG0UBMSPS1tp2pV2c6/olIcbdYU6 17 | ZecUz6N24sSS7itEBC6nwCVBoHOL8u6MsfxMLDzJIPBI68UZjz3IMKTDUDv6U9DtYmXLc8iMVZBn 18 | cYJn9NgNi3ghl9fYPpHcc6QbXeDUjhdzXXUqG+hB6FabGqdTdkIZwoi4gNpyr3kacKRVWJssDgak 19 | eL2MoDNqJyQ0fXC6Ze3f79CKy/WjeU5FLwDZR0Q= 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | MIICjDCCAXSgAwIBAgIFAJRvxcMwDQYJKoZIhvcNAQEEBQAwLjELMAkGA1UEBhMCREUxEjAQBgNV 29 | BAoTCVNTT0NpcmNsZTELMAkGA1UEAxMCQ0EwHhcNMTEwNTE3MTk1NzIxWhcNMTYwODE3MTk1NzIx 30 | WjBLMQswCQYDVQQGEwJERTESMBAGA1UEChMJU1NPQ2lyY2xlMQwwCgYDVQQLEwNpZHAxGjAYBgNV 31 | BAMTEWlkcC5zc29jaXJjbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbzDRkudC/ 32 | aC2gMqRVVaLdPJJEwpFB4o71fR5bnNd2ocnnNzJ/W9CoCargzKx+EJ4Nm3vWmX/IZRCFvrvy9C78 33 | fP1cmt6Sa091K9luaMAyWn7oC8h/YBXH7rB42tdvWLY4Kl9VJy6UCclvasyrfKx+SR4KU6zCsM62 34 | 2Kvp5wW67QIDAQABoxgwFjAUBglghkgBhvhCAQEBAf8EBAMCBHAwDQYJKoZIhvcNAQEEBQADggEB 35 | AJ0heua7mFO3QszdGu1NblGaTDXtf6Txte0zpYIt+8YUcza2SaZXXvCLb9DvGxW1TJWaZpPGpHz5 36 | tLXJbdYQn7xTAnL4yQOKN6uNqUA/aTVgyyUJkWZt2giwEsWUvG0UBMSPS1tp2pV2c6/olIcbdYU6 37 | ZecUz6N24sSS7itEBC6nwCVBoHOL8u6MsfxMLDzJIPBI68UZjz3IMKTDUDv6U9DtYmXLc8iMVZBn 38 | cYJn9NgNi3ghl9fYPpHcc6QbXeDUjhdzXXUqG+hB6FabGqdTdkIZwoi4gNpyr3kacKRVWJssDgak 39 | eL2MoDNqJyQ0fXC6Ze3f79CKy/WjeU5FLwDZR0Q= 40 | 41 | 42 | 43 | 44 | 128 45 | 46 | 47 | 49 | 52 | 55 | 57 | 60 | 63 | 65 | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent 66 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient 67 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified 68 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress 69 | urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos 70 | 72 | 74 | 76 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/localhost.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+zCCAeOgAwIBAgIJAIU7CnmezGizMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAeFw0xNjA0MDMwMjEwMjVaFw0yNjA0MDEwMjEwMjVaMBQx 4 | EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAN1NO3L/yCCb+MYFkypvJXcjlQuyRG7UFATYOYQZzIxsD9AtnXPh67uVkZTI 6 | oK7Ps5X4a5qVARtdN+GCFZ/ITahlAlIx8rmVsbz+7XPWpGPf75tKbem3pON2NlYW 7 | wIEQqyuValZHDUMgIXPdGIAZeNejVu7gYMLJwiSMtB0uBM69ptzgigJcbnup/cSL 8 | W4fBh4ck5kj0SVmX58knfaizrVf+ghGyNFha9Xy+DoilCofxwFIpVskv/hczZ5L+ 9 | e81R+u2UbNzRwf8paF5fdVwaHPGLOYSBGjSm71VDdJqlvKrJCBoCQODhtmJOmDHD 10 | jtf6gwwbdg3g9GvyqIJnRqBO908CAwEAAaNQME4wHQYDVR0OBBYEFMNtl5fAchs3 11 | 5gZS4EF8/0C7QfBQMB8GA1UdIwQYMBaAFMNtl5fAchs35gZS4EF8/0C7QfBQMAwG 12 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAADVL8LgYGlmaHlyrKyKfsQF 13 | TVbdT1Fk3WaGocVbhmvFeEBHScSJNR0syDcDM1C18pZ6Jc73cW7UdtLbLbRNPXS+ 14 | qcp5GZroafndPIL2QzdKXfc5MiGH7CRCZit9kiNJ6YYgsztappXnwKblioJHB1Bc 15 | oLRzMeD295DAGLEVuc5tSY7JHBD3YQS9Pwt3ivrvvCzFKOU9nHqChMCplO4StGpS 16 | bbSR6XNgsPA0XLWlleuTqLGvJ4bHXPKC+0Y+0AiQYx3GeWLVrwJ4w+PFEK73vyuB 17 | 9H10x+zy1nFWvqoa+K66EA4u7DpEoHJBlqH0AVWAd8q9488DpCo1x4ujTGw7AHE= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEA3U07cv/IIJv4xgWTKm8ldyOVC7JEbtQUBNg5hBnMjGwP0C2d 3 | c+Hru5WRlMigrs+zlfhrmpUBG1034YIVn8hNqGUCUjHyuZWxvP7tc9akY9/vm0pt 4 | 6bek43Y2VhbAgRCrK5VqVkcNQyAhc90YgBl416NW7uBgwsnCJIy0HS4Ezr2m3OCK 5 | Alxue6n9xItbh8GHhyTmSPRJWZfnySd9qLOtV/6CEbI0WFr1fL4OiKUKh/HAUilW 6 | yS/+FzNnkv57zVH67ZRs3NHB/yloXl91XBoc8Ys5hIEaNKbvVUN0mqW8qskIGgJA 7 | 4OG2Yk6YMcOO1/qDDBt2DeD0a/KogmdGoE73TwIDAQABAoIBAQDG0OH9+OnU0gt3 8 | 6/5A+0XPeTooHen5H7M0fwV9Nqhb56F1R+XS/D8Kcd8uqegh5RvUOjCB2if6a48O 9 | nA3NVOjfxo+FRLZqIKBjySuPDGD4EXF0NDP26zPJ3qQGR75+tXjyWPQFuyOhELa9 10 | Hv8p5rh4EpjBVvfXR+eRao9OP8+142Sedn5yKobQ6Qe9h4TIgBoCi1XCs86ySChr 11 | 7ITG3vEeB3Eq5hSbeN255m+VGjDySeeXsKHmnDHEq0ayLa8LbmD0XLmiLTrbV8IO 12 | Zy7qDxxnlIxjAmmbQj42orNNhDQwoGzy1wa8Yh5/3gwdxGXhufo7ItkkeRnCKCmh 13 | ThP0GSqBAoGBAPZNtNEHDxo5Getm4DbywTHYv+XBlWfLDkJSRjMSTCKzv9MemoX4 14 | vE5sx4ax8oLRcz4pQnfbXQeDePvvLyWApS6qhWbS9qf8oaIt2exPolqmCJibdGpM 15 | Y0Xk3ZFpUA7a+2jPK1PbrwLj/w7zNmFU8Rh/8RZS0QmBIcxovPH7kZ7vAoGBAOYD 16 | jXGVxcxsTdK8Ns6hltVPEE+XmWGfInCVfpAvECN+plwna1abdXafYnMXlmg/tC4q 17 | 2Ufkcw3PEtFKCAMQ1P0n8jSKXpjj1Lxlrunj2404eH93uHJih6zYE2gb/P+7jm49 18 | 377SQOObrueWZUy4mIIZmbT6464rq6sKP6tb1i2hAoGBAIQG31f0yrmpxiUTPjj2 19 | I21O3H6SKD488GXIqGyT8E/hvn+yte3+iSIY2VNwa6iIEZhOkZyh79opNV8GtWUK 20 | 8oBzU5Lsnt8pYpMGtPwhK8wfmBgFrH+Wdthud/6MTyfHZmCmPHl1FvkbsgsXgBzo 21 | ZVxWqKrotbi8iZuCwVWNHl/tAoGAEms2aGIV9Mi3cqifuuw1p98s7zK0lZyopVtT 22 | Rzh9kloR+E8vyT+pqFYbDBxXbwGq7AeCXr9sdy6d0ySaf6RZaexI+OwbpyKXZn6+ 23 | Avy8GBLtk0eC/aXmN3EWHMAhAlmCjlFmGWG80H0nBGSGuB4QGFr0dAmjMc9Nb+Ti 24 | NFamUAECgYEA7uPN2cpwvVlt4Q4BHxjvvo1XDRe5c+RwDVa/dYkLu85HVvRd42SJ 25 | QgIdcZR9kLRXuOFCWv1shFmfHPqfmH0q6hn39TgVnUyHxzBlAbP5Dx/n4FRs8EP8 26 | qqNS0ft5Mqoy1UuJL6N5iDYY+i8Is90bsC9mMPj007kfFcyJcRULrSA= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/localhost.key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulisesbocchio/spring-boot-security-saml-samples/9ef34b596d6f5ffe9ddad04cabdc896cad73e4f9/spring-security-saml-sample/src/main/resources/localhost.key.der -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Home Page 6 | 7 | 8 |

This is the Home Page

9 | 10 |

Current User: unknown

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
SAML Attributes
Attribute NameAttribute Value
keyvalue
26 |

27 | Idp Single Logout - Local Logout 28 |

29 | 30 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/templates/idpselection.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | IdP Selection 6 | 7 | 8 | Select an IdP: 9 |
10 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sample SAML Spring Boot Application 6 | 7 | 8 |

Hi, Click here to start the Single Sign On process

9 | 10 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/main/resources/templates/protected.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Protected Resource 6 | 7 | 8 |

Protected Resource

9 |

10 | This is a Protected Resource 11 |

12 | Home 13 | 14 | -------------------------------------------------------------------------------- /spring-security-saml-sample/src/test/java/com/ulisesbocchio/security/saml/SamlSpSampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ulisesbocchio.security.saml; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | 8 | @RunWith(SpringJUnit4ClassRunner.class) 9 | @SpringBootTest(classes = SamlServiceProviderApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 10 | public class SamlSpSampleApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------