I am using Keycloak in my REST application with spring-boot.
It works correctly, I have defined roles in Keycloak, then in my Config.class I allow access to the end-points that interest me according to the role of each user. I have the problem when trying to retrieve the user information in my back (name, principal, authorities...).
I have read various SO POSTS like these:
how-to-get-principal-from-a-keycloak-secured-spring-boot-application
nullpointer-when-securing-spring-boot-rest-service-with-keycloak
but I can't find any that work for me. If I use SecurityContext or KeycloakAuthenticationToken, I get null when calling the getAuthentication method.
In my code, in Controller class I have the following:
private SecurityContext securityContext = SecurityContextHolder.getContext();
#GetMapping(value = "/getLicenses")
public ResponseEntity<List<License>> getLicenses() {
System.out.println("SecurityContext: " + securityContext);
System.out.println("Authentication securityContext: " + securityContext.getAuthentication());
return new ResponseEntity<List<License>>(licenseService.getLicenses(), null, HttpStatus.OK);
}
The output from console after access to /getLicenses is:
SecurityContext: org.springframework.security.core.context.SecurityContextImpl#ffffffff: Null authentication
Authentication securityContext: null
My KeycloakSecurityConfig.class
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity( prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/getLicenses").hasAnyRole("GUEST", "ADMIN", "SUPERADMIN")
.antMatchers("/getRevision/{id}").hasRole("SUPERADMIN")
.permitAll();
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
It works fine, if I try to access to /getRevision/{id} end-point with a 'GUEST' role user, it can't permit it.
My .yml has a BD connection, JPA and keycloak connection:
keycloak.auth-server-url : XXXX
keycloak.realm: XXXX
keycloak.resource: login
keycloak.public-client: true
And Keycloak has 3 users with 3 different roles (1 rol each user). I can do login with Postman
Does anyone know why I get null when trying to access SecurityContext?
My goal is to retrieve user data
You are initializing the securityContext object in your controller when the controller is first created:
private SecurityContext securityContext = SecurityContextHolder.getContext();
At that time, there is no security context available, meaning that the context is always null.
Don't use a private variable in a controller to store the context, instead, fetch it from the SecurityContextHolder in the getLicenses method:
#GetMapping(value = "/getLicenses")
public ResponseEntity<List<License>> getLicenses() {
SecurityContext securityContext = SecurityContextHolder.getContext();
System.out.println("SecurityContext: " + securityContext);
System.out.println("Authentication securityContext: " + securityContext.getAuthentication());
return new ResponseEntity<List<License>>(licenseService.getLicenses(), null, HttpStatus.OK);
}
Related
I am trying to add Facebook authorization using Spring Security in Spring Boot app. Currently, my problem is extracting data from Principal.
Here is my security config:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure (HttpSecurity http) throws Exception {
http
.csrf().disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**").permitAll()
.anyRequest().authenticated()
.and()
.logout()
.deleteCookies("JSESSIONID")
.clearAuthentication(true)
.logoutSuccessUrl("/").permitAll();
}
#Bean
public PrincipalExtractor facebookPrincipalExtractor(){
return new FacebookPrincipalExtractor();
}
}
and principal extractor:
public class FacebookPrincipalExtractor implements PrincipalExtractor {
#Autowired
UserService userService;
#Override
public Object extractPrincipal(Map<String, Object> map) {
String name = (String) map.get("name");
String id = (String) map.get("id");
User user = userService.findOne(id);
if (user == null) {
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
String token = ((OAuth2AuthenticationDetails) authentication.getDetails()).getTokenValue();
user = new User();
FacebookClient facebookClient = new DefaultFacebookClient(token, Version.VERSION_2_10);
JSONObject object = facebookClient.fetchObject("me", JSONObject.class);
// userService.createUser(object);
}
return user;
}
}
After login, the Map<String, Object> map contains only the name and id. Call to securityContext.getAuthentication() returns null.
Moreover, if I create something similar to the endpoint and pass the Principal there as a parameter, then this will work. Example:
#RequestMapping("/user")
public Principal user(Principal principal) {
return principal;
}
The principal will contain all the necessary data.
In this regard, 2 questions:
Why security context does not contain authentication?
Where does the principal come from if it is passed as a parameter to a method?
This is what the debug looks like inside
Although SecurityContextHolder.getContext() is never null the authentication it contains is cleared once a request is completed. What this means is that if you try to access it during a process which goes through the spring web security it will be there. But as soon as the request finishes the following gets logged
SecurityContextHolder now cleared, as request processing completed
and the authentication is set to null. Any attempts to access it directly through the SecurityContext outside of an http request will result in a null.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
authentication.getPrincipal();
use nested call for getting authentication object and then getPrincipal(); will return current loggedin user details
I am trying a develop a spring boot rest API with JWT authorization using spring security. I want all of my request to go through the filter to validate the JWT token except for the /authenticate request which should generate the jwt token. But with the below code, the /authenticate request is also getting intercepted by the filter due to which its failing with 401. Please let me know what am I missing in the below code.
JwtTokenFilter class
#Component
public class JwtTokenFilter extends OncePerRequestFilter
{
#Autowired
private UserService jwtUserDetailsService;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException
{
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
// JWT Token is in the form "Bearer token". Remove Bearer word and get
// only the Token
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer "))
{
jwtToken = requestTokenHeader.substring(7);
try
{
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
}
catch (IllegalArgumentException e)
{
System.out.println("Unable to get JWT Token");
}
catch (ExpiredJwtException e)
{
System.out.println("JWT Token has expired");
}
}
else
{
logger.warn("JWT Token does not begin with Bearer String");
}
// Once we get the token validate it.
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null)
{
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
// if token is valid configure Spring Security to manually set
// authentication
if (jwtTokenUtil.validateToken(jwtToken, userDetails))
{
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
JwtConfig class
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class JwtConfigurer extends WebSecurityConfigurerAdapter
{
#Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
#Autowired
private UserService jwtUserDetailsService;
#Autowired
private JwtTokenFilter jwtRequestFilter;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
// configure AuthenticationManager so that it knows from where to load
// user for matching credentials
// Use BCryptPasswordEncoder
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
// We don't need CSRF for this example
httpSecurity.csrf().disable().
// dont authenticate this particular request
authorizeRequests().antMatchers("/authenticate").permitAll().
// all other requests need to be authenticated
anyRequest().authenticated().and().
// make sure we use stateless session; session won't be used to
// store user's state.
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Add a filter to validate the tokens with every request
httpSecurity.addFilterAfter(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Controller class
#RestController
#CrossOrigin
public class JwtAuthenticationController
{
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Autowired
private UserService userDetailsService;
#RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(#RequestBody User authenticationRequest) throws Exception
{
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
User u = new User();
u.setUsername(authenticationRequest.getUsername());
u.setToken(token);
return ResponseEntity.ok(u);
}
private void authenticate(String username, String password) throws Exception
{
try
{
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
catch (DisabledException e)
{
throw new Exception("USER_DISABLED", e);
}
catch (BadCredentialsException e)
{
throw new Exception("INVALID_CREDENTIALS", e);
}
}
}
I struggled with this for two days and the best solution was the Tom answer combined with this setup on my SecurityConfig:
override fun configure(http: HttpSecurity?) {
// Disable CORS
http!!.cors().disable()
// Disable CSRF
http.csrf().disable()
// Set session management to stateless
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
//Add JwtTokenFilter
http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter::class.java)
}
Basically, OncePerRequestFilter works in that way only. Not sure if this can be avoided. Quoting the documentation :
Filter base class that aims to guarantee a single execution per
request dispatch, on any servlet container.
You can try adding the method type as well to skip teh authentication on the endpoint.
.antMatchers(HttpMethod.GET, "/authenticate").permitAll()
As already pointed by Mohit, even i couldn't see any mistakes in your configuration.
If you understand below explanation, it will help you to resolve.
Even though /authenticate request is permitAll configured the request should pass through your JWT Filter. But FilterSecurityInterceptor is the last filter it will check for configured antMatchers and associated restrictions/permissions based on that it will decide whether request should be permitted or denied.
For /authenticate method it should pass through filter and requestTokenHeader, username should be null and make sure chain.doFilter(request, response); is reaching without any exceptions.
And when it reaches FilterSecurityInterceptor and If you have set log level to debug) logs similar as given below should be printed.
DEBUG - /app/admin/app-config at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG - Checking match of request : '/app/admin/app-config'; against '/resources/**'
DEBUG - Checking match of request : '/app/admin/app-config'; against '/'
DEBUG - Checking match of request : '/app/admin/app-config'; against '/login'
DEBUG - Checking match of request : '/app/admin/app-config'; against '/api/**'
DEBUG - Checking match of request : '/app/admin/app-config'; against '/app/admin/app-config'
DEBUG - Secure object: FilterInvocation: URL: /app/admin/app-config; Attributes: [permitAll]
DEBUG - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#511cd205: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#2cd90: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 696171A944493ACA1A0F7D560D93D42B; Granted Authorities: ROLE_ANONYMOUS
DEBUG - Voter: org.springframework.security.web.access.expression.WebExpressionVoter#6df827bf, returned: 1
DEBUG - Authorization successful
Attach those logs, so that then problem can be predicted.
Write a configuration class that implements org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter and override the configur method like so:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// dont authenticate this particular request. you can use a wild card here. e.g /unprotected/**
httpSecurity.csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll().
//authenticate everything else
anyRequest().authenticated().and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Add a filter to validate the tokens with every request
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
I had similar problem, and I overcome it by comparing request path to the path I do not want to filter.
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//To skip OncePerRequestFilter for authenticate endpoint
if(request.getServletPath().equals("/authenticate")){
filterChain.doFilter(request, response);
return;
}
// filter logic continue..
I'm trying to access a Spring App via Keycloak, but I always get a 401 Unauthorized error. Basically I have a chat module that works fine on its own, but once I add Keycloak I'm unable to access the app due to that 401 error.
I've followed about 3 tutorials that showed similar things to what I've done, and I still have no idea what I've done wrong.
Here's my app's config :
keycloak:
enabled: true
realm: myReal
resource: myReal-api
public-client: true
bearer-only: true
auth-server-url: http://localhost:8080/auth
credentials:
secret: 82eXXXXX-3XXX-4XXX-XXX7-287aXXXXXXXX
principal-attribute: preferred_username
cors: true
From localhost:port/ I have a first interface (with no Keycloak safety) that has a link to my service, which is localhost:port/index/{topicName} . Now when I click on that link, I'm supposed to get the Keycloak authentication screen, but I get a 401 error instead.
I've checked the header of my request, adding a HttpServletRequest as a parameter to my displayMessage method, and I actually could display the access_token and the X-Auth-Token in my IDE's console. But it seems like when I follow that link, it sends the request without the token.
Here are my controller methods (my Controller class is annotated with #Controller:
#GetMapping(path = "/")
public String index() {
return "external";
}
#GetMapping(path = "/index/{topicName}",
produces = MediaType.APPLICATION_JSON_VALUE)
public String displayMessages(Model model,
#PathVariable String topicName) {
//HttpHeaders headers = new HttpHeaders();
//headers.set("Authorization", request.getHeader("Authorization"));
//header = request.getHeader("Authorization");
//System.out.println(" T O K E N "+request.getHeader("X-Auth-Token"));
projectServiceImpl.findByName(topicName);
List<Message> messages = messageServiceImpl.findAllMessagesByProjectName(topicName);
model.addAttribute("topic", topicName);
model.addAttribute("message",messages);
return "index";
}
My Keycloak config file is inspired from the tuto's I've read, so there might be a mistake in there that I don't know about (not sure what the difference between methods access and hasRole is) :
#Configuration
#ComponentScan(
basePackageClasses = KeycloakSecurityComponents.class,
excludeFilters = #ComponentScan.Filter(
type = FilterType.REGEX,
pattern = "org.keycloak.adapters.springsecurity.management.HttpSessionManager"))
#EnableWebSecurity
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
#Bean
public HttpSessionIdResolver httpSessionIdResolver() { //replace HttpSessionStrategy
return HeaderHttpSessionIdResolver.xAuthToken();
}
//Registers the KeycloakAuthenticationProvider with the authentication manager.
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
try {
SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
grantedAuthorityMapper.setPrefix("ROLE_");
grantedAuthorityMapper.setConvertToUpperCase(true);
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);
auth.authenticationProvider(keycloakAuthenticationProvider());
} catch(Exception ex) {
logger.error("SecurityConfig.configureGlobal: " + ex);
}
/*try {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}catch(Exception ex){
logger.error("SecurityConfig.configureGlobal: " +ex);
}*/
}
//Load Keycloak properties from service config-file
#Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
//Defines the session authentication strategy.
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
//Public or Confidential application keycloak/OpenID Connect client
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
//Bearer mode only keycloak/OpenID Connect client without keycloak session -> stateless behavior
//return new NullAuthenticatedSessionStrategy();
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
super.configure(http);
http.authorizeRequests()
//BEGIN
//USER -done to be tested
.antMatchers(HttpMethod.GET,"/index**").access("hasAuthority('ADMIN')")
.antMatchers(HttpMethod.GET,"/").access("hasAuthority('ADMIN')")
.antMatchers(HttpMethod.GET,"/").access("hasAnyAuthority('ADMIN','MANAGER','EXPERT','STANDARD')")
.anyRequest().authenticated()
.and()
.cors()
.and()
.csrf().disable()
//BEGIN Login/Logout
.formLogin()
.permitAll()//.successHandler(authenticationSuccessHandler) //
.and()
.logout()//.clearAuthentication(true) //Add .clearAuthentication(true) to logout()
//.logoutUrl("/custom-logout")
.addLogoutHandler(keycloakLogoutHandler())
//.addLogoutHandler(new LogoutHandlerImpl())
.clearAuthentication(true)
.invalidateHttpSession(true)
.permitAll();
//END Login/Logout
//BEGIN Session
http
.sessionManagement()
//.sessionCreationPolicy(SessionCreationPolicy.ALWAYS) //BY default IF_REQUIRED
.maximumSessions(1)
.maxSessionsPreventsLogin(false) // if true generate an error when user login after reaching maximumSession (SessionAuthenticationStrategy rejected the authentication object / SessionAuthenticationException: Maximum sessions of 1 for this principal exceeded)
//.expiredUrl("/auth/login")
.sessionRegistry(sessionRegistry());
}
#Bean
#Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken accessToken() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
return ((KeycloakSecurityContext) ((KeycloakAuthenticationToken) request.getUserPrincipal()).getCredentials()).getToken();
}
///BEGIN session
#Bean
public SessionRegistry sessionRegistry() {
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
#Bean
public RegisterSessionAuthenticationStrategy registerSessionAuthStr( ) {
return new RegisterSessionAuthenticationStrategy( sessionRegistry( ) );
}
// Register HttpSessionEventPublisher
#Bean
public static ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}
I don't really know what else I should change to make it work, but I believe there has to be something wrong in there. But I think if I can have the Keycloak authentication screen when trying to access my service, this would be alright.
I received the same error, one thing to double check is that auth-server-url is the same for the server, and the client getting the token.
I.e. if one is the dns name, and one is the IP address, it will not authorize. (in my case I had localhost and 127.0.0.1 so authorization failed)
Server, src/main/resources/application.yml
Postman/client:
This solved my issue. I was using within a docker container and had to match both to host.docker.internal
I'm using spring basic authentication with a custom authentication provider:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider authProvider;
#Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
And
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
if (customauth()) { // use the credentials
// and authenticate against the third-party system
{
return new UsernamePasswordAuthenticationToken(
name, password, new ArrayList<>());
}
} else {
return null;
}
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(
UsernamePasswordAuthenticationToken.class
);
}
To test this I'm using postman with the following tests:
invalid credentials -> 401 unauthorized
correct credentials -> 200 OK
invalid credentials -> 200 OK
My problem is that the last request should return 401 unauthorized and every following request after a successful login is 200 OK even with a wrong token and without token.
Thanks in advance.
When you logged in successfully, Spring Security will create an Authentication object and will put it in SecurityContext in your HTTP session. As far as you have a valid session with a valid Authentication object at the server, Spring Security won't authenticate your request again and will use the Authentication object saved in your session.
This is a Spring Security feature, see SEC-53:
Check the SecurityContextHolder for an authenticated Authentication and reuse it in that case, do not call the authentication manager again.
If you like to reauthenticate, you could
use no session at all
logout before reauthenticate
In both cases Spring Security will not find an authenticated user saved in the session and will use the new username and password for authentication.
I have been trying to authenticate my service by spring security. For that I am using filter as
This is the Security configuration I have been Using: In this configuration I am filtering all requests and permitting all , by authentication. For Authentication I have login page. In the login form I have use 'username' for email and 'password' for password for the attribute names respectively.
public class LoginAuthenticate extends WebSecurityConfigurerAdapter{
#Autowired
#Qualifier("userDetailsService")
MyUserDetailService userDetailsService;
#Autowired
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
System.out.println("reaching");
}
#Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/success")
.failureUrl("/")
.permitAll()
.and()
.logout()
.permitAll().and().csrf().disable();
}
#Bean
public PasswordEncoder passwordEncoder(){
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
This is my program structure
And for implementing UserDEtailService I did the following
This is my UserDetailsService which I overrided, I have autowired the repository to get the email address and password from the database[ using email as username] and then created a userdetails user object with the username and password and returned that object. When the use inputs the username and password in login page then I should be able to authenticate using the details with the details pulled from the database like the email and password of the user should match the email and password retrieved from the db.But the problem is I couldnt fire the authenticate method in spring security configuration:
#Service("userDetailsService")
public class MyUserDetailService implements UserDetailsService{
#Autowired
IUsers userrepo;
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userrepo.finduserByUserName(username);
if (user == null) {
return null;
}
List<GrantedAuthority> auth = AuthorityUtils
.commaSeparatedStringToAuthorityList("ROLE_USER");
if (username.equals("admin")) {
auth = AuthorityUtils
.commaSeparatedStringToAuthorityList("ROLE_ADMIN");
}
String password = user.getLoginPassword();
String Email = user.getEmailAddress();
System.out.println(password+ " "+ Email);
return new org.springframework.security.core.userdetails.User(Email,password,auth);
}
}
But My authentication function is not evaluating the user!
Can someone help me what is going wrong here. There are no errors to debug. I consoled out if reaching authentication function , but not reaching. I tried every possible thing on internet on this custom login with JPA but my effort didn't turn up anything to be fruitful.
In class LoginAuthenticate: remove #Autowired before void configure(AuthenticationManagerBuilder auth),
add annotation for this class
#Configuration
#EnableWebSecurity
In class MyUserDetailService.loadUserByUsername: change
if (user == null) {
return null;
}
to
if (user == null) {
throw new UsernameNotFoundException ("User not found");
}