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;
}
}
Related
I am working Spring-Boot, Spring Security with basic Authentication. I will send login url from my client application written in AngularJS via RESTful API call.
Everything works as expected. All the users in the DB configured in the SecurityConfiguration.java as below.
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
List<User> users = userService.getUsers();
for (User user : users) {
auth.inMemoryAuthentication().withUser(user.getUserName()).password(user.getPassword())
.roles(user.getRole().getName());
}
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/server/rest/secure/**")
.hasRole("ADMIN").and()
.httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint());
}
#Bean
public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint() {
return new CustomBasicAuthenticationEntryPoint();
}
CustomBasicAuthenticationEntryPoint.java
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
#Override
public void commence(final HttpServletRequest request,
final HttpServletResponse response,
final AuthenticationException authException) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName() + "");
PrintWriter writer = response.getWriter();
writer.println("HTTP Status 401 : " + authException.getMessage());
response.setHeader("WWW-Authenticate", "FormBased");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
#Override
public void afterPropertiesSet() throws Exception {
setRealmName("MY_TEST_REALM");
super.afterPropertiesSet();
}
}
So If I signup a new user which will inserted in the DB but not added in the above implementation. So authentication fails.
How can refresh the above implementation whenever i'm and doing signup of a new user
When doing authentication with db, you should do the following:
#Service("userDetailsService")
#Transactional
public class MUserDetailService implements UserDetailsService {
#Autowired
AppUserDao appUserDao;
#Override
public UserDetails loadUserByUsername(final String appUserName) throws UsernameNotFoundException {
AppUser appUser = appUserDao.findByName(appUserName);
if (appUser == null) throw new UsernameNotFoundException(appUserName);
else{
return new User(appUser.getUsername(),appUser.getPassword(),appUser.getActive(),true,true,true,getGrantedAuthorities(appUser));
}
}
private List<GrantedAuthority> getGrantedAuthorities(AppUser appUser){
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (Authority authority : appUser.getAuthorities()){
authorities.add(new SimpleGrantedAuthority(authority.getAuthorityName()));
}
return authorities;
}
}
and then define SecurityConfiguration as follows:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
#Qualifier("userDetailsService")
UserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}
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
I did a tutorial https://auth0.com/blog/securing-spring-boot-with-jwts/ about authorization using Spring Security, but this example use hardcoded user data. I would like to authorize using database PostgreSQL. How can I do that? Or do you know some examples on github using Spring REST Security and PostgreSQL?
package com.example.security;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
// We filter the api/login requests
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in header
.addFilterBefore(new JWTAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// Create a default account
auth.inMemoryAuthentication()
.withUser("admin")
.password("password")
.roles("ADMIN");
}
}
You can use it with your custom userdetailservice like this:
#Autowired
private CustomUserDetailService userDetailsService;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
;
}
and add customuserdetail service :
#Service
public class CustomUserDetailService implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = getUserFromDatabase();
UserItem userItem = new UserItem(user.getUsername(),user.getPassword(),true,true,true,true, new ArrayList<GrantedAuthority>());;
userItem.setAuthorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN", "ROLE_USER"));
return userItem;
}
}
You need to create a bean for dataSource like this
#Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("org.postgresql.Driver");
driverManagerDataSource.setUrl("jdbc:postgresql://127.0.0.1:5432/mydb");
driverManagerDataSource.setUsername("postgres");
driverManagerDataSource.setPassword("root");
return driverManagerDataSource;
}
And then autowire javax.sql.DataSource inside your WebSecurityConfig class:
#Autowired
DataSource dataSource;
if your password is Bcrypt encoded then create a bean for passwordEncoder
#Bean(name="passwordEncoder")
public PasswordEncoder passwordencoder(){
return new BCryptPasswordEncoder();
}
Configure authentication like this:
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select email,password from users where email=?").passwordEncoder(passwordencoder());
}
and finally hit the /login route.
I have this listener in the context of Spring:
package listeners;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.stereotype.Component;
import services.UserService;
import services.security.CustomUserDetails;
/**
*
* #author sergio
*/
#Component
public class AuthenticationSuccessEventHandler{
private static Logger logger = LoggerFactory.getLogger(AuthenticationSuccessEventHandler.class);
#Autowired
private UserService userService;
#EventListener({AuthenticationSuccessEvent.class, InteractiveAuthenticationSuccessEvent.class})
public void processAuthenticationSuccessEvent(AbstractAuthenticationEvent e) {
logger.info("Autenticación realizada ....");
// Actualizamos la útltima fecha de acceso
String username = ((CustomUserDetails) e.getAuthentication().getPrincipal()).getUsername();
logger.info("Actualizando último acceso para user: " + username);
userService.updateLastLoginAccess(username, new Date());
}
}
This is successfully created in context, according to the Spring debug messages.
DEBUG DefaultListableBeanFactory:448 - Creating instance of bean 'authenticationSuccessEventHandler'
2016-12-11 11:33:29 DEBUG InjectionMetadata:72 - Registered injected element on class [listeners.AuthenticationSuccessEventHandler]: AutowiredFieldElement for private services.UserService listeners.AuthenticationSuccessEventHandler.userService
When I authenticate correctly in the application, no event is released by Spring Security and therefore this Event Listener is not called.
My Spring Security configuration is this
#Configuration
#EnableWebSecurity
#ComponentScan(basePackageClasses = CustomUserDetailsService.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/signup").anonymous()
.antMatchers("/admin/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/admin/login").permitAll()
.usernameParameter("username").passwordParameter("password")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout"))
.logoutSuccessUrl("/admin/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
}
SecurityWebApplicationInitializer
package config;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
/**
*
* #author sergio
*/
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
I am using Spring Security 4.2.0.RELEASE.
You may need to register the event-publishing infrastructure (eg. by configuring a DefaultAuthenticationEventPublisher).
#EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {
...
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationEventPublisher(authenticationEventPublisher())
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean
public DefaultAuthenticationEventPublisher authenticationEventPublisher() {
return new DefaultAuthenticationEventPublisher();
}
}
This is how i achieved it.
1) In your Application class, expose your application listener like
#Bean
public ApplicationListener applicationListener(){
return new AuthSuccessApplicationListener();
}
2) Implement AuthSuccessApplicationListener for example
public class AuthSuccessApplicationListener implements
ApplicationListener<InteractiveAuthenticationSuccessEvent>{
#Autowired(required=false)
HttpSession httpSession;
#Autowired
Environment env;
/**
* Handle an application event.
*
* #param appEvent the event to respond to
*/
#Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent appEvent) {
if (appEvent!=null) {
LdapUserDetailsImpl ldapUserDetailsImpl = (LdapUserDetailsImpl) appEvent.getAuthentication().getPrincipal();
try {
if (ldapUserDetailsImpl != null) {
logger.info("Session Created for " + ldapUserDetailsImpl.getUsername());
if (httpSession.getAttribute("adminUser") == null) {
// check user is admin and set into session
if (isAdminUser(ldapUserDetailsImpl.getUsername())) {
httpSession.setAttribute("adminUser", "ADMIN_USER");
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(auth.getAuthorities());
// Add the ROLE_ADMIN into Authorities
authorities.add(new SimpleGrantedAuthority(SecurityConfig.ADMIN));
// Create a new Authentication based on current principal and authorities and set into Security Context
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
SecurityContextHolder.getContext().setAuthentication(newAuth);
}
}
}
} catch (Exception e) {
logger.error("Exception occurred : " + e.getMessage());
}
}
}
Here's how the Spring Security docs explain it (at the time of writing, Spring Security is at version 5.6.1):
To listen for these events, you must first publish an AuthenticationEventPublisher. Spring Security’s DefaultAuthenticationEventPublisher will probably do fine:
#Bean
public AuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher appEventPublisher) {
return new DefaultAuthenticationEventPublisher(appEventPublisher);
}
See https://docs.spring.io/spring-security/reference/servlet/authentication/events.html
In spring-security version 5.6.0 only UsernamePasswordAuthenticationFilter fires InteractiveAuthenticationSuccessEvent. As option You may extends AbstractAuthenticationProcessingFilter or do it by own a success handler implementation. Example:
class LoggingAuthenticationSuccessHandler extends WebFilterChainServerAuthenticationSuccessHandler {
#Autowired
private AuthenticationEventPublisher eventPublisher;
#Override
public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
this.eventPublisher.publishAuthenticationSuccess(authentication);
return super.onAuthenticationSuccess(webFilterExchange,authentication);
}
}
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);
}