diff --git a/pom.xml b/pom.xml index 508a8f5bb6..9bf12725c0 100644 --- a/pom.xml +++ b/pom.xml @@ -146,6 +146,7 @@ spring-5-reactive spring-5-mvc + spring-5-security spring-activiti spring-akka spring-amqp diff --git a/spring-5-security/pom.xml b/spring-5-security/pom.xml new file mode 100644 index 0000000000..c0f73b1bdd --- /dev/null +++ b/spring-5-security/pom.xml @@ -0,0 +1,95 @@ + + 4.0.0 + com.baeldung + spring-5-security + 0.0.1-SNAPSHOT + jar + + spring-5-security + spring 5 security sample project + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.M7 + + + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + org.springframework.security + spring-security-oauth2-client + + + org.springframework.security + spring-security-oauth2-jose + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.apache.maven.plugins + maven-surefire-plugin + + 3 + true + methods + true + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + UTF-8 + UTF-8 + 1.8 + + \ No newline at end of file diff --git a/spring-5-security/src/main/java/com/baeldung/oauth2/LoginController.java b/spring-5-security/src/main/java/com/baeldung/oauth2/LoginController.java new file mode 100644 index 0000000000..5d6c13bb0e --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/oauth2/LoginController.java @@ -0,0 +1,75 @@ +package com.baeldung.oauth2; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ResolvableType; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.client.RestTemplate; + +@Controller +public class LoginController { + + private static final String authorizationRequestBaseUri = "oauth2/authorize-client"; + Map oauth2AuthenticationUrls = new HashMap<>(); + + @Autowired + private ClientRegistrationRepository clientRegistrationRepository; + @Autowired + private OAuth2AuthorizedClientService authorizedClientService; + + @GetMapping("/oauth_login") + public String getLoginPage(Model model) { + Iterable clientRegistrations = null; + ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository) + .as(Iterable.class); + if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) { + clientRegistrations = (Iterable) clientRegistrationRepository; + } + + clientRegistrations.forEach(registration -> oauth2AuthenticationUrls.put(registration.getClientName(), authorizationRequestBaseUri + "/" + registration.getRegistrationId())); + model.addAttribute("urls", oauth2AuthenticationUrls); + + return "oauth_login"; + } + + @GetMapping("/loginSuccess") + public String getLoginInfo(Model model, OAuth2AuthenticationToken authentication) { + + OAuth2AuthorizedClient client = authorizedClientService.loadAuthorizedClient(authentication.getAuthorizedClientRegistrationId(), authentication.getName()); + + String userInfoEndpointUri = client.getClientRegistration() + .getProviderDetails() + .getUserInfoEndpoint() + .getUri(); + + if (!StringUtils.isEmpty(userInfoEndpointUri)) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + client.getAccessToken() + .getTokenValue()); + + HttpEntity entity = new HttpEntity("", headers); + + ResponseEntity response = restTemplate.exchange(userInfoEndpointUri, HttpMethod.GET, entity, Map.class); + Map userAttributes = response.getBody(); + model.addAttribute("name", userAttributes.get("name")); + } + + return "loginSuccess"; + } + +} diff --git a/spring-5-security/src/main/java/com/baeldung/oauth2/MvcConfig.java b/spring-5-security/src/main/java/com/baeldung/oauth2/MvcConfig.java new file mode 100644 index 0000000000..07d783b63d --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/oauth2/MvcConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.oauth2; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class MvcConfig implements WebMvcConfigurer { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("securedPage"); + registry.addViewController("loginFailure"); + } +} diff --git a/spring-5-security/src/main/java/com/baeldung/oauth2/SecurityConfig.java b/spring-5-security/src/main/java/com/baeldung/oauth2/SecurityConfig.java new file mode 100644 index 0000000000..b45f325767 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/oauth2/SecurityConfig.java @@ -0,0 +1,102 @@ +package com.baeldung.oauth2; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.oauth2.client.CommonOAuth2Provider; +import org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient; +import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; +import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; +import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; + +@Configuration +@PropertySource("application-oauth2.properties") +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers("/oauth_login", "/loginFailure", "/") + .permitAll() + .anyRequest() + .authenticated() + .and() + .oauth2Login() + .loginPage("/oauth_login") + .authorizationEndpoint() + .baseUri("/oauth2/authorize-client") + .authorizationRequestRepository(authorizationRequestRepository()) + .and() + .tokenEndpoint() + .accessTokenResponseClient(accessTokenResponseClient()) + .and() + .defaultSuccessUrl("/loginSuccess") + .failureUrl("/loginFailure"); + } + + @Bean + public AuthorizationRequestRepository authorizationRequestRepository() { + return new HttpSessionOAuth2AuthorizationRequestRepository(); + } + + @Bean + public OAuth2AccessTokenResponseClient accessTokenResponseClient() { + return new NimbusAuthorizationCodeTokenResponseClient(); + } + + + // additional configuration for non-Spring Boot projects + private static List clients = Arrays.asList("google", "facebook"); + + //@Bean + public ClientRegistrationRepository clientRegistrationRepository() { + List registrations = clients.stream() + .map(c -> getRegistration(c)) + .filter(registration -> registration != null) + .collect(Collectors.toList()); + + return new InMemoryClientRegistrationRepository(registrations); + } + + private static String CLIENT_PROPERTY_KEY = "spring.security.oauth2.client.registration."; + + @Autowired + private Environment env; + + private ClientRegistration getRegistration(String client) { + String clientId = env.getProperty(CLIENT_PROPERTY_KEY + client + ".client-id"); + + if (clientId == null) { + return null; + } + + String clientSecret = env.getProperty(CLIENT_PROPERTY_KEY + client + ".client-secret"); + if (client.equals("google")) { + return CommonOAuth2Provider.GOOGLE.getBuilder(client) + .clientId(clientId) + .clientSecret(clientSecret) + .build(); + } + if (client.equals("facebook")) { + return CommonOAuth2Provider.FACEBOOK.getBuilder(client) + .clientId(clientId) + .clientSecret(clientSecret) + .build(); + } + return null; + } + +} diff --git a/spring-5-security/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java b/spring-5-security/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java new file mode 100644 index 0000000000..557c23b368 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.oauth2; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringOAuthApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringOAuthApplication.class, args); + } + +} diff --git a/spring-5-security/src/main/resources/application-oauth2.properties b/spring-5-security/src/main/resources/application-oauth2.properties new file mode 100644 index 0000000000..5365bf8542 --- /dev/null +++ b/spring-5-security/src/main/resources/application-oauth2.properties @@ -0,0 +1,5 @@ +spring.security.oauth2.client.registration.google.client-id=368238083842-3d4gc7p54rs6bponn0qhn4nmf6apf24a.apps.googleusercontent.com +spring.security.oauth2.client.registration.google.client-secret=2RM2QkEaf3A8-iCNqSfdG8wP + +spring.security.oauth2.client.registration.facebook.client-id=151640435578187 +spring.security.oauth2.client.registration.facebook.client-secret=3724fb293d401245b1ce7b2d70e97571 \ No newline at end of file diff --git a/spring-5-security/src/main/resources/application.properties b/spring-5-security/src/main/resources/application.properties new file mode 100644 index 0000000000..ccec014c2b --- /dev/null +++ b/spring-5-security/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port=8081 + +logging.level.root=INFO \ No newline at end of file diff --git a/spring-5-security/src/main/resources/templates/index.html b/spring-5-security/src/main/resources/templates/index.html new file mode 100644 index 0000000000..4216d74037 --- /dev/null +++ b/spring-5-security/src/main/resources/templates/index.html @@ -0,0 +1,11 @@ + + + + Home + + + + Home + Welcome! + + \ No newline at end of file diff --git a/spring-5-security/src/main/resources/templates/loginFailure.html b/spring-5-security/src/main/resources/templates/loginFailure.html new file mode 100644 index 0000000000..75007a9aec --- /dev/null +++ b/spring-5-security/src/main/resources/templates/loginFailure.html @@ -0,0 +1,10 @@ + + + + Login Failure + + + + Login Failure + + \ No newline at end of file diff --git a/spring-5-security/src/main/resources/templates/loginSuccess.html b/spring-5-security/src/main/resources/templates/loginSuccess.html new file mode 100644 index 0000000000..3923297d03 --- /dev/null +++ b/spring-5-security/src/main/resources/templates/loginSuccess.html @@ -0,0 +1,16 @@ + + + + Login Success + + + + +

