Register api is resposing 403 forbidden but csrf is disabled in spring boot - spring

I am creating backend app and testing as well. my register url is resposing 403 forbidden but csrf is disabled. I can't fix this problem. Please help me P
Here is my configuration
package uz.renessans.configuration;
import lombok.RequiredArgsConstructor;
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.method.configuration.EnableGlobalMethodSecurity;
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.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import uz.renessans.entity.user.UserRepository;
import uz.renessans.security.JwtFilter;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#RequiredArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final JwtFilter jwtFilter;
private final UserRepository userRepository;
#Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserDetailsService userDetailsService = username ->
userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException(username));
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
String[] OPEN_URLS = {
"/api/v1/register/**",
"/swagger-ui/**",
"/api/v1/login"
};
http
.csrf()
.disable()
.httpBasic()
.disable()
.authorizeRequests()
.antMatchers(
"/api/v1/register/**",
"/swagger-ui/**",
"/api/v1/login"
)
.permitAll()
.anyRequest()
.authenticated();
// .permitAll();
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Here is my jwt filter class:
package uz.renessans.security;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import uz.renessans.entity.user.User;
import uz.renessans.entity.user.UserRepository;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
#Component
#RequiredArgsConstructor
public class JwtFilter extends OncePerRequestFilter {
private final JwtProvider jwtProvider;
private final UserRepository userRepository;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String authorization = request.getHeader("Authorization");
if (authorization != null && authorization.startsWith("Bearer") && authorization.length() > 7) {
authorization = authorization.substring(7);
String username = jwtProvider.getPhoneNumber(authorization);
if (username != null) {
Optional<User> optionalUser = userRepository.findByUsername(username);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = null;
if (optionalUser.isPresent()) {
usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(optionalUser.get(), null, optionalUser.get().getAuthorities());
}
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
Here is my register api
public HttpEntity<?> register(RegisterDto dto, Role role) {
if (userRepository.existsByUsername(dto.getUsername()))
return new ResponseEntity<>(new ApiResponse("Username already exists", false), HttpStatus.CONFLICT);
if (!dto.getPassword().equals(dto.getRePassword()))
return new ResponseEntity<>(new ApiResponse("Password must match", false), HttpStatus.CONFLICT);
User user = new User();
user.setRole(role);
user.setUsername(dto.getUsername());
user.setPassword(passwordEncoder.encode(dto.getPassword()));
user.setFullName(dto.getFullName());
User savedUser = userRepository.save(user);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
savedUser.getUsername(), savedUser.getPassword());
authenticationManager.authenticate(authenticationToken);
String token = jwtProvider.generateToken(savedUser.getUsername(), savedUser.getRole());
Response response = Response.builder().token(token).role(role.toString()).build();
return new ResponseEntity<>(new ApiResponse("Registered Successfully", true, response), HttpStatus.OK);
}

Related

There was an unexpected error (type=Forbidden, status=403). Access Denied

There was an unexpected error (type=Forbidden, status=403). Access Denied.
When I was trying to access URL from postman or from browser I am getting an error of There was an unexpected error (type=Forbidden, status=403). Access Denied.
1)Web Security Class:-
import javax.servlet.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
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.crypto.bcrypt.BCryptPasswordEncoder;
import com.photoapp.users.service.ApiUserService;
#Configuration
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private Environment environment;
private ApiUserService apiUserService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
public WebSecurity(Environment environment , ApiUserService apiUserService , BCryptPasswordEncoder bCryptPasswordEncoder) {
this.environment = environment;
this.apiUserService = apiUserService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/**").hasIpAddress(environment.getProperty("gateway.ip"))
.and()
.addFilter(getAuthenticationFilter());
http.headers().frameOptions().disable();
}
private AuthenticationFilter getAuthenticationFilter() throws Exception {
// TODO Auto-generated method stub
AuthenticationFilter authenticationFilter = new AuthenticationFilter();
authenticationFilter.setAuthenticationManager(authenticationManager());
return authenticationFilter;
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(apiUserService).passwordEncoder(bCryptPasswordEncoder);
}
}
2)Authentication Filter Class:-
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.photoapp.users.model.LoginRequestModel;
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public Authentication attemptAuthentiation(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {
try {
LoginRequestModel creds = new ObjectMapper()
.readValue(req.getInputStream() , LoginRequestModel.class);
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken (
creds.getEmail(),
creds.getPassword(),
new ArrayList<>()));
}
catch(IOException e) {
throw new RuntimeException(e);
}
}
protected void succeddfulAuthentication(HttpServletRequest req, HttpServletResponse res , FilterChain chain , Authentication auth) throws IOException , ServletException {
}
}
3)Controller Class:-
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.photoapp.users.dto.UserDto;
import com.photoapp.users.model.CreateUserRequestModel;
import com.photoapp.users.model.CreateUserResponseModel;
import com.photoapp.users.service.ApiUserService;
#RestController
#RequestMapping("/users")
public class UsersController {
#Autowired
private ApiUserService apiUserService;
#GetMapping("/status/check")
public String status() {
return "Working";
}
#PostMapping( consumes = {MediaType.APPLICATION_XML_VALUE , MediaType.APPLICATION_JSON_VALUE } ,
produces = {MediaType.APPLICATION_XML_VALUE , MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<CreateUserResponseModel> createUser(#RequestBody CreateUserRequestModel userDetails) {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
UserDto userDto = modelMapper.map(userDetails, UserDto.class);
UserDto createdUser = apiUserService.createUser(userDto);
CreateUserResponseModel responseModel = modelMapper.map(createdUser , CreateUserResponseModel.class);
return ResponseEntity.status(HttpStatus.CREATED).body(responseModel);
}
}
4)Service Implementation Class:-
import java.util.ArrayList;
import java.util.UUID;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.photoapp.users.dao.UserRepository;
import com.photoapp.users.dto.UserDto;
import com.photoapp.users.entity.UserEntity;
#Service
public class ApiUserServiceImpl implements ApiUserService{
UserRepository userRepository;
BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
public ApiUserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userRepository = userRepository;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
#Override
public UserDto createUser(UserDto userDetails) {
userDetails.setUserId(UUID.randomUUID().toString());
userDetails.setEncryptedPassword(bCryptPasswordEncoder.encode(userDetails.getPassword()));
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
UserEntity userEntity = modelMapper.map(userDetails, UserEntity.class);
userRepository.save(userEntity);
return userDetails;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
UserEntity userEntity = userRepository.findByEmail(username);
if(userEntity == null) throw new UsernameNotFoundException(username);
return new User(userEntity.getEmail() , userEntity.getEncryptedPassword() , true ,true ,true ,true , new ArrayList<>());
}
}
Can you check if gateway.ip property is set in your environment variavales? if its mac,try echo ${gateway.ip}.
Other point is why are you limiting to just one ip? any specific reason?
Also can you confirm if removing .hasIpAddress(environment.getProperty("gateway.ip")) works?
In my application i configure AuthenticationEntryPoint in spring boot security config because if any error occurred (even my custom 404 - item was not found) spring boot catched error and return 401 (in my case) but i remeber that some people told about 403. So i think that 403 could hide real error from you
Therefore you could try to catch error via configure exception handling
.exceptionHandling().authenticationEntryPoint(new AppAuthenticationEntryPoint())
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().sameOrigin();
http.cors();
http.csrf().disable()
.authorizeRequests().antMatchers("/", "/callback", "/login**", "/webjars/**", "/error**").permitAll()
.and()
.authorizeRequests().antMatchers("/api/**").authenticated()
.and()
.authorizeRequests().antMatchers("/h2-console/**").permitAll()
.and()
.authorizeRequests().antMatchers("/swagger-ui.html").permitAll()
.and()
.authorizeRequests().antMatchers("/swagger-ui/**").permitAll()
.and()
.exceptionHandling().authenticationEntryPoint(new AppAuthenticationEntryPoint())
.and()
.logout().permitAll().logoutSuccessUrl("/");
}
#Bean
public PrincipalExtractor getPrincipalExtractor(){
return new KeyCloakUserInfoExtractorService();
}
#Autowired
private ResourceServerTokenServices resourceServerTokenServices;
}
My AuthenticationEntryPoint looks like:
#ControllerAdvice
public class AppAuthenticationEntryPoint implements AuthenticationEntryPoint{
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException auth) throws IOException, ServletException {
// 401
setResponseError(response, HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed");
}
#ExceptionHandler (value = {AccessDeniedException.class})
public void commence(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
// 403
setResponseError(response, HttpServletResponse.SC_FORBIDDEN, String.format("Access Denies: %s", accessDeniedException.getMessage()));
}
#ExceptionHandler (value = {NotFoundException.class})
public void commence(HttpServletRequest request, HttpServletResponse response, NotFoundException notFoundException) throws IOException {
// 404
setResponseError(response, HttpServletResponse.SC_NOT_FOUND, String.format("Not found: %s", notFoundException.getMessage()));
}
#ExceptionHandler (value = {Exception.class})
public void commence(HttpServletRequest request, HttpServletResponse response, Exception exception) throws IOException {
//logger.error(String.format("An error occurred during request: %s %s error message: %s",
//request.getMethod(), request.getRequestURL(), exception.getMessage()));
// 500
setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, String.format("Internal Server Error: %s", exception.getMessage()));
}
private void setResponseError(HttpServletResponse response, int errorCode, String errorMessage) throws IOException{
response.setStatus(errorCode);
response.getWriter().write(errorMessage);
response.getWriter().flush();
response.getWriter().close();
}
//private final Logger logger = LoggerFactory.getLogger(this.getClass());
}
Hope it helps you to understand reason of 403
You must permit all of the swagger related URLs.
http.authorizeRequests().antMatchers(
"/swagger-ui.html/**",
"/webjars/springfox-swagger-ui/**",
"/swagger-resources/**",
"/swagger-ui/**",
"/v2/api-docs/**"
).permitAll();

Getting problem authenticationProvider in jwt authorization

I am getting error in configure method of SecurityConfig class whose code is here:
package com.sumit.Security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.sumit.Repo.UserRepository;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Autowired
private UserRepository userRepository;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// remove csrf and state in session because in jwt we do not need them
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager(),userRepository))
.authorizeRequests()
// configure access rules
.antMatchers("/register").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.antMatchers("/user").hasAnyRole("ADMIN","USER")
.antMatchers("/management").hasAnyRole("MANAGER","ADMIN")
.antMatchers("/page1").hasAnyAuthority("ROLE_ADMIN","ACCESS_PAGE1")
.antMatchers("/page2").hasAnyAuthority("ROLE_ADMIN","ACCESS_PAGE2")
.anyRequest().authenticated();
// .and()
// .formLogin()
// .loginPage("/login")
// .usernameParameter("username")
// .passwordParameter("password").successForwardUrl("/welcome")
// .permitAll();
}
#Bean
DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
daoAuthenticationProvider.setUserDetailsService(this.userDetailsService);
return daoAuthenticationProvider;
}
#Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
in above code, error lies here auth.authenticationProvider(authenticationProvider());
code is getting compiled fine but due to this i am getting 403 forbidden. Flow is getting broken here
JwtAutheticationFilter class is here
package com.sumit.Security;
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.auth0.jwt.JWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sumit.Repo.UserRepository;
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
LoginModel credentials = null;
try {
credentials = new ObjectMapper().readValue(request.getInputStream(), LoginModel.class);
} catch (Exception e) {
e.printStackTrace();
}
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
credentials.getUsername(), credentials.getPassword(), new ArrayList<>());
Authentication auth = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
return auth;
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
UserPrincipal principal = (UserPrincipal) authResult.getPrincipal();
String token = JWT.create()
.withSubject(principal.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + JWTProperties.EXPIRATION_TIME))
.sign(HMAC512(JWTProperties.SECRET.getBytes()));
response.addHeader(JWTProperties.HEADER_STRING, JWTProperties.TOKEN_PREFIX + token);
}
}
JwtAuthorizationFilter class is here
package com.sumit.Security;
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import com.auth0.jwt.JWT;
import com.sumit.Repo.UserRepository;
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
#Autowired
private UserRepository userRepository;
public JwtAuthorizationFilter(AuthenticationManager authenticationManager,UserRepository userRepository
) {
super(authenticationManager);
}
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
// Read the Authorization header, where the JWT token should be
String header = request.getHeader(JWTProperties.HEADER_STRING);
// If header does not contain BEARER or is null delegate to Spring impl and exit
if (header == null || !header.startsWith(JWTProperties.TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
// If header is present, try grab user principal from database and perform authorization
Authentication authentication = getUsernamePasswordAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
// Continue filter execution
chain.doFilter(request, response);
}
private Authentication getUsernamePasswordAuthentication(HttpServletRequest request) {
String token = request.getHeader(JWTProperties.HEADER_STRING)
.replace(JWTProperties.TOKEN_PREFIX,"");
if (token != null) {
// parse the token
String userName = JWT.require(HMAC512(JWTProperties.SECRET.getBytes()))
.build()
.verify(token)
.getSubject();
if (userName != null) {
User user = userRepository.findByUsername(userName);
UserPrincipal principal = new UserPrincipal(user);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userName, null, principal.getAuthorities());
return auth;
}
return null;
}
return null;
}
}
User registration process is working fine but authentication is not working because of above mentioned code.
I am using postman to verify it.
Don't know what trouble i am facing and totally frustrated.

How to make spring-boot 1.5.0 support this oauth2 solution?

I am using spring boot 1.5.0 with java 7 and am using following classes for implementation of Oauth for securing REST API
1) AuthorizationServerConfiguration.java
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;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static String REALM="MY_OAUTH_REALM";
#Autowired
private TokenStore tokenStore;
#Autowired
private UserApprovalHandler userApprovalHandler;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
int accessTokenMinutesValidity = 60;
int refreshTokenMinutesValidity = 24 * 60;
clients.inMemory()
.withClient("my-trusted-client")
.authorizedGrantTypes("password", "client_credentials", "refresh_token")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.secret("{noop}secret")
.accessTokenValiditySeconds(60 * accessTokenMinutesValidity ).//Access token is only valid for 60 minutes.
refreshTokenValiditySeconds(60 * refreshTokenMinutesValidity);//Refresh token is only valid for 24 hours
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.allowFormAuthenticationForClients()
.realm(REALM+"/client");
}
}
2) MethodSecurityConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Autowired
private OAuth2SecurityConfiguration securityConfig;
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
3) OAuth2SecurityConfiguration.java
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
#SuppressWarnings("deprecation")
#Configuration
#EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
private DataSource dataSource;
#Primary
#Bean
public DataSource customDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//dataSource properties set here
return dataSource;
}
#Bean
#ConfigurationProperties("spring.datasource")
public DataSource ds() {
return customDataSource();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
PasswordEncoder encoder = NoOpPasswordEncoder.getInstance();
BCryptPasswordEncoder enc;
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select USERNAME, ENC_PASSWD as PASSWORD, IS_ACTIVE AS ENABLED FROM USER_MSTR WHERE USERNAME=?")
.authoritiesByUsernameQuery("select USERNAME, 'ROLE_CLIENT' as ROLE from USER_MSTR where USERNAME=?")
.passwordEncoder(NoOpPasswordEncoder.getInstance())
;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}
4) ResourceServerConfiguration.java
import org.springframework.context.annotation.Configuration;
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.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.requestMatchers()
.antMatchers("/category_mstr/**", "/equipment/**", "/param_mstr/**", "/chklist_txn/**", "/settings/**", "/user/**")
.and().authorizeRequests()
.antMatchers("/category_mstr/**", "/equipment/**", "/param_mstr/**", "/chklist_txn/**", "/settings/**", "/user/**")
.access("hasRole('ROLE_CLIENT')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
However when accessing /oauth/token , I am getting error message saying "bad credentials" even when provided proper credentials
However if I use java 8 and spring boot 2.1.5 for same issue, then it runs fine and works as expected.
The old versions it was not necessary to add {noop} then remove it, since the latest versions work by using the password encoder {noop}.

How to get refresh token with grant type client_credentials

I am using spring-boot 2.5.0 for a REST API and implemented OAuth using following classes. I am aware that in grant type 'client_credentials' refresh token is not returned. However, the android team I am working with is adamant about having refresh token in grant type 'client_credentials' .
So I am seeking a way to get refresh tokens in client_credential
Currently , as per the default, I am only getting refresh_token in grant_type password.
The classes I am using :
1) AuthorizationServerConfiguration
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;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static String REALM="MY_OAUTH_REALM";
#Autowired
private TokenStore tokenStore;
#Autowired
private UserApprovalHandler userApprovalHandler;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
int accessTokenMinutesValidity = 60;
int refreshTokenMinutesValidity = 24 * 60;
clients.inMemory()
.withClient("my-trusted-client")
.authorizedGrantTypes("client_credentials", "refresh_token")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.secret("{noop}secret")
.accessTokenValiditySeconds(60 * accessTokenMinutesValidity ).//Access token is only valid for 60 minutes.
refreshTokenValiditySeconds(60 * refreshTokenMinutesValidity);//Refresh token is only valid for 24 hours
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.allowFormAuthenticationForClients()
.realm(REALM+"/client");
}
}
2) MethodSecurityConfig
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Autowired
private OAuth2SecurityConfiguration securityConfig;
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
3) OAuth2SecurityConfiguration
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
#SuppressWarnings("deprecation")
#Configuration
#EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
private DataSource dataSource;
#Primary
#Bean
public DataSource customDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dataSource.setUrl("<connection string>");
dataSource.setUsername("<username>");
dataSource.setPassword("<password>");
return dataSource;
}
#Bean
#ConfigurationProperties("spring.datasource")
public DataSource ds() {
//return DataSourceBuilder.create().build();
return customDataSource();
}
//USERS FROM DATABASE
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
PasswordEncoder encoder = NoOpPasswordEncoder.getInstance();
BCryptPasswordEncoder enc;
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select USERNAME, ENC_PASSWD as PASSWORD, IS_ACTIVE AS ENABLED FROM USER_MSTR WHERE USERNAME=?")
.authoritiesByUsernameQuery("select USERNAME, 'ROLE_CLIENT' as ROLE from USER_MSTR where USERNAME=?")
.passwordEncoder(NoOpPasswordEncoder.getInstance())
;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}
4) ResourceServerConfiguration
import org.springframework.context.annotation.Configuration;
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.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.requestMatchers()
.antMatchers("/category_mstr/**", "/equipment/**", "/param_mstr/**", "/chklist_txn/**", "/settings/**", "/user/**")
.and().authorizeRequests()
.antMatchers("/category_mstr/**", "/equipment/**", "/param_mstr/**", "/chklist_txn/**", "/settings/**", "/user/**")
.access("hasRole('ROLE_CLIENT')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
currently with grant_type = password, I am getting response as
{
"access_token": "25ca1254-4460-44bd-94c3-367f4b21e3b0",
"token_type": "bearer",
"refresh_token": "ef64adad-3772-4e0c-ae30-50358cdfffe1",
"expires_in": 3599,
"scope": "read trust write"
}
and with grant_type = client_credentials, I am getting response as
{
"access_token": "8c2bcdac-0a6b-4262-8664-75f1e0dc8351",
"token_type": "bearer",
"expires_in": 3599,
"scope": "read trust write"
}
How do I get response with refresh_token in above ??
I have tried extending ClientCredentialsAccessTokenProvider as follows
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider;
public class CCAccessTokenProvider extends ClientCredentialsAccessTokenProvider {
#Override
public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource) {
return true;
}
}
but I don't know where to fit it in my current architecture
--EDIT
I am seeking a solution to this critical issue and the other thread doesn't address it .

Spring Boot security getting Bad credentials error

I am new to Spring Boot Security and try to implement JWT based authentication & authorisation. I have made all the required setup configuration for spring security. Even with right credentials, from Spring Security I am getting error - Bad Credential.
I have hard coded the user details which need to be supplied for spring security (No database call).
My code is like below,
SpringConfig.java
package com.wocs.rest.controller;
//import com.example.polls.security.CustomUserDetailsService;
//import com.example.polls.security.JwtAuthenticationEntryPoint;
//import com.example.polls.security.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.wocs.rest.security.CustomUserDetailsService;
import com.wocs.rest.security.JwtAuthenticationEntryPoint;
import com.wocs.rest.security.JwtAuthenticationFilter;
/**
* Created by rajeevkumarsingh on 01/08/17.
*/
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
CustomUserDetailsService customUserDetailsService;
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
#Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/auth/login")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
CustomUserDetailsService.java
package com.wocs.rest.security;
import com.wocs.services.user.iface.UserServiceIface;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.transaction.annotation.Transactional;
/**
* Created by rajeevkumarsingh on 02/08/17.
*/
#Service
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserServiceIface userService;
public void setUserService(UserServiceIface userService) {
this.userService = userService;
}
#Override
#Transactional
public UserDetails loadUserByUsername(String loginIDorPhoneOrEmail)
throws UsernameNotFoundException {
// Let people login with either loginID or email or Phone
//User user = new User();
//UserPassword userPassword = new UserPassword();
List<String> permissions = new ArrayList<>();
permissions.add("P1");
permissions.add("P2");
permissions.add("P3");
UserDetails userDetails = UserPrincipal.create(115, loginIDorPhoneOrEmail,"222",true, permissions);
return userDetails;
}
}
JWTAuthenticationEntryPoint.java
package com.wocs.rest.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by rajeevkumarsingh on 07/12/17.
*/
#Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationEntryPoint.class);
#Override
public void commence(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
logger.error("Responding with unauthorized error. Message - {}", e.getMessage());
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Sorry, You're not authorized to access this resource.");
}
}
UserPrincipal.java
package com.wocs.rest.security;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class UserPrincipal implements UserDetails {
private int id;
private String username;
#JsonIgnore
private String password;
private boolean isCredentialNonExpired = false;
private Collection<? extends GrantedAuthority> authorities;
public UserPrincipal(int id, String username, String password, boolean isCredentialNonExpired, Collection<? extends GrantedAuthority> authorities) {
this.id = id;
this.username = username;
this.password = password;
this.authorities = authorities;
this.isCredentialNonExpired = isCredentialNonExpired;
}
public static UserPrincipal create(int userID, String userName, String password,boolean isCredentialNonExpired, List<String> permissions) {
List<GrantedAuthority> authorities = permissions.stream().map(permission ->
new SimpleGrantedAuthority(permission)
).collect(Collectors.toList());
return new UserPrincipal(
userID,
userName,
password,
isCredentialNonExpired,
authorities
);
}
public int getId() {
return id;
}
#Override
public String getUsername() {
return username;
}
#Override
public String getPassword() {
return password;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return isCredentialNonExpired;
}
#Override
public boolean isEnabled() {
return true;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserPrincipal that = (UserPrincipal) o;
return Objects.equals(id, that.id);
}
#Override
public int hashCode() {
return Objects.hash(id);
}
}
AuthController.java
#RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "text/plain")
public Map login(#RequestBody String stringRequestBody) throws JsonParseException, JsonMappingException, IOException, ServiceException
{
logger.info("Auth JSON Request:" + stringRequestBody);
Map<String, String> jsonMap = parseJSON(stringRequestBody);
String username = "rahul#gmail.com";
String password = "222";
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username,password)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication);
User user = userService.getUserByLoginIDOrPhoneOrEmail(username);
Map userDetail = new HashMap<String, Object>();
if (user != null) {
userDetail.put("user", user);
userDetail.put("userType", userService.getUserTypeByUserID(user.getID()));
userDetail.put("permissions", userService.getUserPermissions(user.getID()));
userDetail.put("token", jwt);
}
return userDetail;
}
I am trying to hit the api, but its throwing me:
{
"timestamp":"2018-08-08T08:42:14.575+0000",
"status":401,
"error":"Unauthorized",
"message":"Sorry, You're not authorized to access this resource.",
"path":"/auth/login"
}
Log error - Responding with unauthorized error. Message - Bad credentials
I had referred below link for spring security implementation
https://www.callicoder.com/spring-boot-spring-security-jwt-mysql-react-app-part-2/
Please Help me.

Resources