How to Add a Confirmation Step to Spring Boot 2 OAuth2 Authorization Flow
This guide explains why Spring Boot 2’s OAuth2 authorization code flow skips the user‑approval page, walks through the relevant source code, and shows how to customize the confirmation and login pages, configure controllers and security settings, and verify the changes with tests.
Problem Overview
In the OAuth2 authorization code flow, after entering correct credentials the user is redirected directly to the redirect_uri without seeing a confirmation page, even when the auto‑approval setting is set to false.
Investigation of Spring Security Code
The AuthorizationEndpoint class is examined. First, the extractScopes method retrieves all scopes for the client and stores them in an AuthorizationRequest object. Then the checkForPreApproval method compares the scopes from the request with the client’s stored scopes. Because they match, the framework automatically marks the request as approved, resetting the auto‑approval flag to true and bypassing the confirmation step.
Customizing the Confirmation Page
To force a user‑approval step, the source is modified to keep the auto‑approval flag false. A custom HTML page is created (Thymeleaf template) to display the client ID and an "Agree/Authorize" button.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>授权确认</title>
<link rel="stylesheet" th:href="@{/resources/bootstrap/css/bootstrap.min.css}" />
<style type="text/css">
/* simplified CSS omitted for brevity */
</style>
</head>
<body>
<div class="loginContainer">
<div class="pageTitle"><h3>授权确认</h3></div>
<div class="loginPanel">
<div class="loginTitle">
<p th:text="'客户端:' + ${clientId} + ' 请求授权'"></p>
</div>
<div class="loginContent">
<form method="post" action="/oauth/authorize">
<input type="hidden" name="user_oauth_approval" value="true">
<button class="btn btn-sm btn-primary" type="submit">同意/授权</button>
</form>
</div>
</div>
</div>
<script th:src="@{/resources/jquery/jquery.min.js}"></script>
<script th:src="@{/resources/bootstrap/bootstrap.min.js}"></script>
</body>
</html>A corresponding controller returns this view:
@Controller
@SessionAttributes("authorizationRequest")
public class GrantController {
@RequestMapping("/custom/confirm_access")
public ModelAndView getAccessConfirmation(Map<String, Object> model) {
AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get("authorizationRequest");
ModelAndView view = new ModelAndView();
view.setViewName("grant-page");
view.addObject("clientId", authorizationRequest.getClientId());
return view;
}
}Mapping the Custom Page
The core security configuration is updated to map the custom confirmation endpoint:
Custom Login Page
A simple login page is also created to replace the default Spring Security login form, along with a controller that returns the view name:
@Controller
public class LoginController {
@RequestMapping("/sign/login")
public String login() {
return "login";
}
}The login HTML (Thymeleaf) contains fields for username and password and displays error messages when authentication fails.
Security Configuration
The WebSecurityConfig class extends WebSecurityConfigurerAdapter and:
Disables CSRF.
Permits access to the custom login URLs.
Requires authentication for all other requests.
Configures form‑login to use the custom login page.
Sets session management with a maximum of one concurrent session.
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/sign/login", "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/sign/login")
.permitAll()
.and()
.logout()
.logoutUrl("/sign/logout")
.invalidateHttpSession(true)
.and()
.sessionManagement()
.maximumSessions(1);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
}Testing the Changes
After redeploying, logging in redirects to the custom confirmation page, allowing the user to explicitly approve the client. The same flow works for the custom login page. Screenshots in the original article confirm successful navigation to the confirmation screen and final completion of the OAuth2 authorization code flow.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