+
+ Welcome, user! +
+

+ + \ No newline at end of file diff --git a/spring-5-security/src/main/resources/templates/oauth_login.html b/spring-5-security/src/main/resources/templates/oauth_login.html new file mode 100644 index 0000000000..7017d2a75c --- /dev/null +++ b/spring-5-security/src/main/resources/templates/oauth_login.html @@ -0,0 +1,22 @@ + + + + +Oauth2 Login + + + + +
+
+

Login with:

+
+

+ Client +

+
+
+
+ + \ No newline at end of file diff --git a/spring-5-security/src/main/resources/templates/securedPage.html b/spring-5-security/src/main/resources/templates/securedPage.html new file mode 100644 index 0000000000..8fb5986a36 --- /dev/null +++ b/spring-5-security/src/main/resources/templates/securedPage.html @@ -0,0 +1,10 @@ + + + + +Secured Page + + +Secured Page - Welcome + + \ No newline at end of file diff --git a/spring-mvc-push/src/main/java/com/baeldung/controller/PushController.java b/spring-mvc-push/src/main/java/com/baeldung/controller/PushController.java index efee3a840f..c4698fe976 100644 --- a/spring-mvc-push/src/main/java/com/baeldung/controller/PushController.java +++ b/spring-mvc-push/src/main/java/com/baeldung/controller/PushController.java @@ -3,28 +3,22 @@ package com.baeldung.controller; import javax.servlet.http.PushBuilder; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.GetMapping; @Controller public class PushController { - @RequestMapping(value = "/demoWithPush") + @GetMapping(path = "/demoWithPush") public String demoWithPush(PushBuilder pushBuilder) { if (null != pushBuilder) { pushBuilder.path("resources/logo.png") .addHeader("Content-Type", "image/png") .push(); - pushBuilder.path("resources/script.js") - .addHeader("Content-Type", "text/javascript") - .push(); - pushBuilder.path("resources/style.css") - .addHeader("Content-Type", "text/css") - .push(); } return "demo"; } - @RequestMapping(value = "/demoWithoutPush") + @GetMapping(path = "/demoWithoutPush") public String demoWithoutPush() { return "demo"; } diff --git a/spring-mvc-push/src/main/webapp/WEB-INF/views/demo.jsp b/spring-mvc-push/src/main/webapp/WEB-INF/views/demo.jsp index d77619283a..28b27322ae 100644 --- a/spring-mvc-push/src/main/webapp/WEB-INF/views/demo.jsp +++ b/spring-mvc-push/src/main/webapp/WEB-INF/views/demo.jsp @@ -1,22 +1,18 @@ <%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8"%> + pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> PushBuilder demo -" rel="stylesheet" /> - - PushBuilder demo -
- " alt="Logo" height="126" - width="411"> -
- -
Go to - index + PushBuilder demo +
+ " alt="Logo" + height="126" width="411"> +
+
Go to + index \ No newline at end of file