BAEL-3996_Spring_Security_with_Auth0 (#9300)
* BAEL-3996 - Spring Security with Auth0 * BAEL-3996 - Spring Security with Auth0 code fixes * BAEL-3996 - Spring Security with Auth0 * BAEL-3996 - removed spaces * BAEL-3996 - RequestMapping is updated to GetMapping
This commit is contained in:
parent
745d71b127
commit
7b53c3cb55
|
@ -15,6 +15,7 @@
|
|||
|
||||
<modules>
|
||||
<module>spring-security-acl</module>
|
||||
<module>spring-security-auth0</module>
|
||||
<module>spring-security-angular/server</module>
|
||||
<module>spring-security-cache-control</module>
|
||||
<module>spring-security-core</module>
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-auth0</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>spring-security-auth0</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-resource-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>mvc-auth-commons</artifactId>
|
||||
<version>${mvc-auth-commons.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>${json.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-security-auth0</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<addResources>true</addResources>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<json.version>20190722</json.version>
|
||||
<mvc-auth-commons.version>1.2.0</mvc-auth-commons.version>
|
||||
</properties>
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.auth0;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package com.baeldung.auth0;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
|
||||
import com.auth0.AuthenticationController;
|
||||
import com.baeldung.auth0.controller.LogoutController;
|
||||
import com.auth0.jwk.JwkProvider;
|
||||
import com.auth0.jwk.JwkProviderBuilder;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class AuthConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Value(value = "${com.auth0.domain}")
|
||||
private String domain;
|
||||
|
||||
@Value(value = "${com.auth0.clientId}")
|
||||
private String clientId;
|
||||
|
||||
@Value(value = "${com.auth0.clientSecret}")
|
||||
private String clientSecret;
|
||||
|
||||
@Value(value = "${com.auth0.managementApi.clientId}")
|
||||
private String managementApiClientId;
|
||||
|
||||
@Value(value = "${com.auth0.managementApi.clientSecret}")
|
||||
private String managementApiClientSecret;
|
||||
|
||||
@Value(value = "${com.auth0.managementApi.grantType}")
|
||||
private String grantType;
|
||||
|
||||
@Bean
|
||||
public LogoutSuccessHandler logoutSuccessHandler() {
|
||||
return new LogoutController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationController authenticationController() throws UnsupportedEncodingException {
|
||||
JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
|
||||
return AuthenticationController.newBuilder(domain, clientId, clientSecret)
|
||||
.withJwkProvider(jwkProvider)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.csrf().disable();
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/callback", "/login", "/").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginPage("/login")
|
||||
.and()
|
||||
.logout().logoutSuccessHandler(logoutSuccessHandler()).permitAll();
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
public String getManagementApiClientId() {
|
||||
return managementApiClientId;
|
||||
}
|
||||
|
||||
public String getManagementApiClientSecret() {
|
||||
return managementApiClientSecret;
|
||||
}
|
||||
|
||||
public String getGrantType() {
|
||||
return grantType;
|
||||
}
|
||||
|
||||
public String getUserInfoUrl() {
|
||||
return "https://" + getDomain() + "/userinfo";
|
||||
}
|
||||
|
||||
public String getUsersUrl() {
|
||||
return "https://" + getDomain() + "/api/v2/users";
|
||||
}
|
||||
|
||||
public String getUsersByEmailUrl() {
|
||||
return "https://" + getDomain() + "/api/v2/users-by-email?email=";
|
||||
}
|
||||
|
||||
public String getLogoutUrl() {
|
||||
return "https://" + getDomain() +"/v2/logout";
|
||||
}
|
||||
|
||||
public String getContextPath(HttpServletRequest request) {
|
||||
String path = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
|
||||
return path;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package com.baeldung.auth0.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.auth0.AuthenticationController;
|
||||
import com.auth0.IdentityVerificationException;
|
||||
import com.auth0.Tokens;
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.baeldung.auth0.AuthConfig;
|
||||
|
||||
@Controller
|
||||
public class AuthController {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationController authenticationController;
|
||||
|
||||
@Autowired
|
||||
private AuthConfig config;
|
||||
|
||||
private static final String AUTH0_TOKEN_URL = "https://dev-example.auth0.com/oauth/token";
|
||||
|
||||
@GetMapping(value = "/login")
|
||||
protected void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
String redirectUri = config.getContextPath(request) + "/callback";
|
||||
String authorizeUrl = authenticationController.buildAuthorizeUrl(request, response, redirectUri)
|
||||
.withScope("openid email")
|
||||
.build();
|
||||
response.sendRedirect(authorizeUrl);
|
||||
}
|
||||
|
||||
@GetMapping(value="/callback")
|
||||
public void callback(HttpServletRequest request, HttpServletResponse response) throws IOException, IdentityVerificationException {
|
||||
Tokens tokens = authenticationController.handle(request, response);
|
||||
|
||||
DecodedJWT jwt = JWT.decode(tokens.getIdToken());
|
||||
TestingAuthenticationToken authToken2 = new TestingAuthenticationToken(jwt.getSubject(), jwt.getToken());
|
||||
authToken2.setAuthenticated(true);
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authToken2);
|
||||
response.sendRedirect(config.getContextPath(request) + "/");
|
||||
}
|
||||
|
||||
public String getManagementApiToken() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("client_id", config.getManagementApiClientId());
|
||||
requestBody.put("client_secret", config.getManagementApiClientSecret());
|
||||
requestBody.put("audience", "https://dev-example.auth0.com/api/v2/");
|
||||
requestBody.put("grant_type", config.getGrantType());
|
||||
|
||||
HttpEntity<String> request = new HttpEntity<String>(requestBody.toString(), headers);
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
HashMap<String, String> result = restTemplate.postForObject(AUTH0_TOKEN_URL, request, HashMap.class);
|
||||
|
||||
return result.get("access_token");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.baeldung.auth0.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
|
||||
@Controller
|
||||
public class HomeController {
|
||||
|
||||
@GetMapping(value = "/")
|
||||
@ResponseBody
|
||||
public String home(HttpServletRequest request, HttpServletResponse response, final Authentication authentication) throws IOException {
|
||||
|
||||
if (authentication!= null && authentication instanceof TestingAuthenticationToken) {
|
||||
TestingAuthenticationToken token = (TestingAuthenticationToken) authentication;
|
||||
|
||||
DecodedJWT jwt = JWT.decode(token.getCredentials().toString());
|
||||
String email = jwt.getClaims().get("email").asString();
|
||||
|
||||
return "Welcome, " + email + "!";
|
||||
} else {
|
||||
response.sendRedirect("http://localhost:8080/login");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.baeldung.auth0.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import com.baeldung.auth0.AuthConfig;
|
||||
|
||||
@Controller
|
||||
public class LogoutController implements LogoutSuccessHandler {
|
||||
|
||||
@Autowired
|
||||
private AuthConfig config;
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse res, Authentication authentication) {
|
||||
if (req.getSession() != null) {
|
||||
req.getSession().invalidate();
|
||||
}
|
||||
String returnTo = config.getContextPath(req);
|
||||
String logoutUrl = config.getLogoutUrl() + "?client_id=" + config.getClientId() + "&returnTo=" +returnTo;
|
||||
try {
|
||||
res.sendRedirect(logoutUrl);
|
||||
} catch(IOException e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.baeldung.auth0.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.auth0.IdentityVerificationException;
|
||||
import com.baeldung.auth0.AuthConfig;
|
||||
import com.baeldung.auth0.service.ApiService;
|
||||
|
||||
@Controller
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
private ApiService apiService;
|
||||
|
||||
@Autowired
|
||||
private AuthConfig config;
|
||||
|
||||
@GetMapping(value="/users")
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> users(HttpServletRequest request, HttpServletResponse response) throws IOException, IdentityVerificationException {
|
||||
ResponseEntity<String> result = apiService.getCall(config.getUsersUrl());
|
||||
return result;
|
||||
}
|
||||
|
||||
@GetMapping(value = "/userByEmail")
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> userByEmail(HttpServletResponse response, @RequestParam String email) {
|
||||
ResponseEntity<String> result = apiService.getCall(config.getUsersByEmailUrl()+email);
|
||||
return result;
|
||||
}
|
||||
|
||||
@GetMapping(value = "/createUser")
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> createUser(HttpServletResponse response) {
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("email", "norman.lewis@email.com");
|
||||
request.put("given_name", "Norman");
|
||||
request.put("family_name", "Lewis");
|
||||
request.put("connection", "Username-Password-Authentication");
|
||||
request.put("password", "Pa33w0rd");
|
||||
|
||||
ResponseEntity<String> result = apiService.postCall(config.getUsersUrl(), request.toString());
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.auth0.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.baeldung.auth0.controller.AuthController;
|
||||
|
||||
@Service
|
||||
public class ApiService {
|
||||
|
||||
@Autowired
|
||||
private AuthController controller;
|
||||
|
||||
public ResponseEntity<String> getCall(String url) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", "Bearer "+controller.getManagementApiToken());
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<String>(headers);
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResponseEntity<String> postCall(String url, String requestBody) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", "Bearer "+controller.getManagementApiToken());
|
||||
|
||||
HttpEntity<String> request = new HttpEntity<String>(requestBody, headers);
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
ResponseEntity<String> result = restTemplate.postForEntity(url, request, String.class);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
com.auth0.domain: dev-example.auth0.com
|
||||
com.auth0.clientId: exampleClientId
|
||||
com.auth0.clientSecret: exampleClientSecret
|
||||
|
||||
com.auth0.managementApi.clientId: exampleManagementApiClientId
|
||||
com.auth0.managementApi.clientSecret: exampleManagementApiClientSecret
|
||||
com.auth0.managementApi.grantType: client_credentials
|
Loading…
Reference in New Issue