This is my first time with a Spring Boot secured REST app. I've added spring-boot-starter-security to my classpath, and I understand that automatically secures all URLs. But at this point in my development, I'm not ready to do that, so I added an antMatcher to ALLOW all URLs. But no matter what I put in my WebSecurityConfig, I still get an the error message:
Full authentication is required to access this resource
Below is my WebSecurityConfig in full. Is there something else I need to do for Spring to pick this up? How can verify if it's being used at all? Many thanks!
package com.company.jwt.security;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import com.company.jwt.UserUtils;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests()
.antMatchers("/**").permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder authBuilder) throws Exception {
authBuilder.userDetailsService(inMemoryUserDetailsManager());
}
#Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
Properties props = new Properties();
UserUtils.getUsers()
.forEach(e -> props.put(e.getUsername(), e.getPassword() + "," +
e.getAuthorities() + ", enabled"));
return new InMemoryUserDetailsManager(props);
}
}
What kind of URL are you trying to access there? A rest controller that you created?
There may be something overriding the permission of your URLs.
I ran the code bellow with no problem (SpringBoot 1.5.2).
#SpringBootApplication
#RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#RequestMapping("/foo")
public String foo() {
return "foo";
}
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests()
.antMatchers("/**").permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
$ curl -s http://localhost:8080/foo
foo
Related
I am using OAuth2 with spring boot. I am new to Oauth. I am getting this Consider defining a bean of type 'org.springframework.security.authentication.AuthenticationManager' in your configuration exception while running my spring boot application. I have seen some other answered questions in StackOverflow but they were no fulfilling my need. I am using Spring boot version 2.3.3.RELEASE. I am taking reference from this Repository. I have just Updated the Version of my application. Here is my class where i am facing this issue:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
#EnableAuthorizationServer
#Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("ClientId").secret("secret").authorizedGrantTypes("authorization_code")
.scopes("user_info").autoApprove(true);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
If I create a bean like this. :
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
it has resolved my error for a class that extends WebSecurityConfigurerAdapter but my other class extends AuthorizationServerConfigurerAdapter and for this class, the solution is not working
and I am getting a warning saying The method authenticationManagerBean() is undefined for the type AuthorizationServerConfigurerAdapter. Could you please help me.
You are overriding a method that does not exist in AuthorizationServerConfigurerAdapter hense the error.
As you can see AuthorizationServerConfigurerAdapter define only configure method with 3 signatures:
public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
}
}
I have resolved this issue by just updating my AuthorizationServerConfig.java class & ResourceServerConfig.java class like this:
AuthorizationServerConfig.java class:
package com.ab.security.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
#EnableAuthorizationServer
#Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("ClientId").secret("secret").authorizedGrantTypes("authorization_code")
.scopes("user_info").autoApprove(true);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
ResourceServerConfig.java class:
package com.ab.security.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
#EnableResourceServer
#Configuration
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/login", "/oauth/authorize").and().authorizeRequests().anyRequest()
.authenticated().and().formLogin().permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManagerBean()).inMemoryAuthentication().withUser("Peter")
.password("peter").roles("USER");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
I'm using spring boot with spring security and jpa. I would like to have admin user in config and other users in database. The problem is when I added UserDetailsService, the admin user from application.properties stop working.
application.properties:
spring.security.user.name=admin
spring.security.user.password={bcrypt}$2a$10$7F7xGm8iuzafFA7RPS8gzeKJm9qNBwtejT4hSuBKXMNlc/4NxOy1G
spring.security.user.roles=admin
Spring Security config class:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Qualifier("myUserDetailsService")
#Autowired
private UserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(encodePWD());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers("/").permitAll()
.antMatchers("/uzytkownik/pacjent/rejestracja").anonymous()
.anyRequest().hasRole("admin")
.and().formLogin().permitAll()
;
}
#Bean
public BCryptPasswordEncoder encodePWD() {
return new BCryptPasswordEncoder();
}
}
Without any configuration Spring Security reads user from properties file by default. But if you add an UserDetailsService it means you want to read users using the interface's method loadUserByUsername. This method can be implemented for example to read users from database
If you want your admin user from application.properties to be considered as a user, you can create it in your implementation of UserDetailsService :
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
#Service
public class MyUserDetailsService implements UserDetailsService {
#Value("${spring.security.user.name}")
private String adminUserName;
#Value("${spring.security.user.password}")
private String adminPassword;
#Value("${spring.security.user.roles}")
private String adminRole;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(username.equals(adminPassword)) {
return User.builder().username(adminUserName).password(adminPassword).roles(adminRole).build();
}
//return your other users from database here
return null;
}
}
What I am trying to do should be pretty easy:
a REST-Service with 3 different security levels:
A "public" RestService accessible by all
A "protected" RestService for "USER"s
A "private" RestService for "ADMIN"s
but either I have Access to all - or with the current config I got acces to NONE, because Without BasicAuth I always got
Full authentication is required to access this resource
and with the "uuu" + "ppp" I always got
Bad credentials
By the way I using spring boot 1.5.3
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
#Configuration
#EnableWebSecurity
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("aaa").password("ppp").roles("USER", "ADMIN");
auth.inMemoryAuthentication().withUser("uuu").password("ppp").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/protected/**").hasRole("USER")
.antMatchers("/private/**").hasRole("ADMIN")
.and().httpBasic()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // We don't need sessions to be created.
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**"); /* To allow Pre-flight [OPTIONS] request from browser */
}
}
The OP found their solution actually works. There was a problem with the component-Scan, because my Rest project is a child of my DAO and Repository-Project...
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan({"com.leycarno.base", "com.leycarno.rest"}) // now we're listen to all the nice components :-)
#EnableJpaRepositories("com.leycarno.base.repositories")
#EntityScan("com.leycarno.base.models")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I am trying out Oauth2 with Spring security. I am trying to call the /getresource service in my resource class by following the below
GET http://localhost:8080/oauth/authorize?
response_type=code
&client_id=my-first-client
&redirect_url=http://localhost:8080/getcode
&scope=read
Get the code and call the Authorization service to get the auth token by doing
POST http://localhost:8080/oauth/token
grant_type=authorization_code&code=XXXX
Get the token and call the /getresource rest service.
by
GET http://localhost:8080/getresource
Header : Authorization: Bearer <>
But I have been getting the below error
<oauth>
<error_description>
Full authentication is required to access this resource
</error_description>
<error>unauthorized</error>
</oauth>
Any help will to locate the issue will be greatly appreciated.
My Authorization class
package auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
#EnableAuthorizationServer
#SpringBootApplication
#EnableWebSecurity
public class AuthProvider extends WebSecurityConfigurerAdapter implements AuthorizationServerConfigurer{
#Autowired
AuthenticationManager authenticationManager;
#Autowired
DriverManagerDataSource dataSource;
public static void main(String[] args)
{
SpringApplication.run(AuthProvider.class, args);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
String uname_query = "select username,userpass,enabled from users where username=?";
String role_query = "Select username, role_name from user_roles where username=?";
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(uname_query)
.authoritiesByUsernameQuery(role_query);
}
/* #Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","/login","/home","/403","/oauth/**","/resources/**").permitAll()
.antMatchers("/getresource").access("#oauth2.hasScope('read')")
.anyRequest().authenticated().and().formLogin().loginPage("/login");
}*/
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
// TODO Auto-generated method stub
security.allowFormAuthenticationForClients();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("my-first-client")
.secret("password")
.accessTokenValiditySeconds(120)
.authorizedGrantTypes("authorization_code", "refresh_token","password")
.authorities("ROLE_CLIENT")
.redirectUris("http://localhost:8080/authcode")
.resourceIds("testresource");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// TODO Auto-generated method stub
endpoints.authenticationManager(authenticationManager);
}
}
My Resource class
package auth;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#Configuration
#EnableResourceServer
#RestController
public class Resource {
private static final String resourceid="testresource";
#RequestMapping("/getresource")
public String getResource()
{
return "Hello Everyone!!";
}
private static class Resourceconfigurator extends ResourceServerConfigurerAdapter
{
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(Resource.resourceid);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","/login","/home","/403","/oauth/**","/resources/**").permitAll()
.antMatchers("/getresource").access("#oauth2.hasScope('read')")
.anyRequest().authenticated().and().formLogin().loginPage("/login");
}
}
}
When the user login I generate a token so when the user want to access information of RESTapi he will not login again , the code works but I have a problem.
The token that spring generate works but when I recompile the code I wrote, this token doesn't work anymore and I should request a new token to use the "bearer $Token " is this a normal behavior or I should fix something in the settings?
Example :
curl -u test: http://localhost:8080/oauth/token -d "grant_type=password&username=id&password=pass"
{"access_token":"a46c3cf4-6777-4a61-9f71-268be047c383","token_type":"bearer","refresh_token":"8ef69c18-1a9e-47c0-ba80-b51a34144e9a","expires_in":603005,"scope":"read write trust"}
When I recompile the code :
curl -u test: http://localhost:8080/oauth/token -d "grant_type=password&username=id&password=pass"
{"access_token":"1a69f140-47ac-4dde-9786-1d4f14f9a389","token_type":"bearer","refresh_token":"be99d434-54a0-4273-add8-cccad95caec3","expires_in":604799,"scope":"read write trust"}
this is my code :
import com.lms.entities.UsersEntity;
import com.lms.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
#Configuration
#ComponentScan
#EnableAutoConfiguration
#RestController
class SpringBackendScoutApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBackendScoutApplication.class, args);
}
#Configuration
#EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.requestMatchers()
.antMatchers(
Constants.USERS, Constants.COMMENTS, Constants.FRIENDS_REQUEST,
Constants.MUSICS, Constants.PHOTOS, Constants.POSTS, Constants.VIDEOS,
Constants.PROFILE_PHOTOS, Constants.FRIENDS, "/"
).and()
.authorizeRequests()
.anyRequest().access("#oauth2.hasScope('read')")
.and().logout();
// #formatter:on
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("sparklr");
}
}
#Configuration
#EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("test")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.resourceIds("sparklr")
.accessTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(7))
;
}
}
#Configuration
#EnableWebSecurity
protected static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserRepository userRepository;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
for (UsersEntity user : userRepository.findAll())
if (user.getUsername() != null && user.getPassword() != null)
auth.inMemoryAuthentication().withUser(user.getUsername()).password(user.getPassword()).roles("USER");
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
}
To solve the problem , you should add a token store to persist the token generated each time :
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
#Value("${spring.datasource.driverClassName}")
private String oauthClass;
#Value("${spring.datasource.url}")
private String oauthUrl;
#Bean
public TokenStore tokenStore() {
DataSource tokenDataSource = DataSourceBuilder.create()
.driverClassName(oauthClass)
.username("root")
.password("")
.url(oauthUrl)
.build();
return new JdbcTokenStore(tokenDataSource);
}
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("scout").tokenStore(tokenStore());
}
For the other class :
#Configuration
#EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
endpoints.tokenStore(tokenStore());
}
}
In applications.properties it should be configured :
spring.datasource.url=jdbc:mysql://localhost:3306/MyDatabase
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
and Finally you should add the two tables in your database :
create table oauth_access_token (
token_id VARCHAR(256),
token BLOB,
authentication_id VARCHAR(256) PRIMARY KEY,
user_name VARCHAR(256),
client_id VARCHAR(256),
authentication BLOB,
refresh_token VARCHAR(256)
);
create table oauth_refresh_token (
token_id VARCHAR(256),
token BLOB,
authentication BLOB
);
By default, an in memory token store is configured. If you want to persist the tokens between restarts then you need to configure a persistent token store (JdbcTokenStore for example)
Edit to add steps:
This SQL will create the basic schema that you need.
Create a DataSource bean connected to the database containing that schema and then add the following bean to your OAuth config
#Autowired
DataSource dataSource;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}