diff --git a/.gitignore b/.gitignore index 349efbcb67..9c100eaded 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,6 @@ target/ spring-openid/src/main/resources/application.properties .recommenders/ /spring-hibernate4/nbproject/ -spring-security-openid/src/main/resources/application.properties spring-all/*.log diff --git a/pom.xml b/pom.xml index b8978ab067..7ea23f0d63 100644 --- a/pom.xml +++ b/pom.xml @@ -825,7 +825,7 @@ spring-security-modules/spring-security-mvc-login spring-security-modules/spring-security-mvc-persisted-remember-me spring-security-modules/spring-security-mvc-socket - spring-security-modules/spring-security-openid + spring-security-modules/spring-security-oidc spring-security-modules/spring-security-rest spring-security-modules/spring-security-rest-basic-auth diff --git a/spring-security-modules/spring-security-oidc/README.md b/spring-security-modules/spring-security-oidc/README.md new file mode 100644 index 0000000000..92ba60cad9 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/README.md @@ -0,0 +1,23 @@ +## Spring Security OpenID + +This module contains articles about OpenID with Spring Security + +### Relevant articles + +- [Spring Security and OpenID Connect](https://www.baeldung.com/spring-security-openid-connect) + +### OpenID Connect with Spring Security + +### Run the Project + +``` +mvn spring-boot:run +``` + +### Obtain Google App - Client ID, Secret + +- We need to get client id and client secret by creating a new project at [Google Developer Console](https://console.developers.google.com/project/_/apiui/credential?pli=1) +- We can follow these instructions to register our client application on their platform + +- Once we have the client id and secret, we have to make sure we add them to the YAML files of the project + diff --git a/spring-security-modules/spring-security-oidc/pom.xml b/spring-security-modules/spring-security-oidc/pom.xml new file mode 100644 index 0000000000..91e4641450 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + spring-security-oidc + spring-security-oidc + war + Spring OpenID Connect sample project + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + + + 2.2.1.RELEASE + + + diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/discovery/SpringOidcDiscoveryApplication.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/discovery/SpringOidcDiscoveryApplication.java new file mode 100644 index 0000000000..895fe676e1 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/discovery/SpringOidcDiscoveryApplication.java @@ -0,0 +1,20 @@ +package com.baeldung.openid.oidc.discovery; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; + +import com.baeldung.openid.oidc.utils.YamlLoaderInitializer; + +@SpringBootApplication +public class SpringOidcDiscoveryApplication { + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(SpringOidcDiscoveryApplication.class); + ApplicationContextInitializer yamlInitializer = new YamlLoaderInitializer("discovery-application.yml"); + application.addInitializers(yamlInitializer); + application.run(args); + } + +} diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/discovery/web/controllers/UserRestController.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/discovery/web/controllers/UserRestController.java new file mode 100644 index 0000000000..984a23fea3 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/discovery/web/controllers/UserRestController.java @@ -0,0 +1,17 @@ +package com.baeldung.openid.oidc.discovery.web.controllers; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/user") +public class UserRestController { + + @GetMapping("/oidc-principal") + public OidcUser getOidcUserPrincipal(@AuthenticationPrincipal OidcUser principal) { + return principal; + } +} diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/SpringOidcLoginApplication.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/SpringOidcLoginApplication.java new file mode 100644 index 0000000000..6ec87c4406 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/SpringOidcLoginApplication.java @@ -0,0 +1,20 @@ +package com.baeldung.openid.oidc.login; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; + +import com.baeldung.openid.oidc.utils.YamlLoaderInitializer; + +@SpringBootApplication +public class SpringOidcLoginApplication { + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(SpringOidcLoginApplication.class); + ApplicationContextInitializer yamlInitializer = new YamlLoaderInitializer("login-application.yml"); + application.addInitializers(yamlInitializer); + application.run(args); + } + +} diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/config/OAuth2LoginSecurityConfig.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/config/OAuth2LoginSecurityConfig.java new file mode 100644 index 0000000000..5bb5cef58c --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/config/OAuth2LoginSecurityConfig.java @@ -0,0 +1,28 @@ +package com.baeldung.openid.oidc.login.config; + +import java.util.HashSet; +import java.util.Set; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; + +@Configuration +public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {// @formatter:off + + @Override + protected void configure(HttpSecurity http) throws Exception { + Set googleScopes = new HashSet<>(); + googleScopes.add("https://www.googleapis.com/auth/userinfo.email"); + googleScopes.add("https://www.googleapis.com/auth/userinfo.profile"); + + OidcUserService googleUserService = new OidcUserService(); + googleUserService.setAccessibleScopes(googleScopes); + + http.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest() + .authenticated()) + .oauth2Login(oauthLogin -> oauthLogin.userInfoEndpoint() + .oidcUserService(googleUserService)); + }// @formatter:on +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/service/UserService.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/service/UserService.java new file mode 100644 index 0000000000..b6e35bd139 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/service/UserService.java @@ -0,0 +1,23 @@ +package com.baeldung.openid.oidc.login.service; + +import java.util.Collections; +import java.util.Map; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.stereotype.Service; + +@Service +public class UserService { + + public Map getUserClaims() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication.getPrincipal() instanceof OidcUser) { + OidcUser principal = ((OidcUser) authentication.getPrincipal()); + return principal.getClaims(); + } + return Collections.emptyMap(); + } +} diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/web/controllers/UserRestController.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/web/controllers/UserRestController.java new file mode 100644 index 0000000000..a4715c9310 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/login/web/controllers/UserRestController.java @@ -0,0 +1,32 @@ +package com.baeldung.openid.oidc.login.web.controllers; + +import java.util.Map; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.openid.oidc.login.service.UserService; + +@RestController +@RequestMapping("/user") +public class UserRestController { + + private UserService service; + + public UserRestController(UserService service) { + this.service = service; + } + + @GetMapping("/oidc-principal") + public OidcUser getOidcUserPrincipal(@AuthenticationPrincipal OidcUser principal) { + return principal; + } + + @GetMapping("/oidc-claims") + public Map getClaimsFromBean() { + return service.getUserClaims(); + } +} diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/SpringOidcSessionManagementApplication.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/SpringOidcSessionManagementApplication.java new file mode 100644 index 0000000000..700fc7fbe7 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/SpringOidcSessionManagementApplication.java @@ -0,0 +1,20 @@ +package com.baeldung.openid.oidc.sessionmanagement; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; + +import com.baeldung.openid.oidc.utils.YamlLoaderInitializer; + +@SpringBootApplication +public class SpringOidcSessionManagementApplication { + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(SpringOidcSessionManagementApplication.class); + ApplicationContextInitializer yamlInitializer = new YamlLoaderInitializer("sessionmanagement-application.yml"); + application.addInitializers(yamlInitializer); + application.run(args); + } + +} diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/config/OAuth2SessionManagementSecurityConfig.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/config/OAuth2SessionManagementSecurityConfig.java new file mode 100644 index 0000000000..5a55c89b05 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/config/OAuth2SessionManagementSecurityConfig.java @@ -0,0 +1,37 @@ +package com.baeldung.openid.oidc.sessionmanagement.config; + +import java.net.URI; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; + +@Configuration +public class OAuth2SessionManagementSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientRegistrationRepository clientRegistrationRepository; + + @Override + protected void configure(HttpSecurity http) throws Exception { // @formatter:off + http.authorizeRequests(authorizeRequests -> authorizeRequests.mvcMatchers("/home") + .permitAll() + .anyRequest() + .authenticated()) + .oauth2Login(oauthLogin -> oauthLogin.permitAll()) + .logout(logout -> logout.logoutSuccessHandler(oidcLogoutSuccessHandler())); + } // @formatter:on + + + private LogoutSuccessHandler oidcLogoutSuccessHandler() { + OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository); + + oidcLogoutSuccessHandler.setPostLogoutRedirectUri(URI.create("http://localhost:8081/home")); + + return oidcLogoutSuccessHandler; + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/web/controllers/HomeRestController.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/web/controllers/HomeRestController.java new file mode 100644 index 0000000000..88becc2456 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/web/controllers/HomeRestController.java @@ -0,0 +1,14 @@ +package com.baeldung.openid.oidc.sessionmanagement.web.controllers; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HomeRestController { + + @GetMapping("/home") + public String simpleHomepage() { + return "Welcome to this simple homepage!"; + } + +} diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/web/controllers/UserRestController.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/web/controllers/UserRestController.java new file mode 100644 index 0000000000..256d4bc389 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/sessionmanagement/web/controllers/UserRestController.java @@ -0,0 +1,17 @@ +package com.baeldung.openid.oidc.sessionmanagement.web.controllers; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/user") +public class UserRestController { + + @GetMapping("/oidc-principal") + public OidcUser getOidcUserPrincipal(@AuthenticationPrincipal OidcUser principal) { + return principal; + } +} diff --git a/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/utils/YamlLoaderInitializer.java b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/utils/YamlLoaderInitializer.java new file mode 100644 index 0000000000..4d51dcb9a8 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/java/com/baeldung/openid/oidc/utils/YamlLoaderInitializer.java @@ -0,0 +1,48 @@ +package com.baeldung.openid.oidc.utils; + +import java.io.IOException; + +import org.springframework.boot.env.YamlPropertySourceLoader; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class YamlLoaderInitializer implements ApplicationContextInitializer { + + private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); + private final String file; + + public YamlLoaderInitializer() { + this.file = null; + } + + public YamlLoaderInitializer(String file) { + this.file = file; + } + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + String yamlFile = (this.file == null) ? applicationContext.getEnvironment() + .getProperty("custom.configyaml.file") : this.file; + Resource path = new ClassPathResource(yamlFile); + PropertySource propertySource = loadYaml(path); + applicationContext.getEnvironment() + .getPropertySources() + .addLast(propertySource); + } + + private PropertySource loadYaml(Resource path) { + if (!path.exists()) { + throw new IllegalArgumentException("Resource " + path + " does not exist"); + } + try { + return this.loader.load("custom-resource", path) + .get(0); + } catch (IOException ex) { + throw new IllegalStateException("Failed to load yaml configuration from" + path, ex); + } + } + +} diff --git a/spring-security-modules/spring-security-oidc/src/main/resources/application.yml b/spring-security-modules/spring-security-oidc/src/main/resources/application.yml new file mode 100644 index 0000000000..f303fcecd1 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/resources/application.yml @@ -0,0 +1,7 @@ +server: + port: 8081 + +logging: + level: + org.springframework.web.client.RestTemplate: DEBUG + \ No newline at end of file diff --git a/spring-security-modules/spring-security-oidc/src/main/resources/discovery-application.yml b/spring-security-modules/spring-security-oidc/src/main/resources/discovery-application.yml new file mode 100644 index 0000000000..1cbebbcb7b --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/resources/discovery-application.yml @@ -0,0 +1,11 @@ +spring: + security: + oauth2: + client: + registration: + custom-google: + client-id: + client-secret: + provider: + custom-google: + issuer-uri: https://accounts.google.com \ No newline at end of file diff --git a/spring-security-modules/spring-security-oidc/src/main/resources/login-application.yml b/spring-security-modules/spring-security-oidc/src/main/resources/login-application.yml new file mode 100644 index 0000000000..b3220a0550 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/resources/login-application.yml @@ -0,0 +1,8 @@ +spring: + security: + oauth2: + client: + registration: + google: + client-id: + client-secret: \ No newline at end of file diff --git a/spring-security-modules/spring-security-oidc/src/main/resources/sessionmanagement-application.yml b/spring-security-modules/spring-security-oidc/src/main/resources/sessionmanagement-application.yml new file mode 100644 index 0000000000..d7dd5e6ec7 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/main/resources/sessionmanagement-application.yml @@ -0,0 +1,16 @@ +spring: + security: + oauth2: + client: + registration: + okta: + client-id: + client-secret: + provider: + okta: + issuer-uri: https://dev-123.okta.com + # Or, optionally: + #authorization-uri https://dev-123-admin.okta.com/oauth2/v1/authorize + #token-uri: https://dev-123-admin.okta.com/oauth2/v1/token + #user-info-uri: https://dev-123-admin.okta.com/oauth2/v1/userinfo + #jwk-set-uri: https://dev-123-admin.okta.com/oauth2/v1/keys \ No newline at end of file diff --git a/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/discovery/SpringContextTest.java b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/discovery/SpringContextTest.java new file mode 100644 index 0000000000..25c87cdc6f --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/discovery/SpringContextTest.java @@ -0,0 +1,19 @@ +package com.baeldung.openid.oidc.discovery; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import com.baeldung.openid.oidc.utils.YamlLoaderInitializer; + +//We'll ignore this test, as we don't want to depend on Google's OIDC-configuration endpoint to be available +@Disabled +@SpringBootTest(classes = SpringOidcDiscoveryApplication.class, properties = "custom.configyaml.file=discovery-application.yml") +@ContextConfiguration(initializers = YamlLoaderInitializer.class) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/login/SpringContextTest.java b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/login/SpringContextTest.java new file mode 100644 index 0000000000..675dcd8727 --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/login/SpringContextTest.java @@ -0,0 +1,16 @@ +package com.baeldung.openid.oidc.login; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import com.baeldung.openid.oidc.utils.YamlLoaderInitializer; + +@SpringBootTest(classes = SpringOidcLoginApplication.class, properties = "custom.configyaml.file=login-application.yml") +@ContextConfiguration(initializers = YamlLoaderInitializer.class) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/sessionmanagement/SpringContextTest.java b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/sessionmanagement/SpringContextTest.java new file mode 100644 index 0000000000..91ed11fbaf --- /dev/null +++ b/spring-security-modules/spring-security-oidc/src/test/java/com/baeldung/openid/oidc/sessionmanagement/SpringContextTest.java @@ -0,0 +1,19 @@ +package com.baeldung.openid.oidc.sessionmanagement; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import com.baeldung.openid.oidc.utils.YamlLoaderInitializer; + +//We'll ignore this test, as we don't want to depend on the Okta instance OIDC-configuration endpoint to be available +@Disabled +@SpringBootTest(classes = SpringOidcSessionManagementApplication.class, properties = "custom.configyaml.file=sessionmanagement-application.yml") +@ContextConfiguration(initializers = YamlLoaderInitializer.class) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-security-modules/spring-security-openid/README.md b/spring-security-modules/spring-security-openid/README.md deleted file mode 100644 index 1f856fe191..0000000000 --- a/spring-security-modules/spring-security-openid/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## Spring Security OpenID - -This module contains articles about OpenID with Spring Security - -### Relevant articles - -- [Spring Security and OpenID Connect](https://www.baeldung.com/spring-security-openid-connect) - -### OpenID Connect with Spring Security - -### Run the Project - -``` -mvn spring-boot:run -``` - -### Obtain Google App - Client ID, Secret - -- You need to get client id and client secret by creating a new project at [Google Developer Console](https://console.developers.google.com/project/_/apiui/credential?pli=1) -- Make sure to add OAuth2 credentials by selecting Add credentials > OAuth 2.0 client ID -- Make sure you set redirect URI to http://localhost:8081/google-login - -- Once you have your client id and secret, make sure you add them to the `application.properties` of the project - diff --git a/spring-security-modules/spring-security-openid/pom.xml b/spring-security-modules/spring-security-openid/pom.xml deleted file mode 100644 index 970182dc3b..0000000000 --- a/spring-security-modules/spring-security-openid/pom.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - 4.0.0 - spring-security-openid - spring-security-openid - war - Spring OpenID sample project - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-tomcat - - - - org.springframework.security.oauth - spring-security-oauth2 - ${spring-security-oauth2.version} - - - - org.springframework.security - spring-security-jwt - ${spring-security-jwt.version} - - - - com.auth0 - jwks-rsa - ${jwks-rsa.version} - - - - - 2.2.1.RELEASE - 1.0.9.RELEASE - 0.3.0 - - - diff --git a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java b/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java deleted file mode 100644 index 8e9c6e974e..0000000000 --- a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.baeldung.config; - -import java.util.Arrays; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; -import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; - -@Configuration -@EnableOAuth2Client -public class GoogleOpenIdConnectConfig { - @Value("${google.clientId}") - private String clientId; - - @Value("${google.clientSecret}") - private String clientSecret; - - @Value("${google.accessTokenUri}") - private String accessTokenUri; - - @Value("${google.userAuthorizationUri}") - private String userAuthorizationUri; - - @Value("${google.redirectUri}") - private String redirectUri; - - @Bean - public OAuth2ProtectedResourceDetails googleOpenId() { - final AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); - details.setClientId(clientId); - details.setClientSecret(clientSecret); - details.setAccessTokenUri(accessTokenUri); - details.setUserAuthorizationUri(userAuthorizationUri); - details.setScope(Arrays.asList("openid", "email")); - details.setPreEstablishedRedirectUri(redirectUri); - details.setUseCurrentUri(false); - return details; - } - - @Bean - public OAuth2RestTemplate googleOpenIdTemplate(final OAuth2ClientContext clientContext) { - final OAuth2RestTemplate template = new OAuth2RestTemplate(googleOpenId(), clientContext); - return template; - } - -} diff --git a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/HomeController.java b/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/HomeController.java deleted file mode 100644 index f0a5378019..0000000000 --- a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/HomeController.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.baeldung.config; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -@Controller -public class HomeController { - private final Logger logger = LoggerFactory.getLogger(getClass()); - - @RequestMapping("/") - @ResponseBody - public final String home() { - final String username = SecurityContextHolder.getContext().getAuthentication().getName(); - logger.info(username); - return "Welcome, " + username; - } - -} diff --git a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/SecurityConfig.java deleted file mode 100644 index d929bfd631..0000000000 --- a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/SecurityConfig.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.baeldung.config; - -import org.baeldung.security.OpenIdConnectFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; -import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; -import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; - -@Configuration -@EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Autowired - private OAuth2RestTemplate restTemplate; - - @Override - public void configure(WebSecurity web) throws Exception { - web.ignoring().antMatchers("/resources/**"); - } - - @Bean - public OpenIdConnectFilter myFilter() { - final OpenIdConnectFilter filter = new OpenIdConnectFilter("/google-login"); - filter.setRestTemplate(restTemplate); - return filter; - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .addFilterAfter(new OAuth2ClientContextFilter(), AbstractPreAuthenticatedProcessingFilter.class) - .addFilterAfter(myFilter(), OAuth2ClientContextFilter.class) - .httpBasic().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/google-login")) - .and() - .authorizeRequests() - // .antMatchers("/","/index*").permitAll() - .anyRequest().authenticated() - ; - - // @formatter:on - } -} \ No newline at end of file diff --git a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java b/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java deleted file mode 100644 index 1acdba0623..0000000000 --- a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.baeldung.config; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; - -@SpringBootApplication -public class SpringOpenidApplication extends SpringBootServletInitializer { - - public static void main(String[] args) { - SpringApplication.run(SpringOpenidApplication.class, args); - } - -} diff --git a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java b/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java deleted file mode 100644 index f12169cb27..0000000000 --- a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.baeldung.security; - -import java.io.IOException; -import java.net.URL; -import java.security.interfaces.RSAPublicKey; -import java.util.Date; -import java.util.Map; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.jwt.Jwt; -import org.springframework.security.jwt.JwtHelper; -import org.springframework.security.jwt.crypto.sign.RsaVerifier; -import org.springframework.security.oauth2.client.OAuth2RestOperations; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; - -import com.auth0.jwk.Jwk; -import com.auth0.jwk.JwkProvider; -import com.auth0.jwk.UrlJwkProvider; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class OpenIdConnectFilter extends AbstractAuthenticationProcessingFilter { - @Value("${google.clientId}") - private String clientId; - - @Value("${google.issuer}") - private String issuer; - - @Value("${google.jwkUrl}") - private String jwkUrl; - - public OAuth2RestOperations restTemplate; - - public OpenIdConnectFilter(String defaultFilterProcessesUrl) { - super(defaultFilterProcessesUrl); - setAuthenticationManager(new NoopAuthenticationManager()); - } - - @Override - public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { - - OAuth2AccessToken accessToken; - try { - accessToken = restTemplate.getAccessToken(); - } catch (final OAuth2Exception e) { - throw new BadCredentialsException("Could not obtain access token", e); - } - try { - final String idToken = accessToken.getAdditionalInformation().get("id_token").toString(); - String kid = JwtHelper.headers(idToken) - .get("kid"); - final Jwt tokenDecoded = JwtHelper.decodeAndVerify(idToken, verifier(kid)); - final Map authInfo = new ObjectMapper().readValue(tokenDecoded.getClaims(), Map.class); - verifyClaims(authInfo); - final OpenIdConnectUserDetails user = new OpenIdConnectUserDetails(authInfo, accessToken); - return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); - } catch (final Exception e) { - throw new BadCredentialsException("Could not obtain user details from token", e); - } - - } - - public void verifyClaims(Map claims) { - int exp = (int) claims.get("exp"); - Date expireDate = new Date(exp * 1000L); - Date now = new Date(); - if (expireDate.before(now) || !claims.get("iss").equals(issuer) || !claims.get("aud").equals(clientId)) { - throw new RuntimeException("Invalid claims"); - } - } - - - private RsaVerifier verifier(String kid) throws Exception { - JwkProvider provider = new UrlJwkProvider(new URL(jwkUrl)); - Jwk jwk = provider.get(kid); - return new RsaVerifier((RSAPublicKey) jwk.getPublicKey()); - } - - public void setRestTemplate(OAuth2RestTemplate restTemplate2) { - restTemplate = restTemplate2; - - } - - private static class NoopAuthenticationManager implements AuthenticationManager { - - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - throw new UnsupportedOperationException("No authentication should be done with this AuthenticationManager"); - } - - } -} diff --git a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java b/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java deleted file mode 100644 index f0d91fdc27..0000000000 --- a/spring-security-modules/spring-security-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.baeldung.security; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.common.OAuth2AccessToken; - -public class OpenIdConnectUserDetails implements UserDetails { - - private static final long serialVersionUID = 1L; - - private String userId; - private String username; - private OAuth2AccessToken token; - - public OpenIdConnectUserDetails(Map userInfo, OAuth2AccessToken token) { - this.userId = userInfo.get("sub"); - this.username = userInfo.get("email"); - this.token = token; - } - - @Override - public String getUsername() { - return username; - } - - @Override - public Collection getAuthorities() { - return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public OAuth2AccessToken getToken() { - return token; - } - - public void setToken(OAuth2AccessToken token) { - this.token = token; - } - - public void setUsername(String username) { - this.username = username; - } - - @Override - public String getPassword() { - return null; - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } - -} diff --git a/spring-security-modules/spring-security-openid/src/main/resources/application.properties b/spring-security-modules/spring-security-openid/src/main/resources/application.properties deleted file mode 100644 index 49022bf280..0000000000 --- a/spring-security-modules/spring-security-openid/src/main/resources/application.properties +++ /dev/null @@ -1,8 +0,0 @@ -server.port=8081 -google.clientId=TODO -google.clientSecret=TODO -google.accessTokenUri=https://www.googleapis.com/oauth2/v3/token -google.userAuthorizationUri=https://accounts.google.com/o/oauth2/auth -google.redirectUri=http://localhost:8081/google-login -google.issuer=accounts.google.com -google.jwkUrl=https://www.googleapis.com/oauth2/v2/certs \ No newline at end of file diff --git a/spring-security-modules/spring-security-openid/src/main/resources/logback.xml b/spring-security-modules/spring-security-openid/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/spring-security-modules/spring-security-openid/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/spring-security-modules/spring-security-openid/src/test/java/org/baeldung/SpringContextTest.java b/spring-security-modules/spring-security-openid/src/test/java/org/baeldung/SpringContextTest.java deleted file mode 100644 index fa346b2b31..0000000000 --- a/spring-security-modules/spring-security-openid/src/test/java/org/baeldung/SpringContextTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.baeldung; - -import org.baeldung.config.SpringOpenidApplication; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = SpringOpenidApplication.class) -public class SpringContextTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -}