This topic describes the related configurations of some commonly used SDKs of Open Authorization (OAuth). In this topic, configurations by using Spring Boot and OAuth 2.0 are provided.
Prerequisites
An OAuth application is created. For more information, see Manage an OAuth application.
A Spring Boot application is created. For more information, see Spring Boot.
Modify configuration files
Modify the following configuration files. For more information, see Spring Boot and OAuth2.
Create the core configuration file application.yml or application.yaml in the src/main/resources directory of a Spring Boot project. The following sample code provides a configuration example:
spring: security: oauth2: client: registration: alibabacloud: client-id: 415195082384692**** client-secret: 6EwN4qutnZuchG6n677Ie33SsjAhwyTpcOMSoIo6v0gqJtw4QcHhERVXfqzc**** client-authentication-method: client_secret_basic authorization-grant-type: authorization_code redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" client-name: alibabacloud provider: alibabacloud: authorization-uri: https://signin.alibabacloud.com/oauth2/v1/auth token-uri: https://oauth.alibabacloud.com/v1/token user-info-uri: https://oauth.alibabacloud.com/v1/userinfo user-name-attribute: sub jwk-set-uri: https://oauth.alibabacloud.com/v1/keys
Add the following dependencies to the pom.xml file:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.18</version> <relativePath /> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>4.3.1</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator-core</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>js-cookie</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> </dependencies>
Complete sample code
Backend code
Deploy a secure Web application based on the Spring Security backend framework that incorporates authentication, authorization, error handling, and cross-site request forgery (CSRF) protection. In the following example, the RESTful API controller WebApplication is defined. The controller processes HTTP requests and is integrated with the OAuth 2.0 authentication system.
The private variable handler is defined as an AuthenticationEntryPointFailureHandler instance and is used to handle failures at the authentication entry point. When a user attempts to access a page that requires authentication but authentication fails, the handler sets the HTTP status code to 401 and returns the "Unauthorized" error message.
The WebApplication class provides a GET mapping to the
/user
path. If a GET request is sent to the /user path, the method specified in the GET mapping is called.The method receives an OAuth2User object as a parameter. The OAuth2User object represents the OAuth2 information of the authenticated user. Then, the method returns a Map object that contains the username. The username is obtained from the attributes of the OAuth2User object.
In the configure method of the WebApplication class, the HttpSecurity object is configured to implement the security policy for the web application. In the HttpSecurity object, paths that allow anonymous access are configured, including
/
,/error
, andwebjars
. In the HttpSecurity object, identity authentication for requests to access the other paths is also configured. Thus, only authenticated users can access the paths.In the configure method, error handling is configured. If an error occurs because a user is unauthorized, the 401 status code is returned, and the defined variable handler is used to handle the authentication failure. In the configure method, the OAuth2 logon feature is configured to handle logon failures. If logon fails, an error message is configured in the user session, and the handler is called to handle the failure.
In the configure method, the logout feature is configured. If a user logs out, the user is redirected to
/
. All users can log out.In the configure method, CSRF protection is configured. CookieCsrfTokenRepository is used to store CSRF tokens, and the HttpOnly attribute is disabled to improve security. An additional GET mapping to the error method is configured to handle error requests. The error method obtains error messages from the user session and removes the error messages before the error messages are returned. This way, the error messages are not repeatedly displayed to users.
import org.springframework.boot.SpringApplication; import org.springframework.http.HttpStatus; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler; import org.springframework.security.web.authentication.HttpStatusEntryPoint; import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.web.bind.annotation.GetMapping; import javax.servlet.http.HttpServletRequest; import java.util.Collections; import java.util.Map; public class WebApplication extends WebSecurityConfigurerAdapter { private AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler((request, response, authException) -> response.sendError(401, "Unauthorized")); @GetMapping("/user") public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) { return Collections.singletonMap("name", principal.getAttribute("name")); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests(a -> a .antMatchers("/", "/error", "/webjars/**").permitAll() .anyRequest().authenticated() ) .exceptionHandling(e -> e .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)) ) .oauth2Login(o -> o .failureHandler((request, response, exception) -> { request.getSession().setAttribute("error.message", exception.getMessage()); handler.onAuthenticationFailure(request, response, exception); }) ) .logout(l -> l .logoutSuccessUrl("/").permitAll() ) .csrf(c -> c .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) ); } @GetMapping("/error") public String error(HttpServletRequest request) { String message = (String) request.getSession().getAttribute("error.message"); if (message != null) { request.getSession().removeAttribute("error.message"); } return message; } }
Frontend code
Create the index.html file in the src/main/resources/static directory of the project for verification. The following sample code provides a configuration example:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>Demo</title>
<meta name="description" content=""/>
<meta name="viewport" content="width=device-width"/>
<base href="/"/>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css"/>
<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
<script src="/webjars/js-cookie/js.cookie.js">
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (settings.type === 'POST' || settings.type === 'PUT' || settings.type === 'DELETE') {
if (!(/^(http:\/\/|https:\/\/)/.test(settings.url))) {
xhr.setRequestHeader("X-XSRF-TOKEN", Cookies.get('XSRF-TOKEN'));
}
}
}
});
</script>
</head>
<body>
<h1>Demo</h1>
<div class="container text-danger error"></div>
<script>
$.get("/error", function (data) {
if (data) {
$(".error").html(data);
} else {
$(".error").html('');
}
});
</script>
<div class="container unauthenticated">
With Aliyun: <a href="/oauth2/authorization/aliyun">click here</a>
</div>
<div class="container authenticated">
With Google: <a href="/oauth2/authorization/google">click here</a>
</div>
<script type="text/javascript">
$.get("/user", function(data) {
$("#user").html(data.name);
$(".unauthenticated").hide()
$(".authenticated").show()
});
</script>
<div class="container authenticated">
Logged in as: <span id="user"></span>
<div>
<button onClick="logout()" class="btn btn-primary">Logout</button>
</div>
</div>
<script type="text/javascript">
var logout = function() {
$.post("/logout", function() {
$("#user").html('');
$(".unauthenticated").show();
$(".authenticated").hide();
})
return true;
}
</script>
</body>
</html>
Verification
Run the sample codes and access http://localhost:8080
in a browser after the project starts.