{"id":1590,"date":"2023-10-10T18:59:56","date_gmt":"2023-10-10T18:59:56","guid":{"rendered":"https:\/\/www.w3computing.com\/articles\/?p=1590"},"modified":"2023-10-10T18:59:59","modified_gmt":"2023-10-10T18:59:59","slug":"implementing-oauth2-with-spring-security-in-java","status":"publish","type":"post","link":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/","title":{"rendered":"Implementing OAuth2 with Spring Security in Java"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth2, or Open Authorization 2.0, is a standard protocol for authorization. While it&#8217;s often mistakenly referred to as an authentication protocol, its primary job is to delegate permissions. Here\u2019s a simple analogy: imagine giving the keys to your home to a trusted friend to water your plants. Instead of giving them the main key, you give them a temporary pass that only grants access to your living room and expires after a set period. OAuth2 operates similarly, but for applications. It allows third-party services to use account information without exposing user passwords, using what is termed as &#8220;access tokens&#8221;. These tokens grant specific permissions (or scopes) and have an expiration time, ensuring that permissions are limited and temporary.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Significance of Spring Security with OAuth2<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Spring, a prominent framework in the Java ecosystem, is known for its comprehensive set of tools to build enterprise-grade applications. Among its vast toolbox, Spring Security stands out as a powerful module designed to provide authentication and authorization features seamlessly. When Spring Security and OAuth2 come together, it\u2019s like joining two powerhouses.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Ease of Integration<\/strong>: Spring Security offers first-class support for OAuth2, making it relatively straightforward for developers to integrate OAuth2 into their Spring applications.<\/li>\n\n\n\n<li><strong>Flexibility and Configurability<\/strong>: Developers can fine-tune security configurations, customize token responses, and more, catering to the diverse and ever-evolving needs of modern applications.<\/li>\n\n\n\n<li><strong>Scalability<\/strong>: With Spring&#8217;s underlying architecture, it becomes easier to scale OAuth2 implementations, making it fit for small to large applications.<\/li>\n\n\n\n<li><strong>Community and Support<\/strong>: Given the widespread adoption of Spring, a vast community is available. This means ample resources, constant updates, and prompt solutions to common challenges.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding OAuth2<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth2, which stands for Open Authorization version 2, is an authorization framework that enables third-party applications to obtain limited access to user accounts on HTTP services. It is used by several web services like Google, Facebook, and GitHub to provide token-based authentication to apps. Before implementing OAuth2, it&#8217;s essential to understand its foundational components.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">OAuth2 Protocol Flow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth2 follows a specific flow, depending on the grant type in use, but the general process includes:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Request for Authorization<\/strong>: A client application requests authorization from the resource owner (typically the user) to access their protected resources.<\/li>\n\n\n\n<li><strong>Granting Permission<\/strong>: The user consents to the client&#8217;s request.<\/li>\n\n\n\n<li><strong>Obtaining an Access Token<\/strong>: With the user\u2019s authorization grant, the client requests an access token from the authorization server.<\/li>\n\n\n\n<li><strong>Accessing the Resource<\/strong>: Using the access token, the client can access the protected resources from the resource server until the token expires or is revoked.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Roles in OAuth2<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth2 defines four primary roles:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Resource Owner<\/strong>: Typically the end-user who grants permission to access their protected resources. They authorize or deny client applications&#8217; requests.<\/li>\n\n\n\n<li><strong>Client<\/strong>: This is the application requesting access to the user&#8217;s account. It could be a web app, a mobile app, or any other third-party application.<\/li>\n\n\n\n<li><strong>Authorization Server<\/strong>: This server authenticates the resource owner and issues access tokens after obtaining proper authorization. In the context of our tutorial, our Spring application will act as this server.<\/li>\n\n\n\n<li><strong>Resource Server<\/strong>: This server hosts the user&#8217;s protected resources. It&#8217;s capable of accepting and responding to protected resource requests using access tokens.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">OAuth2 Grant Types<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Grant types determine how a client application gets an access token. Different scenarios or applications require different grant types:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Authorization Code<\/strong>: This is the most common flow, especially for server-side applications. Here, the client redirects the user to the authorization server to authenticate. Upon successful authentication, the user is redirected back to the client with an authorization code. The client then exchanges this code for an access token.<\/li>\n\n\n\n<li><strong>Implicit<\/strong>: This was primarily designed for browser-based or mobile apps. Unlike the Authorization Code flow, it returns the access token directly without requiring an intermediate authorization code. However, it&#8217;s considered less secure and is used less frequently nowadays.<\/li>\n\n\n\n<li><strong>Password (Resource Owner Password Credentials)<\/strong>: In this flow, the user provides their service credentials (username &amp; password) directly to the application, which then uses these credentials to obtain an access token. It&#8217;s suitable for trusted clients.<\/li>\n\n\n\n<li><strong>Client Credentials<\/strong>: Here, the client authenticates itself with the authorization server and gets a token directly. It\u2019s used for server-to-server authentication where no user interaction is required.<\/li>\n\n\n\n<li><strong>Refresh Token<\/strong>: This isn&#8217;t precisely a separate grant type but rather accompanies other tokens. It&#8217;s used to obtain a new access token without forcing the user to re-authenticate, especially handy when the access token has a short lifespan.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Setting Up a Spring Boot Application<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before implementing OAuth2 with Spring Security, you need to set up a basic Spring Boot application. Let\u2019s walk through the process.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating a new Spring Boot project<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">There are multiple ways to set up a new Spring Boot project, but the easiest and most commonly used method is via <strong>Spring Initializr<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Go to <a href=\"https:\/\/start.spring.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Spring Initializr<\/a>.<\/li>\n\n\n\n<li>Choose your preferred build tool: Maven or Gradle.<\/li>\n\n\n\n<li>Select the Spring Boot version. If unsure, the latest stable release is typically a good choice.<\/li>\n\n\n\n<li>Fill in the &#8216;Project Metadata&#8217;:\n<ul class=\"wp-block-list\">\n<li><strong>Group<\/strong>: Typically represents your organization. Example: <code>com.example<\/code><\/li>\n\n\n\n<li><strong>Artifact<\/strong>: Represents the name of your project. Example: <code>oauth2springsecurity<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Under the &#8216;Dependencies&#8217; section, add basic dependencies for web apps, such as <code>Spring Web<\/code> and <code>Spring Security<\/code>. We&#8217;ll add OAuth2-related dependencies in the next step.<\/li>\n\n\n\n<li>Click on the <code>Generate<\/code> button. This action will download a <code>.zip<\/code> file containing the skeleton of your Spring Boot application.<\/li>\n\n\n\n<li>Extract the downloaded <code>.zip<\/code> file to your workspace and open it in your preferred IDE (e.g., IntelliJ IDEA or Eclipse).<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Adding necessary dependencies (Maven\/Gradle)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now, let&#8217;s add the required OAuth2 dependencies. Depending on your build tool, follow the instructions below:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>For Maven (<code>pom.xml<\/code>):<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Add the following dependencies to your <code>pom.xml<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-comment\">&lt;!-- Spring Security OAuth2 Dependency --&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.security.oauth.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-security-oauth2-autoconfigure<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>2.5.5<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-comment\">&lt;!-- OAuth2 JWT (if you'll be using JWT tokens) --&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.security.oauth<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-security-oauth2-jose<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then, update your project dependencies. In most IDEs, you can do this by right-clicking on the project and selecting an option similar to &#8216;Reload Project&#8217; or &#8216;Update Project&#8217;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>For Gradle (<code>build.gradle<\/code>):<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Add the following dependencies to your <code>build.gradle<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Gradle\" data-shcb-language-slug=\"gradle\"><span><code class=\"hljs language-gradle\"><span class=\"hljs-comment\">\/\/ Spring Security OAuth2 Dependency<\/span>\r\nimplementation <span class=\"hljs-string\">'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.5.5'<\/span>\r\n\r\n<span class=\"hljs-comment\">\/\/ OAuth2 JWT (if you'll be using JWT tokens)<\/span>\r\nimplementation <span class=\"hljs-string\">'org.springframework.security.oauth:spring-security-oauth2-jose'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Gradle<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">gradle<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">After adding the dependencies, refresh your Gradle project. In IDEs like IntelliJ IDEA, you can do this by clicking on the refresh icon in the Gradle sidebar.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring Spring Security and OAuth2<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Configuring Spring Security with OAuth2 requires a series of steps. Let\u2019s break down the process:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Integration of Spring Security with Spring Boot:<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Once you&#8217;ve added the <code>Spring Security<\/code> and <code>OAuth2<\/code> dependencies, Spring Boot will automatically apply certain default security configurations. However, to tailor it to our OAuth2 setup, we need to make some custom configurations.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Securing the Application<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The primary purpose of Spring Security is to protect our application. By default, all endpoints will be protected. For our OAuth2 setup, let&#8217;s create a configuration class to specify which endpoints require authentication and which grant types our application supports.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableWebSecurity<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SecurityConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">WebSecurityConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    <span class=\"hljs-keyword\">private<\/span> DataSource dataSource;\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        http\r\n            .csrf().disable() <span class=\"hljs-comment\">\/\/ Disabling CSRF protection for simplicity<\/span>\r\n            .authorizeRequests()\r\n                .antMatchers(<span class=\"hljs-string\">\"\/public\/**\"<\/span>).permitAll() <span class=\"hljs-comment\">\/\/ Public endpoints<\/span>\r\n                .anyRequest().authenticated() <span class=\"hljs-comment\">\/\/ All other endpoints require authentication<\/span>\r\n            .and()\r\n            .oauth2Login(); <span class=\"hljs-comment\">\/\/ Enabling OAuth2 login<\/span>\r\n    }\r\n\r\n    <span class=\"hljs-comment\">\/\/ If using JDBC token store, configure the authentication manager builder<\/span>\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">globalUserDetails<\/span><span class=\"hljs-params\">(AuthenticationManagerBuilder auth)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        auth.jdbcAuthentication().dataSource(dataSource);\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">OAuth2 Authorization Server Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">While the authorization process can be handled by third-party services like Google or Facebook, if you&#8217;re setting up your own authorization server, you&#8217;d need a configuration somewhat like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableAuthorizationServer<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AuthorizationServerConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">AuthorizationServerConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    <span class=\"hljs-keyword\">private<\/span> AuthenticationManager authenticationManager;\r\n\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    <span class=\"hljs-keyword\">private<\/span> DataSource dataSource;\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(ClientDetailsServiceConfigurer clients)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        clients.jdbc(dataSource)\r\n            .withClient(<span class=\"hljs-string\">\"your-client-id\"<\/span>)\r\n            .secret(<span class=\"hljs-string\">\"{noop}your-client-secret\"<\/span>)\r\n            .scopes(<span class=\"hljs-string\">\"read\"<\/span>, <span class=\"hljs-string\">\"write\"<\/span>)\r\n            .authorizedGrantTypes(<span class=\"hljs-string\">\"password\"<\/span>, <span class=\"hljs-string\">\"refresh_token\"<\/span>, <span class=\"hljs-string\">\"authorization_code\"<\/span>)\r\n            .accessTokenValiditySeconds(<span class=\"hljs-number\">3600<\/span>); <span class=\"hljs-comment\">\/\/ Token validity<\/span>\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(AuthorizationServerEndpointsConfigurer endpoints)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        endpoints\r\n            .authenticationManager(authenticationManager)\r\n            .tokenStore(jdbcTokenStore());\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Bean<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> TokenStore <span class=\"hljs-title\">jdbcTokenStore<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> JdbcTokenStore(dataSource);\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This configuration defines your OAuth2 authorization server using a JDBC backend for storing tokens. The client details (like client-id and secret) are also stored in the database.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">OAuth2 Resource Server Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Once you&#8217;ve set up the Authorization server, you need to configure the resource server where your protected resources are.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableResourceServer<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ResourceServerConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">ResourceServerConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        http\r\n            .authorizeRequests()\r\n                .antMatchers(<span class=\"hljs-string\">\"\/public\/**\"<\/span>).permitAll() <span class=\"hljs-comment\">\/\/ Public endpoints<\/span>\r\n                .anyRequest().authenticated() <span class=\"hljs-comment\">\/\/ All other endpoints require authentication<\/span>\r\n            .and()\r\n            .exceptionHandling().accessDeniedHandler(<span class=\"hljs-keyword\">new<\/span> OAuth2AccessDeniedHandler());\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Adding OAuth2 dependency<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Adding the OAuth2 dependency to your Spring Boot project is straightforward. However, please note that the traditional OAuth2 setup has evolved. The Spring Security team now recommends using the native OAuth2 support in Spring Security instead of the older Spring Security OAuth project.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s how to add the necessary dependencies:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Maven<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re using Maven, add the following dependencies to your <code>pom.xml<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-comment\">&lt;!-- Spring Security OAuth2 Client --&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-oauth2-client<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-comment\">&lt;!-- Spring Security OAuth2 Resource Server (if you plan to set up a resource server) --&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-oauth2-resource-server<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-comment\">&lt;!-- OAuth2 JOSE (handles JSON Web Tokens) --&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.security<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-security-oauth2-jose<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Gradle<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re using Gradle, add the following dependencies to your <code>build.gradle<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Gradle\" data-shcb-language-slug=\"gradle\"><span><code class=\"hljs language-gradle\"><span class=\"hljs-comment\">\/\/ Spring Security OAuth2 Client<\/span>\r\nimplementation <span class=\"hljs-string\">'org.springframework.boot:spring-boot-starter-oauth2-client'<\/span>\r\n\r\n<span class=\"hljs-comment\">\/\/ Spring Security OAuth2 Resource Server (if you plan to set up a resource server)<\/span>\r\nimplementation <span class=\"hljs-string\">'org.springframework.boot:spring-boot-starter-oauth2-resource-server'<\/span>\r\n\r\n<span class=\"hljs-comment\">\/\/ OAuth2 JOSE (handles JSON Web Tokens)<\/span>\r\nimplementation <span class=\"hljs-string\">'org.springframework.security:spring-security-oauth2-jose'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Gradle<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">gradle<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">After adding these dependencies, your Spring Boot project will be equipped with the necessary libraries to support OAuth2 integration using Spring Security.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Basic configuration in <code>application.properties<\/code> or <code>application.yml<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Configuring your Spring Boot application for OAuth2 integration can be done through either the <code>application.properties<\/code> or the <code>application.yml<\/code> file. These files are typically located in the <code>src\/main\/resources<\/code> directory of your project.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ll provide configuration snippets for both formats:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>application.properties<\/code> Configuration<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Properties\" data-shcb-language-slug=\"properties\"><span><code class=\"hljs language-properties\"><span class=\"hljs-comment\"># Server port<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">server.port<\/span>=<span class=\"hljs-string\">8080<\/span><span class=\"hljs-attr\">\r<\/span><span class=\"hljs-comment\">\n\r\n# Database settings (assuming you're using a database)<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.datasource.url<\/span>=<span class=\"hljs-string\">jdbc:mysql:\/\/localhost:3306\/mydb<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.datasource.username<\/span>=<span class=\"hljs-string\">dbuser<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.datasource.password<\/span>=<span class=\"hljs-string\">dbpass<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.datasource.driver-class-name<\/span>=<span class=\"hljs-string\">com.mysql.cj.jdbc.Driver<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.jpa.hibernate.ddl-auto<\/span>=<span class=\"hljs-string\">update<\/span><span class=\"hljs-attr\">\r<\/span><span class=\"hljs-comment\">\n\r\n# OAuth2 client configurations (e.g., for Google login)<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.client-id<\/span>=<span class=\"hljs-string\">YOUR_CLIENT_ID<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.client-secret<\/span>=<span class=\"hljs-string\">YOUR_CLIENT_SECRET<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.access-token-uri<\/span>=<span class=\"hljs-string\">https:\/\/www.googleapis.com\/oauth2\/v4\/token<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.user-authorization-uri<\/span>=<span class=\"hljs-string\">https:\/\/accounts.google.com\/o\/oauth2\/auth<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.client-authentication-scheme<\/span>=<span class=\"hljs-string\">form<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.scope<\/span>=<span class=\"hljs-string\">profile,email<\/span><span class=\"hljs-attr\">\r<\/span><span class=\"hljs-comment\">\n\r\n# OAuth2 resource server configurations<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.resource.user-info-uri<\/span>=<span class=\"hljs-string\">https:\/\/www.googleapis.com\/userinfo\/v2\/me<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.resource.jwt.key-value<\/span>=<span class=\"hljs-string\">YOUR_JWT_KEY<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Properties<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">properties<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><code>application.yml<\/code> Configuration<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">server:<\/span>\r\n  <span class=\"hljs-attr\">port:<\/span> <span class=\"hljs-number\">8080<\/span>\r\n\r\n<span class=\"hljs-attr\">spring:<\/span>\r\n  <span class=\"hljs-attr\">datasource:<\/span>\r\n    <span class=\"hljs-attr\">url:<\/span> <span class=\"hljs-string\">jdbc:mysql:\/\/localhost:3306\/mydb<\/span>\r\n    <span class=\"hljs-attr\">username:<\/span> <span class=\"hljs-string\">dbuser<\/span>\r\n    <span class=\"hljs-attr\">password:<\/span> <span class=\"hljs-string\">dbpass<\/span>\r\n    <span class=\"hljs-attr\">driver-class-name:<\/span> <span class=\"hljs-string\">com.mysql.cj.jdbc.Driver<\/span>\r\n  <span class=\"hljs-attr\">jpa:<\/span>\r\n    <span class=\"hljs-attr\">hibernate:<\/span>\r\n      <span class=\"hljs-attr\">ddl-auto:<\/span> <span class=\"hljs-string\">update<\/span>\r\n\r\n<span class=\"hljs-attr\">security:<\/span>\r\n  <span class=\"hljs-attr\">oauth2:<\/span>\r\n    <span class=\"hljs-attr\">client:<\/span>\r\n      <span class=\"hljs-attr\">client-id:<\/span> <span class=\"hljs-string\">YOUR_CLIENT_ID<\/span>\r\n      <span class=\"hljs-attr\">client-secret:<\/span> <span class=\"hljs-string\">YOUR_CLIENT_SECRET<\/span>\r\n      <span class=\"hljs-attr\">access-token-uri:<\/span> <span class=\"hljs-string\">https:\/\/www.googleapis.com\/oauth2\/v4\/token<\/span>\r\n      <span class=\"hljs-attr\">user-authorization-uri:<\/span> <span class=\"hljs-string\">https:\/\/accounts.google.com\/o\/oauth2\/auth<\/span>\r\n      <span class=\"hljs-attr\">client-authentication-scheme:<\/span> <span class=\"hljs-string\">form<\/span>\r\n      <span class=\"hljs-attr\">scope:<\/span>\r\n        <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">profile<\/span>\r\n        <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">email<\/span>\r\n    <span class=\"hljs-attr\">resource:<\/span>\r\n      <span class=\"hljs-attr\">user-info-uri:<\/span> <span class=\"hljs-string\">https:\/\/www.googleapis.com\/userinfo\/v2\/me<\/span>\r\n      <span class=\"hljs-attr\">jwt:<\/span>\r\n        <span class=\"hljs-attr\">key-value:<\/span> <span class=\"hljs-string\">YOUR_JWT_KEY<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Replace placeholders like <code>YOUR_CLIENT_ID<\/code>, <code>YOUR_CLIENT_SECRET<\/code>, and <code>YOUR_JWT_KEY<\/code> with appropriate values for your application. The above example uses Google as the OAuth2 provider, but similar configurations apply to other providers. You just need to adjust the endpoints (<code>access-token-uri<\/code>, <code>user-authorization-uri<\/code>, <code>user-info-uri<\/code>) and other configurations as necessary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Additionally, the database configurations are provided assuming you might store some user or token information in a database. Adjust them according to your application&#8217;s needs or remove them if not relevant.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Remember that while these configurations get you started, depending on your project&#8217;s requirements, you might need additional configurations or adjustments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementing the Authorization Server<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Defining the Authorization Server Config class<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Implementing the Authorization Server in a Spring Boot application requires extending the <code>AuthorizationServerConfigurerAdapter<\/code> and overriding its methods to provide the necessary configurations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s how you can define the Authorization Server Config class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.beans.factory.annotation.Autowired;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Configuration;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.authentication.AuthenticationManager;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.provider.token.TokenStore;\r\n\r\n<span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableAuthorizationServer<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AuthorizationServerConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">AuthorizationServerConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    <span class=\"hljs-keyword\">private<\/span> TokenStore tokenStore;\r\n\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    <span class=\"hljs-keyword\">private<\/span> AuthenticationManager authenticationManager;\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(ClientDetailsServiceConfigurer clients)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        clients.inMemory()\r\n                .withClient(<span class=\"hljs-string\">\"my-client-id\"<\/span>)\r\n                .secret(<span class=\"hljs-string\">\"{noop}my-secret\"<\/span>)  <span class=\"hljs-comment\">\/\/ {noop} is a prefix indicating that the provided password is not encoded.<\/span>\r\n                .authorizedGrantTypes(<span class=\"hljs-string\">\"authorization_code\"<\/span>, <span class=\"hljs-string\">\"refresh_token\"<\/span>, <span class=\"hljs-string\">\"password\"<\/span>)\r\n                .scopes(<span class=\"hljs-string\">\"read\"<\/span>, <span class=\"hljs-string\">\"write\"<\/span>)\r\n                .accessTokenValiditySeconds(<span class=\"hljs-number\">3600<\/span>)  <span class=\"hljs-comment\">\/\/ Token validity<\/span>\r\n                .refreshTokenValiditySeconds(<span class=\"hljs-number\">86400<\/span>);  <span class=\"hljs-comment\">\/\/ Refresh token validity<\/span>\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(AuthorizationServerEndpointsConfigurer endpoints)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        endpoints\r\n                .tokenStore(tokenStore)\r\n                .authenticationManager(authenticationManager);\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Some points to note:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <code>@EnableAuthorizationServer<\/code> annotation signals Spring that this class will be used for the OAuth2 Authorization Server setup.<\/li>\n\n\n\n<li>We&#8217;re using an <code>inMemory<\/code> client store in this example for simplicity, which means the client details are hardcoded and stored in memory. In real-world applications, it&#8217;s common to use a JDBC or another persistent store to manage client details.<\/li>\n\n\n\n<li>The <code>{noop}<\/code> prefix in the client secret indicates that the password is in plain text and not encoded. In real-world scenarios, you should use a password encoder like BCrypt and store encoded secrets.<\/li>\n\n\n\n<li><code>authorizedGrantTypes<\/code> are the grant types your authorization server will support. Depending on your application, you may support fewer or more grant types.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Configuring clients, scopes, and grant types<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Configuring clients, scopes, and grant types is a fundamental aspect of setting up an OAuth2 Authorization Server. This involves specifying which client applications can use the server, what kind of operations they can perform (scopes), and through which methods they can acquire tokens (grant types).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an in-depth breakdown and a sample code snippet for configuring clients using the <code>ClientDetailsServiceConfigurer<\/code> in the <code>AuthorizationServerConfigurerAdapter<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;\r\n\r\n<span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableAuthorizationServer<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AuthorizationServerConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">AuthorizationServerConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-comment\">\/\/ Other configurations ...<\/span>\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(ClientDetailsServiceConfigurer clients)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        clients\r\n            .inMemory()  <span class=\"hljs-comment\">\/\/ Using in-memory storage for demonstration purposes<\/span>\r\n            .withClient(<span class=\"hljs-string\">\"client-app-1\"<\/span>)\r\n                .secret(<span class=\"hljs-string\">\"{noop}client-app-secret-1\"<\/span>) <span class=\"hljs-comment\">\/\/ {noop} prefix indicates the password isn't encoded<\/span>\r\n                .authorizedGrantTypes(<span class=\"hljs-string\">\"authorization_code\"<\/span>, <span class=\"hljs-string\">\"refresh_token\"<\/span>, <span class=\"hljs-string\">\"password\"<\/span>, <span class=\"hljs-string\">\"client_credentials\"<\/span>)\r\n                .scopes(<span class=\"hljs-string\">\"read\"<\/span>, <span class=\"hljs-string\">\"write\"<\/span>)\r\n                .accessTokenValiditySeconds(<span class=\"hljs-number\">3600<\/span>)\r\n                .redirectUris(<span class=\"hljs-string\">\"http:\/\/localhost:8082\/client-app-1\/login\/oauth2\/code\/\"<\/span>)\r\n            .and()\r\n            .withClient(<span class=\"hljs-string\">\"client-app-2\"<\/span>)\r\n                .secret(<span class=\"hljs-string\">\"{noop}client-app-secret-2\"<\/span>)\r\n                .authorizedGrantTypes(<span class=\"hljs-string\">\"authorization_code\"<\/span>, <span class=\"hljs-string\">\"refresh_token\"<\/span>)\r\n                .scopes(<span class=\"hljs-string\">\"read\"<\/span>)\r\n                .accessTokenValiditySeconds(<span class=\"hljs-number\">1800<\/span>)\r\n                .redirectUris(<span class=\"hljs-string\">\"http:\/\/localhost:8083\/client-app-2\/login\/oauth2\/code\/\"<\/span>);\r\n    }\r\n\r\n    <span class=\"hljs-comment\">\/\/ Other configurations ...<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Key aspects:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Storage<\/strong>: We&#8217;re using <code>inMemory()<\/code> for simplicity, which means the client details are stored in memory. In real-world scenarios, it&#8217;s common to use <code>.jdbc()<\/code> or another persistent store.<\/li>\n\n\n\n<li><strong>Client Details<\/strong>:\n<ul class=\"wp-block-list\">\n<li><code>withClient()<\/code>: Specifies the client id.<\/li>\n\n\n\n<li><code>secret()<\/code>: Specifies the client&#8217;s secret key.<\/li>\n\n\n\n<li><code>authorizedGrantTypes()<\/code>: Defines which grant types this client supports.<\/li>\n\n\n\n<li><code>scopes()<\/code>: Indicates the operations or actions the client is allowed to perform.<\/li>\n\n\n\n<li><code>accessTokenValiditySeconds()<\/code>: Sets the validity of the access token in seconds.<\/li>\n\n\n\n<li><code>redirectUris()<\/code>: Defines the callback URIs for the client.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Multiple Clients<\/strong>: You can chain configurations for multiple clients, making it easy to manage several clients with one configuration class.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Remember that in a production environment:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Client secrets should be stored securely, often hashed using an algorithm like BCrypt.<\/li>\n\n\n\n<li>Persistent storage (e.g., a database) is more suitable than in-memory storage for client details.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Setting up the token store and token enhancements<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The token store is essential in an OAuth2 setup as it determines where the tokens (both access and refresh tokens) will be stored. Additionally, token enhancements allow customizing the claims or attributes of a generated token. Here&#8217;s how you can set up both:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Setting Up the Token Store<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">There are several options for token stores in Spring:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>InMemoryTokenStore<\/strong>: Stores tokens in memory.<\/li>\n\n\n\n<li><strong>JdbcTokenStore<\/strong>: Stores tokens in a relational database.<\/li>\n\n\n\n<li><strong>JwtTokenStore<\/strong>: Doesn&#8217;t actually store tokens since JWTs are self-contained, but it can read the data out of them.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">For our example, let&#8217;s use the <code>JdbcTokenStore<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, make sure you have added the required dependencies. If using Maven:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-data-jpa<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.security.oauth<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-security-oauth2<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n\r\n<span class=\"hljs-comment\">&lt;!-- Include the JDBC driver for your database (e.g., H2, MySQL, PostgreSQL) --&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then, configure the token store in your <code>AuthorizationServerConfig<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Autowired<\/span>\r\n<span class=\"hljs-keyword\">private<\/span> DataSource dataSource;\r\n\r\n<span class=\"hljs-meta\">@Bean<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> TokenStore <span class=\"hljs-title\">tokenStore<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> JdbcTokenStore(dataSource);\r\n}\r\n\r\n<span class=\"hljs-meta\">@Override<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(AuthorizationServerEndpointsConfigurer endpoints)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n    endpoints\r\n        .tokenStore(tokenStore())\r\n        <span class=\"hljs-comment\">\/\/ other configurations...<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Token Enhancements<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Token enhancements allow you to customize the attributes (claims) of the token. A common use case is adding custom user attributes or roles to the token.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s how you can set up token enhancements using a <code>TokenEnhancer<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.common.OAuth2AccessToken;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.provider.OAuth2Authentication;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.provider.token.TokenEnhancer;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CustomTokenEnhancer<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">TokenEnhancer<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> OAuth2AccessToken <span class=\"hljs-title\">enhance<\/span><span class=\"hljs-params\">(OAuth2AccessToken accessToken, OAuth2Authentication authentication)<\/span> <\/span>{\r\n        Map&lt;String, Object&gt; additionalInfo = <span class=\"hljs-keyword\">new<\/span> HashMap&lt;&gt;();\r\n        \r\n        <span class=\"hljs-comment\">\/\/ Add custom attributes (e.g., user roles, user id, etc.)<\/span>\r\n        additionalInfo.put(<span class=\"hljs-string\">\"customAttribute\"<\/span>, <span class=\"hljs-string\">\"customValue\"<\/span>);\r\n        \r\n        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);\r\n        <span class=\"hljs-keyword\">return<\/span> accessToken;\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then, wire up the token enhancer in your <code>AuthorizationServerConfig<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Bean<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> TokenEnhancer <span class=\"hljs-title\">tokenEnhancer<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> CustomTokenEnhancer();\r\n}\r\n\r\n<span class=\"hljs-meta\">@Override<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(AuthorizationServerEndpointsConfigurer endpoints)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n    TokenEnhancerChain enhancerChain = <span class=\"hljs-keyword\">new<\/span> TokenEnhancerChain();\r\n    enhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));\r\n    endpoints\r\n        .tokenEnhancer(enhancerChain)\r\n        .tokenStore(tokenStore());\r\n        <span class=\"hljs-comment\">\/\/ other configurations...<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">By combining the token store and token enhancements, you ensure that your OAuth2 setup is not only securely storing tokens but also providing the necessary claims to make authorization decisions or convey user attributes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementing the Resource Server<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Defining the Resource Server Config class<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Resource Server is responsible for serving resources (like RESTful endpoints) that are protected by OAuth2 tokens. The <code>ResourceServerConfigurerAdapter<\/code> is an essential class to set up and configure the Resource Server in Spring Security with OAuth2.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a simple example of defining the Resource Server Config class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Configuration;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.config.annotation.web.builders.HttpSecurity;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;\r\n\r\n<span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableResourceServer<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ResourceServerConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">ResourceServerConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        http\r\n            .anonymous().disable()  <span class=\"hljs-comment\">\/\/ Disable anonymous access<\/span>\r\n            .authorizeRequests()\r\n                .antMatchers(<span class=\"hljs-string\">\"\/api\/**\"<\/span>).authenticated()  <span class=\"hljs-comment\">\/\/ Only authenticated requests can access \/api\/** endpoints<\/span>\r\n            .and()\r\n            .exceptionHandling().accessDeniedHandler(<span class=\"hljs-keyword\">new<\/span> OAuth2AccessDeniedHandler());  <span class=\"hljs-comment\">\/\/ Handle access denied exceptions<\/span>\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s break down the configuration:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>@EnableResourceServer<\/strong>: This annotation is crucial. It signals that this configuration is for setting up a resource server.<\/li>\n\n\n\n<li><strong>configure(HttpSecurity http)<\/strong>:\n<ul class=\"wp-block-list\">\n<li><strong>anonymous().disable()<\/strong>: Disables anonymous access to all endpoints. This means every request must be authenticated.<\/li>\n\n\n\n<li><strong>authorizeRequests().antMatchers(&#8220;\/api\/<\/strong>&#8220;).authenticated()**: Specifies that all requests to <code>\/api\/**<\/code> endpoints require authentication.<\/li>\n\n\n\n<li><strong>exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler())<\/strong>: Ensures that if access is denied, the <code>OAuth2AccessDeniedHandler<\/code> is invoked. This handler will produce a 403 Forbidden response by default when access is denied.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This is a basic configuration to get you started. Depending on your needs, you might have to configure additional rules, CORS settings, or other security measures.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Securing specific endpoints<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Securing specific endpoints in a Spring Boot application is typically done using the <code>HttpSecurity<\/code> object within a configuration class that extends <code>WebSecurityConfigurerAdapter<\/code> for general Spring Security, or <code>ResourceServerConfigurerAdapter<\/code> for OAuth2 Resource Servers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a guide on how to secure specific endpoints using both configurations:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">General Spring Security Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re using Spring Security without the OAuth2 context, the configuration might look like the following:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Configuration;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.config.annotation.web.builders.HttpSecurity;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\r\n\r\n<span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableWebSecurity<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WebSecurityConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">WebSecurityConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        http\r\n            .authorizeRequests()\r\n                .antMatchers(<span class=\"hljs-string\">\"\/\"<\/span>, <span class=\"hljs-string\">\"\/home\"<\/span>, <span class=\"hljs-string\">\"\/public\/**\"<\/span>).permitAll()   <span class=\"hljs-comment\">\/\/ Public endpoints<\/span>\r\n                .antMatchers(<span class=\"hljs-string\">\"\/admin\/**\"<\/span>).hasRole(<span class=\"hljs-string\">\"ADMIN\"<\/span>)            <span class=\"hljs-comment\">\/\/ Only users with ADMIN role can access \/admin\/** endpoints<\/span>\r\n                .antMatchers(<span class=\"hljs-string\">\"\/user\/**\"<\/span>).hasRole(<span class=\"hljs-string\">\"USER\"<\/span>)              <span class=\"hljs-comment\">\/\/ Only users with USER role can access \/user\/** endpoints<\/span>\r\n                .anyRequest().authenticated()                         <span class=\"hljs-comment\">\/\/ Any other endpoints require authentication<\/span>\r\n            .and()\r\n            .formLogin()                                             <span class=\"hljs-comment\">\/\/ Enable default form-based login<\/span>\r\n            .and()\r\n            .httpBasic();                                            <span class=\"hljs-comment\">\/\/ Enable HTTP basic authentication<\/span>\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">OAuth2 Resource Server Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re setting up an OAuth2 Resource Server, you&#8217;ll typically secure your endpoints based on the OAuth2 scopes or other attributes present in the OAuth2 token. Here&#8217;s how:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Configuration;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.config.annotation.web.builders.HttpSecurity;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;\r\n\r\n<span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableResourceServer<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ResourceServerConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">ResourceServerConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        http\r\n            .authorizeRequests()\r\n                .antMatchers(<span class=\"hljs-string\">\"\/public\/**\"<\/span>).permitAll()                      <span class=\"hljs-comment\">\/\/ Public endpoints<\/span>\r\n                .antMatchers(<span class=\"hljs-string\">\"\/api\/admin\/**\"<\/span>).access(<span class=\"hljs-string\">\"#oauth2.hasScope('write')\"<\/span>)   <span class=\"hljs-comment\">\/\/ Endpoints under \/api\/admin\/** require 'write' scope<\/span>\r\n                .antMatchers(<span class=\"hljs-string\">\"\/api\/user\/**\"<\/span>).access(<span class=\"hljs-string\">\"#oauth2.hasScope('read')\"<\/span>)     <span class=\"hljs-comment\">\/\/ Endpoints under \/api\/user\/** require 'read' scope<\/span>\r\n                .anyRequest().authenticated();                                 <span class=\"hljs-comment\">\/\/ All other endpoints need authentication<\/span>\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Remember that the <code>.access()<\/code> method allows you to provide a SpEL expression to specify access conditions based on attributes in the OAuth2 token.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Handling token validations<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Token validation is a critical aspect of any OAuth2 implementation. When a resource server receives a token, it must ensure the token is valid before allowing access to the protected resource. A token may be deemed invalid for several reasons:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Expiration<\/strong>: Most tokens, especially access tokens, are short-lived.<\/li>\n\n\n\n<li><strong>Tampering<\/strong>: If the token has been modified since its creation.<\/li>\n\n\n\n<li><strong>Scope<\/strong>: The token might not have the required scopes for the requested resource.<\/li>\n\n\n\n<li><strong>Revocation<\/strong>: The token might have been revoked, even if it hasn&#8217;t expired yet.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s how you can handle token validations in a Spring-based OAuth2 Resource Server:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Token Expiry and Structure Validation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For JWTs, the signature and expiration of the token are automatically validated by Spring Security if you&#8217;ve set up a <code>JwtTokenStore<\/code> and have provided the necessary JWT decoding keys.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For non-JWT tokens or JWT tokens where the resource server doesn&#8217;t have the necessary decoding key, the token&#8217;s validity needs to be checked with the Authorization Server. This often happens via a <code>\/check_token<\/code> endpoint provided by the Authorization Server.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Scope Validation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can check for token scope in Spring Security using the <code>#oauth2.hasScope<\/code> method in your endpoint security configuration:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">http\r\n    .authorizeRequests()\r\n        .antMatchers(<span class=\"hljs-string\">\"\/api\/write\/**\"<\/span>).access(<span class=\"hljs-string\">\"#oauth2.hasScope('write')\"<\/span>)\r\n        .antMatchers(<span class=\"hljs-string\">\"\/api\/read\/**\"<\/span>).access(<span class=\"hljs-string\">\"#oauth2.hasScope('read')\"<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Custom Token Validations<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">If you have more custom validation requirements, you can use a custom filter:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.security.core.context.SecurityContextHolder;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.provider.OAuth2Authentication;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CustomTokenValidationFilter<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">AbstractPreAuthenticatedProcessingFilter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> Object <span class=\"hljs-title\">getPreAuthenticatedPrincipal<\/span><span class=\"hljs-params\">(HttpServletRequest request)<\/span> <\/span>{\r\n        OAuth2Authentication authentication = (OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();\r\n        <span class=\"hljs-comment\">\/\/ Custom validation logic...<\/span>\r\n        <span class=\"hljs-comment\">\/\/ For instance: Check custom claims in the token<\/span>\r\n        <span class=\"hljs-comment\">\/\/ If token is invalid, throw an authentication exception<\/span>\r\n\r\n        <span class=\"hljs-keyword\">return<\/span> authentication.getPrincipal();\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> Object <span class=\"hljs-title\">getPreAuthenticatedCredentials<\/span><span class=\"hljs-params\">(HttpServletRequest request)<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">null<\/span>;\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Remember to add this filter to your security configuration:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Override<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n    http.addFilterBefore(<span class=\"hljs-keyword\">new<\/span> CustomTokenValidationFilter(), AbstractPreAuthenticatedProcessingFilter<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>)<\/span>;\r\n    <span class=\"hljs-comment\">\/\/ ... other configurations<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Token Revocation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For checking token revocation, the resource server typically needs to communicate with the Authorization Server. Implementing token revocation checks in every API call might lead to performance issues. Hence, caching strategies, like using a cache with a short TTL for valid tokens or a revocation list (blacklist) of revoked tokens, might be beneficial.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When handling token validations, performance considerations are crucial. Too much back-and-forth between servers can slow down an application, so strategies like caching valid tokens and JWTs (which are self-contained and don&#8217;t require server validation if the resource server can validate the signature) are often favored.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating an OAuth2 Client with Spring<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When you&#8217;re building an application that needs to access resources protected by OAuth2 tokens (from either your own or a third-party service), you act as an OAuth2 Client. Spring Security provides a convenient way to build such a client, with one of the essential classes being <code>OAuth2RestTemplate<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Role of OAuth2RestTemplate<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>OAuth2RestTemplate<\/code> is an extension of Spring&#8217;s <code>RestTemplate<\/code> that is tailored to simplify the consumption of OAuth2-protected resources. It handles the complete OAuth2 flow, from obtaining an access token to refreshing it when necessary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Some primary responsibilities and benefits of <code>OAuth2RestTemplate<\/code> are:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Token Management<\/strong>: It can automatically fetch, use, and refresh tokens when making requests to protected resources.<\/li>\n\n\n\n<li><strong>Token Storage<\/strong>: It uses <code>OAuth2ClientContext<\/code> to store tokens, ensuring that they&#8217;re reused across requests and refreshed when necessary.<\/li>\n\n\n\n<li><strong>Request Interception<\/strong>: Before making any request, <code>OAuth2RestTemplate<\/code> ensures that the <code>Authorization<\/code> header is populated with a valid access token.<\/li>\n\n\n\n<li><strong>Error Handling<\/strong>: It can handle OAuth2-specific errors and exceptions.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Creating an OAuth2 Client with OAuth2RestTemplate<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a step-by-step guide to setting up an OAuth2 Client with Spring using <code>OAuth2RestTemplate<\/code>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Add Dependencies<\/strong>: Add the necessary Spring OAuth2 dependencies to your project. For Maven:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.security.oauth.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-security-oauth2-autoconfigure<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>2.5.5<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Configure Client Details<\/strong>: In your <code>application.properties<\/code> or <code>application.yml<\/code>, configure the client details:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"Properties\" data-shcb-language-slug=\"properties\"><span><code class=\"hljs language-properties\"><span class=\"hljs-meta\">security.oauth2.client.client-id<\/span>=<span class=\"hljs-string\">YOUR_CLIENT_ID<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.client-secret<\/span>=<span class=\"hljs-string\">YOUR_CLIENT_SECRET<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.access-token-uri<\/span>=<span class=\"hljs-string\">YOUR_ACCESS_TOKEN_URI<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.user-authorization-uri<\/span>=<span class=\"hljs-string\">YOUR_USER_AUTHORIZATION_URI<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">security.oauth2.client.scope<\/span>=<span class=\"hljs-string\">required,scopes<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Properties<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">properties<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Create OAuth2RestTemplate Bean<\/strong>: Define the <code>OAuth2RestTemplate<\/code> bean in one of your configuration classes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Bean;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Configuration;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.client.OAuth2ClientContext;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.client.OAuth2RestTemplate;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;\r\n\r\n<span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">OAuth2ClientConfig<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Bean<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> OAuth2RestTemplate <span class=\"hljs-title\">oauth2RestTemplate<\/span><span class=\"hljs-params\">(OAuth2ClientContext context,\r\n                                                 AuthorizationCodeResourceDetails details)<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> OAuth2RestTemplate(details, context);\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Use OAuth2RestTemplate<\/strong>: You can now autowire and use the <code>OAuth2RestTemplate<\/code> in your service or controller classes to make requests:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Autowired<\/span>\r\n<span class=\"hljs-keyword\">private<\/span> OAuth2RestTemplate restTemplate;\r\n\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">fetchProtectedResource<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n    String resourceUrl = <span class=\"hljs-string\">\"https:\/\/example.com\/api\/protected-endpoint\"<\/span>;\r\n    <span class=\"hljs-keyword\">return<\/span> restTemplate.getForObject(resourceUrl, String<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>)<\/span>;\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">With these steps, you&#8217;ve set up an OAuth2 client in your Spring application that can seamlessly access OAuth2-protected resources. The <code>OAuth2RestTemplate<\/code> will handle the intricacies of the OAuth2 flow, token management, and request authorization, simplifying the process for developers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Client application setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Setting up a client application involves creating an application that will use the OAuth2 framework to authenticate and, optionally, authorize access to resources either in the same application or a separate one (usually a resource server).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a step-by-step guide on setting up an OAuth2 client application using Spring Boot and Spring Security:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Dependencies<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Ensure you have the necessary dependencies in your project. Using Maven, the main dependencies would be:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-security<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-oauth2-client<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Properties Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In your <code>application.properties<\/code> or <code>application.yml<\/code>, you&#8217;ll need to configure the details of your OAuth2 client:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"Properties\" data-shcb-language-slug=\"properties\"><span><code class=\"hljs language-properties\"><span class=\"hljs-comment\"># OAuth2 client configuration<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.registration.my-oauth-provider.client-id<\/span>=<span class=\"hljs-string\">YOUR_CLIENT_ID<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.registration.my-oauth-provider.client-secret<\/span>=<span class=\"hljs-string\">YOUR_CLIENT_SECRET<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.registration.my-oauth-provider.redirect-uri-template<\/span>=<span class=\"hljs-string\">{baseUrl}\/login\/oauth2\/code\/{registrationId}<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.registration.my-oauth-provider.authorization-grant-type<\/span>=<span class=\"hljs-string\">authorization_code<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.registration.my-oauth-provider.scope<\/span>=<span class=\"hljs-string\">profile,email<\/span><span class=\"hljs-attr\">\r<\/span><span class=\"hljs-comment\">\n\r\n# Provider details<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri<\/span>=<span class=\"hljs-string\">AUTHORIZATION_URI<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.provider.my-oauth-provider.token-uri<\/span>=<span class=\"hljs-string\">TOKEN_URI<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri<\/span>=<span class=\"hljs-string\">USER_INFO_URI<\/span><span class=\"hljs-attr\">\r<\/span>\n<span class=\"hljs-meta\">spring.security.oauth2.client.provider.my-oauth-provider.user-name-attribute<\/span>=<span class=\"hljs-string\">name<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Properties<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">properties<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Replace placeholders (<code>YOUR_CLIENT_ID<\/code>, <code>YOUR_CLIENT_SECRET<\/code>, and the URIs) with appropriate values from your OAuth2 authorization server.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Security Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Create a configuration class to specify the security setup:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableWebSecurity<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SecurityConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">WebSecurityConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        http\r\n            .authorizeRequests()\r\n                .antMatchers(<span class=\"hljs-string\">\"\/\"<\/span>, <span class=\"hljs-string\">\"\/home\"<\/span>, <span class=\"hljs-string\">\"\/public\/**\"<\/span>).permitAll()  <span class=\"hljs-comment\">\/\/ Open endpoints<\/span>\r\n                .anyRequest().authenticated()   <span class=\"hljs-comment\">\/\/ All other requests require authentication<\/span>\r\n            .and()\r\n            .oauth2Login()\r\n                .loginPage(<span class=\"hljs-string\">\"\/oauth2\/authorization\/my-oauth-provider\"<\/span>);  <span class=\"hljs-comment\">\/\/ Redirect to OAuth2 provider for login<\/span>\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Controller Setup<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Create a simple controller to test the authentication:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@RestController<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HomeController<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@GetMapping<\/span>(<span class=\"hljs-string\">\"\/\"<\/span>)\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">home<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Welcome to the home page!\"<\/span>;\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@GetMapping<\/span>(<span class=\"hljs-string\">\"\/secured\"<\/span>)\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">secured<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"You're authenticated and viewing a secured page!\"<\/span>;\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">After a successful OAuth2 authentication, trying to access <code>\/secured<\/code> will show the secured message, ensuring that the OAuth2 client setup is working correctly.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Run and Test<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Run your Spring Boot application. When you try to access any secured endpoint, you&#8217;ll be redirected to the OAuth2 provider&#8217;s login page. After a successful login, you&#8217;ll be redirected back to your application with an OAuth2 token, and you can access the secured resources.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Using @EnableOAuth2Sso for Single Sign-On (SSO)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Using the <code>@EnableOAuth2Sso<\/code> annotation in a Spring Boot application activates a pre-configured set of functionalities which turns your application into an OAuth2 client and facilitates Single Sign-On (SSO) with the configured OAuth2 Authorization Server. With Single Sign-On, users can authenticate once and gain access to multiple applications without being prompted to log in again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s how you can set up a Spring Boot OAuth2 client application with Single Sign-On using the <code>@EnableOAuth2Sso<\/code> annotation:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Dependencies<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Ensure you&#8217;ve added the necessary dependencies. With Maven, you&#8217;d include:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-security<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.security.oauth.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-security-oauth2-autoconfigure<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>2.5.5<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Properties Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In your <code>application.properties<\/code> or <code>application.yml<\/code>, you&#8217;ll configure the OAuth2 client details:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" data-shcb-language-name=\"Processing\" data-shcb-language-slug=\"processing\"><span><code class=\"hljs language-processing\"># OAuth2 SSO Configuration\r\nsecurity.oauth2.client.client-id=YOUR_CLIENT_ID\r\nsecurity.oauth2.client.client-secret=YOUR_CLIENT_SECRET\r\nsecurity.oauth2.client.access-token-uri=ACCESS_TOKEN_URI\r\nsecurity.oauth2.client.user-authorization-uri=USER_AUTHORIZATION_URI\r\nsecurity.oauth2.resource.user-info-uri=USER_INFO_URI<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Processing<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">processing<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Replace the placeholders with the appropriate details from your OAuth2 provider.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Main Application Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In your main application class (the one annotated with <code>@SpringBootApplication<\/code>), simply add the <code>@EnableOAuth2Sso<\/code> annotation:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@SpringBootApplication<\/span>\r\n<span class=\"hljs-meta\">@EnableOAuth<\/span>2Sso\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">OAuth2SsoClientApplication<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#91;] args)<\/span> <\/span>{\r\n        SpringApplication.run(OAuth2SsoClientApplication<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>, <span class=\"hljs-title\">args<\/span>)<\/span>;\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Security Configuration<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For a basic setup, <code>@EnableOAuth2Sso<\/code> will handle most of the heavy lifting. However, if you wish to customize the security configuration further, you can create a configuration class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableWebSecurity<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SecurityConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">WebSecurityConfigurerAdapter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        http\r\n            .antMatcher(<span class=\"hljs-string\">\"\/**\"<\/span>)\r\n            .authorizeRequests()\r\n                .antMatchers(<span class=\"hljs-string\">\"\/\"<\/span>, <span class=\"hljs-string\">\"\/login**\"<\/span>, <span class=\"hljs-string\">\"\/webjars\/**\"<\/span>, <span class=\"hljs-string\">\"\/error**\"<\/span>)\r\n                .permitAll()\r\n            .anyRequest()\r\n                .authenticated();\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This configuration ensures that the root path, login endpoints, webjars (for static resources), and error endpoints are publicly accessible, while all other paths require authentication.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Run and Test<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">With these configurations in place, when you access any secured endpoint of your application, you&#8217;ll be redirected to the OAuth2 provider&#8217;s login page. After authentication, you&#8217;ll be redirected back to your application. If you try accessing another application that&#8217;s also integrated with the same OAuth2 provider, you won&#8217;t be prompted for credentials again, demonstrating the Single Sign-On behavior.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Customizing Token Responses<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When dealing with OAuth2 tokens, especially JWTs, there are scenarios where you&#8217;d like to customize the token response. This can involve adding custom claims to the token or handling token expiration and refresh mechanisms in specific ways.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adding Custom Token Claims<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Claims are name-value pairs in the token that contain information about the user and the token. To add custom claims to the token, you&#8217;ll often use a <code>TokenEnhancer<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a sample code snippet demonstrating how you can create a custom token enhancer:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.common.OAuth2AccessToken;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.provider.OAuth2Authentication;\r\n<span class=\"hljs-keyword\">import<\/span> org.springframework.security.oauth2.provider.token.TokenEnhancer;\r\n\r\n<span class=\"hljs-keyword\">import<\/span> java.util.HashMap;\r\n<span class=\"hljs-keyword\">import<\/span> java.util.Map;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CustomTokenEnhancer<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">TokenEnhancer<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> OAuth2AccessToken <span class=\"hljs-title\">enhance<\/span><span class=\"hljs-params\">(OAuth2AccessToken accessToken, OAuth2Authentication authentication)<\/span> <\/span>{\r\n        Map&lt;String, Object&gt; additionalInfo = <span class=\"hljs-keyword\">new<\/span> HashMap&lt;&gt;();\r\n\r\n        <span class=\"hljs-comment\">\/\/ Add your custom claims here<\/span>\r\n        additionalInfo.put(<span class=\"hljs-string\">\"organization\"<\/span>, <span class=\"hljs-string\">\"ExampleCorp\"<\/span>);  <span class=\"hljs-comment\">\/\/ Static claim example<\/span>\r\n        additionalInfo.put(<span class=\"hljs-string\">\"user_id\"<\/span>, authentication.getName());  <span class=\"hljs-comment\">\/\/ Dynamic claim example<\/span>\r\n\r\n        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);\r\n        <span class=\"hljs-keyword\">return<\/span> accessToken;\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Handling Token Expiration and Refresh<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Token expiration and refresh mechanisms are crucial for security. Access tokens usually have short lifetimes, and refresh tokens can be used to obtain new access tokens without requiring the user to log in again.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Setting Token Lifetimes:<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You typically set the token lifetimes in the <code>AuthorizationServerConfigurerAdapter<\/code> configuration:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-35\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Override<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(ClientDetailsServiceConfigurer clients)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n    clients.inMemory()\r\n        .withClient(<span class=\"hljs-string\">\"your-client-id\"<\/span>)\r\n        .secret(<span class=\"hljs-string\">\"your-client-secret\"<\/span>)\r\n        <span class=\"hljs-comment\">\/\/ ... other configurations ...<\/span>\r\n        .accessTokenValiditySeconds(<span class=\"hljs-number\">3600<\/span>)  <span class=\"hljs-comment\">\/\/ 1 hour<\/span>\r\n        .refreshTokenValiditySeconds(<span class=\"hljs-number\">2592000<\/span>);  <span class=\"hljs-comment\">\/\/ 30 days<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-35\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Enabling Refresh Tokens:<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To enable the use of refresh tokens, ensure that you&#8217;ve added <code>\"refresh_token\"<\/code> to the list of authorized grant types for your client and configure the endpoints in <code>AuthorizationServerConfigurerAdapter<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Override<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(AuthorizationServerEndpointsConfigurer endpoints)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n    endpoints\r\n        .tokenStore(tokenStore())\r\n        .authenticationManager(authenticationManager)\r\n        .tokenEnhancer(tokenEnhancer())\r\n        .reuseRefreshTokens(<span class=\"hljs-keyword\">false<\/span>);  <span class=\"hljs-comment\">\/\/ This ensures a new refresh token is issued with every access token refresh request<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-36\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Securing RESTful APIs with OAuth2<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Securing RESTful APIs with OAuth2 ensures that only authenticated and authorized clients and users can access your API endpoints. This is typically achieved using Spring Security and its OAuth2 extensions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Protecting Specific Endpoints<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Using Spring Security&#8217;s <code>HttpSecurity<\/code>, you can easily protect specific endpoints. For instance, you can require that any request to the <code>\/api\/**<\/code> pattern should be authenticated.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Override<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">configure<\/span><span class=\"hljs-params\">(HttpSecurity http)<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n    http\r\n        .authorizeRequests()\r\n            .antMatchers(<span class=\"hljs-string\">\"\/public\/**\"<\/span>).permitAll()  <span class=\"hljs-comment\">\/\/ Open endpoints<\/span>\r\n            .antMatchers(<span class=\"hljs-string\">\"\/api\/**\"<\/span>).authenticated()  <span class=\"hljs-comment\">\/\/ API endpoints require authentication<\/span>\r\n        .and()\r\n        .oauth2ResourceServer().jwt();  <span class=\"hljs-comment\">\/\/ If you're using JWTs for tokens<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Role-Based Access with OAuth2<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Using roles, you can provide fine-grained access control to your RESTful APIs. For instance, only users with an <code>ADMIN<\/code> role might be allowed to access certain sensitive API endpoints.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>@PreAuthorize<\/code> annotation is a powerful tool that integrates with Spring&#8217;s method security, allowing you to protect individual methods based on roles or other conditions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s how you can use <code>@PreAuthorize<\/code> with roles:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Enable Global Method Security<\/strong>: First, you need to enable method-level security by adding <code>@EnableGlobalMethodSecurity<\/code> to a configuration class.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-38\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Configuration<\/span>\r\n<span class=\"hljs-meta\">@EnableWebSecurity<\/span>\r\n<span class=\"hljs-meta\">@EnableGlobalMethodSecurity<\/span>(prePostEnabled = <span class=\"hljs-keyword\">true<\/span>)\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SecurityConfig<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">WebSecurityConfigurerAdapter<\/span> <\/span>{\r\n    <span class=\"hljs-comment\">\/\/ ... other configurations ...<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-38\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Using @PreAuthorize with Roles<\/strong>: Protect specific methods using the <code>@PreAuthorize<\/code> annotation. Here are some code snippets illustrating its use:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-39\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@RestController<\/span>\r\n<span class=\"hljs-meta\">@RequestMapping<\/span>(<span class=\"hljs-string\">\"\/api\"<\/span>)\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SecureApiController<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@GetMapping<\/span>(<span class=\"hljs-string\">\"\/user\"<\/span>)\r\n    <span class=\"hljs-meta\">@PreAuthorize<\/span>(<span class=\"hljs-string\">\"hasRole('ROLE_USER')\"<\/span>)\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">userEndpoint<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"User-specific endpoint.\"<\/span>;\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@GetMapping<\/span>(<span class=\"hljs-string\">\"\/admin\"<\/span>)\r\n    <span class=\"hljs-meta\">@PreAuthorize<\/span>(<span class=\"hljs-string\">\"hasRole('ROLE_ADMIN')\"<\/span>)\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">adminEndpoint<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Admin-specific endpoint.\"<\/span>;\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-39\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">With the above configuration:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A call to <code>\/api\/user<\/code> will only be allowed if the authenticated user has the <code>ROLE_USER<\/code> role.<\/li>\n\n\n\n<li>A call to <code>\/api\/admin<\/code> will only be allowed if the authenticated user has the <code>ROLE_ADMIN<\/code> role.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The roles usually come from the OAuth2 token&#8217;s claims. You&#8217;d ensure that your Authorization Server sets these roles in the token during its creation, and your Resource Server (where the API resides) understands and uses them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing Your OAuth2 Implementation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Unit Tests with Spring Security Test<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To write unit tests around your security logic, you can utilize <code>spring-security-test<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, add the dependency:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-40\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.security<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-security-test<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>5.6.0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span> <span class=\"hljs-comment\">&lt;!-- Use the appropriate version --&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scope<\/span>&gt;<\/span>test<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">scope<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-40\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">With this, you can mock security behaviors in your unit tests:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-41\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@RunWith<\/span>(SpringRunner<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>)\r\n@<span class=\"hljs-title\">SpringBootTest<\/span>\r\n@<span class=\"hljs-title\">AutoConfigureMockMvc<\/span>\r\n<span class=\"hljs-title\">public<\/span> <span class=\"hljs-title\">class<\/span> <span class=\"hljs-title\">MyControllerTest<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    <span class=\"hljs-keyword\">private<\/span> MockMvc mockMvc;\r\n\r\n    <span class=\"hljs-meta\">@Test<\/span>\r\n    <span class=\"hljs-meta\">@WithMockUser<\/span>(username = <span class=\"hljs-string\">\"user\"<\/span>, roles = {<span class=\"hljs-string\">\"USER\"<\/span>})\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">testUserEndpoint<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        <span class=\"hljs-keyword\">this<\/span>.mockMvc.perform(get(<span class=\"hljs-string\">\"\/api\/user\"<\/span>))\r\n            .andExpect(status().isOk());\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Test<\/span>\r\n    <span class=\"hljs-meta\">@WithMockUser<\/span>(username = <span class=\"hljs-string\">\"admin\"<\/span>, roles = {<span class=\"hljs-string\">\"ADMIN\"<\/span>})\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">testAdminEndpoint<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        <span class=\"hljs-keyword\">this<\/span>.mockMvc.perform(get(<span class=\"hljs-string\">\"\/api\/admin\"<\/span>))\r\n            .andExpect(status().isOk());\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-41\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Here, <code>@WithMockUser<\/code> is used to simulate a user with a given username and roles for the span of the test method.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Integration Testing with OAuth2 Tokens<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Integration testing with OAuth2 often requires you to have an actual token. However, obtaining a real token from the Authorization Server for testing can be cumbersome and not always feasible. So, you can mock the OAuth2 authentication in tests:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Configure a Test Profile<\/strong>: Create an application-test.properties with properties for testing:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-42\" data-shcb-language-name=\"Processing\" data-shcb-language-slug=\"processing\"><span><code class=\"hljs language-processing\">spring.profiles.active=test\r\nsecurity.oauth2.resourceserver.jwt.jwk-<span class=\"hljs-built_in\">set<\/span>-uri=http:<span class=\"hljs-comment\">\/\/localhost:8080\/.well-known\/jwks.json<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-42\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Processing<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">processing<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Write Tests<\/strong>: Using <code>@ActiveProfiles(\"test\")<\/code>, activate the test profile, and mock the OAuth2 authentication:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-43\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@RunWith<\/span>(SpringRunner<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>)\r\n@<span class=\"hljs-title\">SpringBootTest<\/span>\r\n@<span class=\"hljs-title\">AutoConfigureMockMvc<\/span>\r\n@<span class=\"hljs-title\">ActiveProfiles<\/span>(\"<span class=\"hljs-title\">test<\/span>\")\r\n<span class=\"hljs-title\">public<\/span> <span class=\"hljs-title\">class<\/span> <span class=\"hljs-title\">MyControllerIntegrationTest<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Autowired<\/span>\r\n    <span class=\"hljs-keyword\">private<\/span> MockMvc mockMvc;\r\n\r\n    <span class=\"hljs-meta\">@Test<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">testUserEndpointWithToken<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> Exception <\/span>{\r\n        OAuth2AuthenticationToken authentication = ...; <span class=\"hljs-comment\">\/\/ create mock OAuth2AuthenticationToken<\/span>\r\n        SecurityContextHolder.getContext().setAuthentication(authentication);\r\n\r\n        <span class=\"hljs-keyword\">this<\/span>.mockMvc.perform(get(<span class=\"hljs-string\">\"\/api\/user\"<\/span>)\r\n            .with(authentication(authentication)))\r\n            .andExpect(status().isOk());\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-43\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">When setting up integration testing with OAuth2 tokens, there are more complexities, especially when the Authorization Server and Resource Server are separate applications or when the Authorization Server is third-party (like Google or Facebook). You might need to mock external server responses or utilize embedded servers for tests.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Pitfalls and Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Frequent Errors in OAuth2 Implementations<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Redirect URI Mismatch<\/strong>: This is a common error where the redirect URI provided during the OAuth2 authentication flow doesn&#8217;t match any of the URIs registered with the Authorization Server. Always double-check registered URIs and ensure they match.<\/li>\n\n\n\n<li><strong>Invalid Client Credentials<\/strong>: Another common error is using incorrect client IDs or secrets. Double-check the credentials and ensure they&#8217;re correctly set up in both your application and the Authorization Server.<\/li>\n\n\n\n<li><strong>Not Handling Token Expiry<\/strong>: Tokens, especially access tokens, often have short lifetimes. Not handling token expiry properly can lead to frequent and unexpected logouts or 401 Unauthorized errors.<\/li>\n\n\n\n<li><strong>Ignoring the Refresh Token<\/strong>: If your Authorization Server provides refresh tokens, use them. They&#8217;re a way to get new access tokens without prompting the user to log in again.<\/li>\n\n\n\n<li><strong>Insecure Token Storage<\/strong>: Storing tokens insecurely, such as in non-https cookies or local storage, can expose tokens to theft.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Debugging Token Issues<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Decode the Token<\/strong>: If you&#8217;re using JWTs, decode the token (using tools like <a href=\"https:\/\/jwt.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">jwt.io<\/a>) to check its structure, claims, and expiration.<\/li>\n\n\n\n<li><strong>Logging<\/strong>: Add logging on both the client and server sides to capture and inspect token values, expiry times, and any error messages related to token processing.<\/li>\n\n\n\n<li><strong>OAuth2 Debug Logs<\/strong>: Enable debug logs for OAuth2 in Spring. Add <code>logging.level.org.springframework.security.oauth2=DEBUG<\/code> to your <code>application.properties<\/code>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Checking for Misconfigurations<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Endpoint Configuration<\/strong>: Ensure your token, authorization, and user-info endpoints are correctly configured. Any mismatch can lead to errors.<\/li>\n\n\n\n<li><strong>Scope Misconfiguration<\/strong>: Ensure that the scopes your client application requests match what&#8217;s configured or allowed on the Authorization Server.<\/li>\n\n\n\n<li><strong>Cross-Origin Resource Sharing (CORS)<\/strong>: When building a SPA (Single Page Application) or when the client and server reside on different domains\/ports, ensure CORS settings are correctly set up to allow requests.<\/li>\n\n\n\n<li><strong>SSL\/HTTPS Issues<\/strong>: If you&#8217;re enforcing HTTPS (which you should for anything security-related), ensure your certificates are valid and trusted. Self-signed certificates, for instance, can cause issues unless explicitly trusted.<\/li>\n\n\n\n<li><strong>Consistency Across Microservices<\/strong>: In a microservices architecture, ensure that all services validate and interpret tokens consistently.<\/li>\n\n\n\n<li><strong>Spring Security Filters<\/strong>: Understand the order and role of each security filter in Spring Security. Misconfigurations can lead to skipped security checks or redundant checks.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth2 can be tricky to implement correctly, but tools and libraries like Spring Security make the job much easier. However, even with these tools, understanding the OAuth2 protocol and its various flows is invaluable. When in doubt, refer to the <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc6749\" target=\"_blank\" rel=\"noreferrer noopener\">official OAuth2 specification<\/a> and the documentation for your chosen libraries or platforms.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Best Practices<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Secure Token Storage<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Avoid Local Storage<\/strong>: For web applications, avoid storing tokens in local storage as it&#8217;s accessible via JavaScript, making it susceptible to cross-site scripting (XSS) attacks.<\/li>\n\n\n\n<li><strong>Use HttpOnly Cookies<\/strong>: If storing tokens in cookies, make sure they&#8217;re set as <code>HttpOnly<\/code>, which prevents them from being accessed via JavaScript.<\/li>\n\n\n\n<li><strong>Always Use HTTPS<\/strong>: Tokens are sensitive. Always ensure your application uses HTTPS to prevent man-in-the-middle attacks.<\/li>\n\n\n\n<li><strong>Server-side Storage<\/strong>: For traditional web applications, consider storing the tokens server-side and associate them with a session ID.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Handling Token Revocation<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Support Token Revocation<\/strong>: Ensure your Authorization Server supports token revocation. This enables clients or users to actively invalidate tokens, useful in scenarios like user logout, password changes, or potential security breaches.<\/li>\n\n\n\n<li><strong>Short-lived Access Tokens<\/strong>: Use short lifetimes for access tokens. This limits the potential misuse window if a token is compromised.<\/li>\n\n\n\n<li><strong>Utilize Refresh Tokens<\/strong>: Use refresh tokens to obtain new access tokens. This means even if an access token is compromised, it&#8217;s valid for only a short time. But remember to handle refresh tokens with extra care, as they typically have longer lifespans.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Considerations for Production Deployments<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Regularly Rotate Client Secrets<\/strong>: Change client secrets periodically and whenever there&#8217;s a suspicion they might have been compromised.<\/li>\n\n\n\n<li><strong>Limit Token Scopes<\/strong>: Always follow the principle of least privilege. Only request and grant the scopes that are absolutely necessary.<\/li>\n\n\n\n<li><strong>Avoid Implicit Flow<\/strong>: The implicit flow is less secure than the authorization code flow, especially for web applications. It&#8217;s susceptible to token interception attacks.<\/li>\n\n\n\n<li><strong>Use PKCE<\/strong>: If building a public client, like mobile apps or SPAs, use the <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc7636\" target=\"_blank\" rel=\"noreferrer noopener\">Proof Key for Code Exchange (PKCE)<\/a> extension with the authorization code flow to prevent authorization code interception attacks.<\/li>\n\n\n\n<li><strong>Monitor and Audit<\/strong>: Regularly monitor and audit your OAuth2 interactions. Look out for unusual patterns, like rapid repeated requests, which might indicate a breach or misuse.<\/li>\n\n\n\n<li><strong>Regularly Update Libraries<\/strong>: Always keep your OAuth2 libraries (like Spring Security OAuth) up-to-date. This ensures you get the latest security patches and stay protected against known vulnerabilities.<\/li>\n\n\n\n<li><strong>State Parameter<\/strong>: Always use the <code>state<\/code> parameter in the authorization request to prevent cross-site request forgery (CSRF) attacks.<\/li>\n\n\n\n<li><strong>Logout<\/strong>: Implement and test the logout functionality, ensuring that it not only ends the session on the client but also invalidates tokens on the server.<\/li>\n\n\n\n<li><strong>CORS<\/strong>: Be restrictive with your Cross-Origin Resource Sharing (CORS) settings. Only allow origins that you trust.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Extending Further<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Using JWT Tokens with OAuth2<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">JSON Web Tokens (JWTs) are a compact, URL-safe means of representing claims to be transferred between two parties. They are particularly well-suited for OAuth2.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Advantages<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Self-contained<\/strong>: JWTs contain all the necessary information about the user, eliminating the need to query the database more than once.<\/li>\n\n\n\n<li><strong>Compact<\/strong>: Can be sent through URLs, POST parameters, or inside HTTP headers.<\/li>\n\n\n\n<li><strong>Standardized<\/strong>: Follows a well-defined standard (RFC 7519).<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Implementation<\/strong>: Ensure you have the JWT dependencies, and configure the token store to use JWT:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-44\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-meta\">@Bean<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> TokenStore <span class=\"hljs-title\">tokenStore<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> JwtTokenStore(accessTokenConverter());\r\n}\r\n\r\n<span class=\"hljs-meta\">@Bean<\/span>\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> JwtAccessTokenConverter <span class=\"hljs-title\">accessTokenConverter<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n    JwtAccessTokenConverter converter = <span class=\"hljs-keyword\">new<\/span> JwtAccessTokenConverter();\r\n    converter.setSigningKey(<span class=\"hljs-string\">\"my-secret-key\"<\/span>);  <span class=\"hljs-comment\">\/\/ Symmetric key, consider using RSA for production<\/span>\r\n    <span class=\"hljs-keyword\">return<\/span> converter;\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-44\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Implementing Multi-Factor Authentication (MFA)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">MFA provides an additional layer of security by requiring users to provide two or more verification factors to gain access.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Advantages<\/strong>:\n<ul class=\"wp-block-list\">\n<li><strong>Enhanced Security<\/strong>: Even if a malicious actor gets the password, they won&#8217;t be able to access the account without the second factor.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Implementation<\/strong>: You&#8217;d typically integrate MFA during the authorization code grant flow:\n<ol class=\"wp-block-list\">\n<li>User logs in with a username and password.<\/li>\n\n\n\n<li>The server prompts the user for a second factor (like an SMS code or a time-based one-time password from an app).<\/li>\n\n\n\n<li>Once both factors are verified, the OAuth2 flow continues as usual.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Scaling Your OAuth2 Architecture<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As your application grows, your OAuth2 setup needs to scale to handle more traffic and provide high availability.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Stateless Tokens<\/strong>: By using JWTs, you can make your tokens stateless, allowing your application to scale horizontally without sharing session data between instances.<\/li>\n\n\n\n<li><strong>Distributed Token Store<\/strong>: If not using stateless tokens, use a distributed token store like Redis or a database cluster to manage token storage.<\/li>\n\n\n\n<li><strong>Load Balancing<\/strong>: Use load balancers in front of your Authorization and Resource Servers to distribute incoming traffic and provide fault tolerance.<\/li>\n\n\n\n<li><strong>Separation of Concerns<\/strong>: Keep the Authorization Server separate from the Resource Server. This way, they can be scaled independently based on the load.<\/li>\n\n\n\n<li><strong>Caching<\/strong>: Cache token validation results and user information to reduce database lookups and improve performance.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Incorporating these advanced features into your OAuth2 implementation ensures that your application remains secure, scalable, and user-friendly as it grows.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction OAuth2, or Open Authorization 2.0, is a standard protocol for authorization. While it&#8217;s often mistakenly referred to as an authentication protocol, its primary job is to delegate permissions. Here\u2019s a simple analogy: imagine giving the keys to your home to a trusted friend to water your plants. Instead of giving them the main key, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[5,4],"tags":[],"class_list":["post-1590","post","type-post","status-publish","format-standard","category-java","category-programming-languages","entry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Implementing OAuth2 with Spring Security in Java<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Implementing OAuth2 with Spring Security in Java\" \/>\n<meta property=\"og:description\" content=\"Introduction OAuth2, or Open Authorization 2.0, is a standard protocol for authorization. While it&#8217;s often mistakenly referred to as an authentication protocol, its primary job is to delegate permissions. Here\u2019s a simple analogy: imagine giving the keys to your home to a trusted friend to water your plants. Instead of giving them the main key, [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-10-10T18:59:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-10-10T18:59:59+00:00\" \/>\n<meta name=\"author\" content=\"w3compadmin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"w3compadmin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/\"},\"author\":{\"name\":\"w3compadmin\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"headline\":\"Implementing OAuth2 with Spring Security in Java\",\"datePublished\":\"2023-10-10T18:59:56+00:00\",\"dateModified\":\"2023-10-10T18:59:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/\"},\"wordCount\":5034,\"commentCount\":0,\"articleSection\":[\"Java\",\"Programming Languages\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/\",\"name\":\"Implementing OAuth2 with Spring Security in Java\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\"},\"datePublished\":\"2023-10-10T18:59:56+00:00\",\"dateModified\":\"2023-10-10T18:59:59+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/implementing-oauth2-with-spring-security-in-java\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Articles Home\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Programming Languages\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/programming-languages\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Implementing OAuth2 with Spring Security in Java\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\",\"name\":\"Developer Articles Hub\",\"description\":\"\",\"alternateName\":\"Developer Articles\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\",\"name\":\"w3compadmin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266\",\"contentUrl\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266\",\"caption\":\"w3compadmin\"},\"sameAs\":[\"http:\\\/\\\/w3computing.com\\\/articles\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Implementing OAuth2 with Spring Security in Java","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/","og_locale":"en_US","og_type":"article","og_title":"Implementing OAuth2 with Spring Security in Java","og_description":"Introduction OAuth2, or Open Authorization 2.0, is a standard protocol for authorization. While it&#8217;s often mistakenly referred to as an authentication protocol, its primary job is to delegate permissions. Here\u2019s a simple analogy: imagine giving the keys to your home to a trusted friend to water your plants. Instead of giving them the main key, [&hellip;]","og_url":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/","article_published_time":"2023-10-10T18:59:56+00:00","article_modified_time":"2023-10-10T18:59:59+00:00","author":"w3compadmin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"w3compadmin","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/#article","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/"},"author":{"name":"w3compadmin","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"headline":"Implementing OAuth2 with Spring Security in Java","datePublished":"2023-10-10T18:59:56+00:00","dateModified":"2023-10-10T18:59:59+00:00","mainEntityOfPage":{"@id":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/"},"wordCount":5034,"commentCount":0,"articleSection":["Java","Programming Languages"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/","url":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/","name":"Implementing OAuth2 with Spring Security in Java","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/#website"},"datePublished":"2023-10-10T18:59:56+00:00","dateModified":"2023-10-10T18:59:59+00:00","author":{"@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"breadcrumb":{"@id":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.w3computing.com\/articles\/implementing-oauth2-with-spring-security-in-java\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Articles Home","item":"https:\/\/www.w3computing.com\/articles\/"},{"@type":"ListItem","position":2,"name":"Programming Languages","item":"https:\/\/www.w3computing.com\/articles\/programming-languages\/"},{"@type":"ListItem","position":3,"name":"Implementing OAuth2 with Spring Security in Java"}]},{"@type":"WebSite","@id":"https:\/\/www.w3computing.com\/articles\/#website","url":"https:\/\/www.w3computing.com\/articles\/","name":"Developer Articles Hub","description":"","alternateName":"Developer Articles","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.w3computing.com\/articles\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561","name":"w3compadmin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266","url":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266","contentUrl":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1780141266","caption":"w3compadmin"},"sameAs":["http:\/\/w3computing.com\/articles"]}]}},"featured_image_src":null,"featured_image_src_square":null,"author_info":{"display_name":"w3compadmin","author_link":"https:\/\/www.w3computing.com\/articles\/author\/w3compadmin\/"},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1590","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/comments?post=1590"}],"version-history":[{"count":9,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1590\/revisions"}],"predecessor-version":[{"id":1599,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1590\/revisions\/1599"}],"wp:attachment":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/media?parent=1590"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/categories?post=1590"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/tags?post=1590"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}