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:
Anshul Bansal 2020-05-26 18:58:17 +03:00 committed by GitHub
parent 745d71b127
commit 7b53c3cb55
10 changed files with 460 additions and 0 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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