springboot bearer token authentication giving 401












1














I am new to Spring boot so please help me. I have got it working to the point where I am able to generate a Bearer Token with an unauthenticated request. Next I want to use this token to use with an endpoint so that my request is authenticated - this is where my trouble is coming in. I am always getting a 401, looks like something is wrong with my config. Here is my code



public class ApplicationUser {

private String username;
private String password;
private String role;

public ApplicationUser(String username, String password, String role) {
this.username = username;
this.password = password;
this.role = role;
}

public String getUsername() {
return username;
}

public String getPassword() {
return password;
}

public String getRole() {
return role;
}
}


JwtConfig Class:



@Component("jwtConfig")
public class JwtConfig {
@Value("${security.jwt.uri:/auth/**}")
private String Uri;

@Value("${security.jwt.header:Authorization}")
private String header;

@Value("${security.jwt.prefix:Bearer }")
private String prefix;

@Value("${security.jwt.expiration:#{24*60*60}}")
private int expiration;

@Value("${security.jwt.secret:JwtSecretKey}")
private String secret;

public String getUri() {
return Uri;
}

public String getHeader() {
return header;
}

public String getPrefix() {
return prefix;
}

public int getExpiration() {
return expiration;
}

public String getSecret() {
return secret;
}


}



JwtTokenAuthenticationFilter



public class JwtTokenAuthenticationFilter extends  OncePerRequestFilter {

private final JwtConfig jwtConfig;

public JwtTokenAuthenticationFilter(JwtConfig jwtConfig) {
this.jwtConfig = jwtConfig;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {

// 1. get the authentication header. Tokens are supposed to be passed in the authentication header
String header = request.getHeader(jwtConfig.getHeader());

// 2. validate the header and check the prefix
if(header == null || !header.startsWith(jwtConfig.getPrefix())) {
chain.doFilter(request, response); // If not valid, go to the next filter.
return;
}

// If there is no token provided and hence the user won't be authenticated.
// It's Ok. Maybe the user accessing a public path or asking for a token.

// All secured paths that needs a token are already defined and secured in config class.
// And If user tried to access without access token, then he won't be authenticated and an exception will be thrown.

// 3. Get the token
String token = header.replace(jwtConfig.getPrefix(), "");

try { // exceptions might be thrown in creating the claims if for example the token is expired

// 4. Validate the token
Claims claims = Jwts.parser()
.setSigningKey(jwtConfig.getSecret().getBytes())
.parseClaimsJws(token)
.getBody();

String username = claims.getSubject();
if(username != null) {
@SuppressWarnings("unchecked")
List<String> authorities = (List<String>) claims.get("authorities");

// 5. Create auth object
// UsernamePasswordAuthenticationToken: A built-in object, used by spring to represent the current authenticated / being authenticated user.
// It needs a list of authorities, which has type of GrantedAuthority interface, where SimpleGrantedAuthority is an implementation of that interface
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
username, null, authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));

// 6. Authenticate the user
// Now, user is authenticated
SecurityContextHolder.getContext().setAuthentication(auth);
}

} catch (Exception e) {
// In case of failure. Make sure it's clear; so guarantee user won't be authenticated
SecurityContextHolder.clearContext();
}

// go to the next filter in the filter chain
chain.doFilter(request, response);
}

}


JwtUsernameAndPasswordAuthenticationFilter



public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter   {

// We use auth manager to validate the user credentials
private AuthenticationManager authManager;

private final JwtConfig jwtConfig;

public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authManager, JwtConfig jwtConfig) {
this.authManager = authManager;
this.jwtConfig = jwtConfig;

// By default, UsernamePasswordAuthenticationFilter listens to "/login" path.
// In our case, we use "/auth". So, we need to override the defaults.
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(jwtConfig.getUri(), "POST"));
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {

try {

// 1. Get credentials from request
UserCredentials creds = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class);

// 2. Create auth object (contains credentials) which will be used by auth manager
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
creds.getUsername(), creds.getPassword(), Collections.emptyList());

// 3. Authentication manager authenticate the user, and use UserDetialsServiceImpl::loadUserByUsername() method to load the user.
return authManager.authenticate(authToken);

} catch (IOException e) {
throw new RuntimeException(e);
}
}

// Upon successful authentication, generate a token.
// The 'auth' passed to successfulAuthentication() is the current authenticated user.
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) throws IOException, ServletException {

Long now = System.currentTimeMillis();
String token = Jwts.builder()
.setSubject(auth.getName())
// Convert to list of strings.
// This is important because it affects the way we get them back in the Gateway.
.claim("authorities", auth.getAuthorities().stream()
.map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
.setIssuedAt(new Date(now))
.setExpiration(new Date(now + jwtConfig.getExpiration() * 1000)) // in milliseconds
.signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())
.compact();

// Add token to header
response.addHeader(jwtConfig.getHeader(), jwtConfig.getPrefix() + token);
}

// A (temporary) class just to represent the user credentials
private static class UserCredentials {
private String username, password;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}
}


SecurityCredentialsConfig



@Configuration
@EnableWebSecurity(debug=true)
public class SecurityCredentialsConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsServiceImpl userDetailsService;

@Autowired
private JwtConfig jwtConfig;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
// make sure we use stateless session; session won't be used to store user's state.
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// handle an authorized attempts
.exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.and()
// Add a filter to validate user credentials and add token in the response header

// What's the authenticationManager()?
// An object provided by WebSecurityConfigurerAdapter, used to authenticate the user passing user's credentials
// The filter needs this auth manager to authenticate the user.
.addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig))
.authorizeRequests()
// allow all POST requests
.antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
// any other requests must be authenticated
// .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
.anyRequest().authenticated();
}

// Spring has UserDetailsService interface, which can be overriden to provide our implementation for fetching user from database (or any other source).
// The UserDetailsService object is used by the auth manager to load the user from database.
// In addition, we need to define the password encoder also. So, auth manager can compare and verify passwords.
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}


UserDetailsServiceImpl



@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private BCryptPasswordEncoder encoder;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final List<ApplicationUser> users = Arrays.asList(
new ApplicationUser("omar",encoder.encode("12345"), "USER"),
new ApplicationUser("admin", encoder.encode("12345"), "ADMIN")
);

for(ApplicationUser appUser: users) {
if(appUser.getUsername().equals(username)) {
List<GrantedAuthority> grantedAuthorities = AuthorityUtils
.commaSeparatedStringToAuthorityList( appUser.getRole());

return new User(appUser.getUsername(), appUser.getPassword(), grantedAuthorities);
}
}

// If user not found. Throw this exception.
throw new UsernameNotFoundException("Username: " + username + " not found");

}
}


WebSecurity



@EnableWebSecurity(debug=true)
@Order(1000)
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Autowired
private JwtConfig jwtConfig;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
// make sure we use stateless session; session won't be used to store user's state.
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// handle an authorized attempts
.exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.and()
// Add a filter to validate the tokens with every request
.addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
// authorization requests config
.authorizeRequests()
// allow all who are accessing "auth" service
.antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
// must be an admin if trying to access admin area (authentication is also required here)
.antMatchers("/v1/cooks").access("hasRole('ADMIN')")
//for other uris
// .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
// Any other request must be authenticated
.anyRequest().authenticated();
}


}



Controller



@RestController


public class CookController {

@Autowired
private CookService cookService;
// Get All Cooks
@GetMapping("/v1/cooks")
public List<Cook> getAllCooks(){
return cookService.getAllCooks();
}


application.properties



zuul.routes.auth-service.path=/auth/**
zuul.routes.auth-service.service-id=AUTH-SERVICE
zuul.routes.auth-service.strip-prefix=false
zuul.routes.auth-service.sensitive-headers=Cookie,Set-Cookie

spring.application.name=auth-service
server.port=9100
eureka.client.service-url.default-zone=http://localhost:8761/eureka


the call to v1/cooks always returns 401.
What part of the configuration I am missing? I followed the documentation at https://medium.com/omarelgabrys-blog/microservices-with-spring-boot-authentication-with-jwt-part-3-fafc9d7187e8



but I am completely lost now.
Request url is
GET http://localhost:9100/v1/cooks



Response is
{
"timestamp": "2018-10-13T20:08:13.804+0000",
"status": 401,
"error": "Unauthorized",
"message": "No message available",
"path": "/v1/cooks"
}



pom.xml



 <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0-b170201.1204</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>


EDIT: Added application.properties and dependies from pom










share|improve this question





























    1














    I am new to Spring boot so please help me. I have got it working to the point where I am able to generate a Bearer Token with an unauthenticated request. Next I want to use this token to use with an endpoint so that my request is authenticated - this is where my trouble is coming in. I am always getting a 401, looks like something is wrong with my config. Here is my code



    public class ApplicationUser {

    private String username;
    private String password;
    private String role;

    public ApplicationUser(String username, String password, String role) {
    this.username = username;
    this.password = password;
    this.role = role;
    }

    public String getUsername() {
    return username;
    }

    public String getPassword() {
    return password;
    }

    public String getRole() {
    return role;
    }
    }


    JwtConfig Class:



    @Component("jwtConfig")
    public class JwtConfig {
    @Value("${security.jwt.uri:/auth/**}")
    private String Uri;

    @Value("${security.jwt.header:Authorization}")
    private String header;

    @Value("${security.jwt.prefix:Bearer }")
    private String prefix;

    @Value("${security.jwt.expiration:#{24*60*60}}")
    private int expiration;

    @Value("${security.jwt.secret:JwtSecretKey}")
    private String secret;

    public String getUri() {
    return Uri;
    }

    public String getHeader() {
    return header;
    }

    public String getPrefix() {
    return prefix;
    }

    public int getExpiration() {
    return expiration;
    }

    public String getSecret() {
    return secret;
    }


    }



    JwtTokenAuthenticationFilter



    public class JwtTokenAuthenticationFilter extends  OncePerRequestFilter {

    private final JwtConfig jwtConfig;

    public JwtTokenAuthenticationFilter(JwtConfig jwtConfig) {
    this.jwtConfig = jwtConfig;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
    throws ServletException, IOException {

    // 1. get the authentication header. Tokens are supposed to be passed in the authentication header
    String header = request.getHeader(jwtConfig.getHeader());

    // 2. validate the header and check the prefix
    if(header == null || !header.startsWith(jwtConfig.getPrefix())) {
    chain.doFilter(request, response); // If not valid, go to the next filter.
    return;
    }

    // If there is no token provided and hence the user won't be authenticated.
    // It's Ok. Maybe the user accessing a public path or asking for a token.

    // All secured paths that needs a token are already defined and secured in config class.
    // And If user tried to access without access token, then he won't be authenticated and an exception will be thrown.

    // 3. Get the token
    String token = header.replace(jwtConfig.getPrefix(), "");

    try { // exceptions might be thrown in creating the claims if for example the token is expired

    // 4. Validate the token
    Claims claims = Jwts.parser()
    .setSigningKey(jwtConfig.getSecret().getBytes())
    .parseClaimsJws(token)
    .getBody();

    String username = claims.getSubject();
    if(username != null) {
    @SuppressWarnings("unchecked")
    List<String> authorities = (List<String>) claims.get("authorities");

    // 5. Create auth object
    // UsernamePasswordAuthenticationToken: A built-in object, used by spring to represent the current authenticated / being authenticated user.
    // It needs a list of authorities, which has type of GrantedAuthority interface, where SimpleGrantedAuthority is an implementation of that interface
    UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
    username, null, authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));

    // 6. Authenticate the user
    // Now, user is authenticated
    SecurityContextHolder.getContext().setAuthentication(auth);
    }

    } catch (Exception e) {
    // In case of failure. Make sure it's clear; so guarantee user won't be authenticated
    SecurityContextHolder.clearContext();
    }

    // go to the next filter in the filter chain
    chain.doFilter(request, response);
    }

    }


    JwtUsernameAndPasswordAuthenticationFilter



    public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter   {

    // We use auth manager to validate the user credentials
    private AuthenticationManager authManager;

    private final JwtConfig jwtConfig;

    public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authManager, JwtConfig jwtConfig) {
    this.authManager = authManager;
    this.jwtConfig = jwtConfig;

    // By default, UsernamePasswordAuthenticationFilter listens to "/login" path.
    // In our case, we use "/auth". So, we need to override the defaults.
    this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(jwtConfig.getUri(), "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
    throws AuthenticationException {

    try {

    // 1. Get credentials from request
    UserCredentials creds = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class);

    // 2. Create auth object (contains credentials) which will be used by auth manager
    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
    creds.getUsername(), creds.getPassword(), Collections.emptyList());

    // 3. Authentication manager authenticate the user, and use UserDetialsServiceImpl::loadUserByUsername() method to load the user.
    return authManager.authenticate(authToken);

    } catch (IOException e) {
    throw new RuntimeException(e);
    }
    }

    // Upon successful authentication, generate a token.
    // The 'auth' passed to successfulAuthentication() is the current authenticated user.
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
    Authentication auth) throws IOException, ServletException {

    Long now = System.currentTimeMillis();
    String token = Jwts.builder()
    .setSubject(auth.getName())
    // Convert to list of strings.
    // This is important because it affects the way we get them back in the Gateway.
    .claim("authorities", auth.getAuthorities().stream()
    .map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
    .setIssuedAt(new Date(now))
    .setExpiration(new Date(now + jwtConfig.getExpiration() * 1000)) // in milliseconds
    .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())
    .compact();

    // Add token to header
    response.addHeader(jwtConfig.getHeader(), jwtConfig.getPrefix() + token);
    }

    // A (temporary) class just to represent the user credentials
    private static class UserCredentials {
    private String username, password;

    public String getUsername() {
    return username;
    }

    public void setUsername(String username) {
    this.username = username;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }
    }
    }


    SecurityCredentialsConfig



    @Configuration
    @EnableWebSecurity(debug=true)
    public class SecurityCredentialsConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private JwtConfig jwtConfig;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http
    .csrf().disable()
    // make sure we use stateless session; session won't be used to store user's state.
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
    // handle an authorized attempts
    .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
    .and()
    // Add a filter to validate user credentials and add token in the response header

    // What's the authenticationManager()?
    // An object provided by WebSecurityConfigurerAdapter, used to authenticate the user passing user's credentials
    // The filter needs this auth manager to authenticate the user.
    .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig))
    .authorizeRequests()
    // allow all POST requests
    .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
    // any other requests must be authenticated
    // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
    .anyRequest().authenticated();
    }

    // Spring has UserDetailsService interface, which can be overriden to provide our implementation for fetching user from database (or any other source).
    // The UserDetailsService object is used by the auth manager to load the user from database.
    // In addition, we need to define the password encoder also. So, auth manager can compare and verify passwords.
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
    }
    }


    UserDetailsServiceImpl



    @Service
    public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private BCryptPasswordEncoder encoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    final List<ApplicationUser> users = Arrays.asList(
    new ApplicationUser("omar",encoder.encode("12345"), "USER"),
    new ApplicationUser("admin", encoder.encode("12345"), "ADMIN")
    );

    for(ApplicationUser appUser: users) {
    if(appUser.getUsername().equals(username)) {
    List<GrantedAuthority> grantedAuthorities = AuthorityUtils
    .commaSeparatedStringToAuthorityList( appUser.getRole());

    return new User(appUser.getUsername(), appUser.getPassword(), grantedAuthorities);
    }
    }

    // If user not found. Throw this exception.
    throw new UsernameNotFoundException("Username: " + username + " not found");

    }
    }


    WebSecurity



    @EnableWebSecurity(debug=true)
    @Order(1000)
    public class WebSecurity extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtConfig jwtConfig;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http
    .csrf().disable()
    // make sure we use stateless session; session won't be used to store user's state.
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
    // handle an authorized attempts
    .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
    .and()
    // Add a filter to validate the tokens with every request
    .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
    // authorization requests config
    .authorizeRequests()
    // allow all who are accessing "auth" service
    .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
    // must be an admin if trying to access admin area (authentication is also required here)
    .antMatchers("/v1/cooks").access("hasRole('ADMIN')")
    //for other uris
    // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
    // Any other request must be authenticated
    .anyRequest().authenticated();
    }


    }



    Controller



    @RestController


    public class CookController {

    @Autowired
    private CookService cookService;
    // Get All Cooks
    @GetMapping("/v1/cooks")
    public List<Cook> getAllCooks(){
    return cookService.getAllCooks();
    }


    application.properties



    zuul.routes.auth-service.path=/auth/**
    zuul.routes.auth-service.service-id=AUTH-SERVICE
    zuul.routes.auth-service.strip-prefix=false
    zuul.routes.auth-service.sensitive-headers=Cookie,Set-Cookie

    spring.application.name=auth-service
    server.port=9100
    eureka.client.service-url.default-zone=http://localhost:8761/eureka


    the call to v1/cooks always returns 401.
    What part of the configuration I am missing? I followed the documentation at https://medium.com/omarelgabrys-blog/microservices-with-spring-boot-authentication-with-jwt-part-3-fafc9d7187e8



    but I am completely lost now.
    Request url is
    GET http://localhost:9100/v1/cooks



    Response is
    {
    "timestamp": "2018-10-13T20:08:13.804+0000",
    "status": 401,
    "error": "Unauthorized",
    "message": "No message available",
    "path": "/v1/cooks"
    }



    pom.xml



     <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.restdocs</groupId>
    <artifactId>spring-restdocs-mockmvc</artifactId>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.16</version>
    <scope>provided</scope>
    </dependency>
    <dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0-b170201.1204</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
    </dependency>
    </dependencies>


    EDIT: Added application.properties and dependies from pom










    share|improve this question



























      1












      1








      1







      I am new to Spring boot so please help me. I have got it working to the point where I am able to generate a Bearer Token with an unauthenticated request. Next I want to use this token to use with an endpoint so that my request is authenticated - this is where my trouble is coming in. I am always getting a 401, looks like something is wrong with my config. Here is my code



      public class ApplicationUser {

      private String username;
      private String password;
      private String role;

      public ApplicationUser(String username, String password, String role) {
      this.username = username;
      this.password = password;
      this.role = role;
      }

      public String getUsername() {
      return username;
      }

      public String getPassword() {
      return password;
      }

      public String getRole() {
      return role;
      }
      }


      JwtConfig Class:



      @Component("jwtConfig")
      public class JwtConfig {
      @Value("${security.jwt.uri:/auth/**}")
      private String Uri;

      @Value("${security.jwt.header:Authorization}")
      private String header;

      @Value("${security.jwt.prefix:Bearer }")
      private String prefix;

      @Value("${security.jwt.expiration:#{24*60*60}}")
      private int expiration;

      @Value("${security.jwt.secret:JwtSecretKey}")
      private String secret;

      public String getUri() {
      return Uri;
      }

      public String getHeader() {
      return header;
      }

      public String getPrefix() {
      return prefix;
      }

      public int getExpiration() {
      return expiration;
      }

      public String getSecret() {
      return secret;
      }


      }



      JwtTokenAuthenticationFilter



      public class JwtTokenAuthenticationFilter extends  OncePerRequestFilter {

      private final JwtConfig jwtConfig;

      public JwtTokenAuthenticationFilter(JwtConfig jwtConfig) {
      this.jwtConfig = jwtConfig;
      }

      @Override
      protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
      throws ServletException, IOException {

      // 1. get the authentication header. Tokens are supposed to be passed in the authentication header
      String header = request.getHeader(jwtConfig.getHeader());

      // 2. validate the header and check the prefix
      if(header == null || !header.startsWith(jwtConfig.getPrefix())) {
      chain.doFilter(request, response); // If not valid, go to the next filter.
      return;
      }

      // If there is no token provided and hence the user won't be authenticated.
      // It's Ok. Maybe the user accessing a public path or asking for a token.

      // All secured paths that needs a token are already defined and secured in config class.
      // And If user tried to access without access token, then he won't be authenticated and an exception will be thrown.

      // 3. Get the token
      String token = header.replace(jwtConfig.getPrefix(), "");

      try { // exceptions might be thrown in creating the claims if for example the token is expired

      // 4. Validate the token
      Claims claims = Jwts.parser()
      .setSigningKey(jwtConfig.getSecret().getBytes())
      .parseClaimsJws(token)
      .getBody();

      String username = claims.getSubject();
      if(username != null) {
      @SuppressWarnings("unchecked")
      List<String> authorities = (List<String>) claims.get("authorities");

      // 5. Create auth object
      // UsernamePasswordAuthenticationToken: A built-in object, used by spring to represent the current authenticated / being authenticated user.
      // It needs a list of authorities, which has type of GrantedAuthority interface, where SimpleGrantedAuthority is an implementation of that interface
      UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
      username, null, authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));

      // 6. Authenticate the user
      // Now, user is authenticated
      SecurityContextHolder.getContext().setAuthentication(auth);
      }

      } catch (Exception e) {
      // In case of failure. Make sure it's clear; so guarantee user won't be authenticated
      SecurityContextHolder.clearContext();
      }

      // go to the next filter in the filter chain
      chain.doFilter(request, response);
      }

      }


      JwtUsernameAndPasswordAuthenticationFilter



      public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter   {

      // We use auth manager to validate the user credentials
      private AuthenticationManager authManager;

      private final JwtConfig jwtConfig;

      public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authManager, JwtConfig jwtConfig) {
      this.authManager = authManager;
      this.jwtConfig = jwtConfig;

      // By default, UsernamePasswordAuthenticationFilter listens to "/login" path.
      // In our case, we use "/auth". So, we need to override the defaults.
      this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(jwtConfig.getUri(), "POST"));
      }

      @Override
      public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
      throws AuthenticationException {

      try {

      // 1. Get credentials from request
      UserCredentials creds = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class);

      // 2. Create auth object (contains credentials) which will be used by auth manager
      UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
      creds.getUsername(), creds.getPassword(), Collections.emptyList());

      // 3. Authentication manager authenticate the user, and use UserDetialsServiceImpl::loadUserByUsername() method to load the user.
      return authManager.authenticate(authToken);

      } catch (IOException e) {
      throw new RuntimeException(e);
      }
      }

      // Upon successful authentication, generate a token.
      // The 'auth' passed to successfulAuthentication() is the current authenticated user.
      @Override
      protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
      Authentication auth) throws IOException, ServletException {

      Long now = System.currentTimeMillis();
      String token = Jwts.builder()
      .setSubject(auth.getName())
      // Convert to list of strings.
      // This is important because it affects the way we get them back in the Gateway.
      .claim("authorities", auth.getAuthorities().stream()
      .map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
      .setIssuedAt(new Date(now))
      .setExpiration(new Date(now + jwtConfig.getExpiration() * 1000)) // in milliseconds
      .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())
      .compact();

      // Add token to header
      response.addHeader(jwtConfig.getHeader(), jwtConfig.getPrefix() + token);
      }

      // A (temporary) class just to represent the user credentials
      private static class UserCredentials {
      private String username, password;

      public String getUsername() {
      return username;
      }

      public void setUsername(String username) {
      this.username = username;
      }

      public String getPassword() {
      return password;
      }

      public void setPassword(String password) {
      this.password = password;
      }
      }
      }


      SecurityCredentialsConfig



      @Configuration
      @EnableWebSecurity(debug=true)
      public class SecurityCredentialsConfig extends WebSecurityConfigurerAdapter {

      @Autowired
      private UserDetailsServiceImpl userDetailsService;

      @Autowired
      private JwtConfig jwtConfig;

      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http
      .csrf().disable()
      // make sure we use stateless session; session won't be used to store user's state.
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and()
      // handle an authorized attempts
      .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
      .and()
      // Add a filter to validate user credentials and add token in the response header

      // What's the authenticationManager()?
      // An object provided by WebSecurityConfigurerAdapter, used to authenticate the user passing user's credentials
      // The filter needs this auth manager to authenticate the user.
      .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig))
      .authorizeRequests()
      // allow all POST requests
      .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
      // any other requests must be authenticated
      // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
      .anyRequest().authenticated();
      }

      // Spring has UserDetailsService interface, which can be overriden to provide our implementation for fetching user from database (or any other source).
      // The UserDetailsService object is used by the auth manager to load the user from database.
      // In addition, we need to define the password encoder also. So, auth manager can compare and verify passwords.
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
      }

      @Bean
      public BCryptPasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
      }
      }


      UserDetailsServiceImpl



      @Service
      public class UserDetailsServiceImpl implements UserDetailsService {

      @Autowired
      private BCryptPasswordEncoder encoder;

      @Override
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      final List<ApplicationUser> users = Arrays.asList(
      new ApplicationUser("omar",encoder.encode("12345"), "USER"),
      new ApplicationUser("admin", encoder.encode("12345"), "ADMIN")
      );

      for(ApplicationUser appUser: users) {
      if(appUser.getUsername().equals(username)) {
      List<GrantedAuthority> grantedAuthorities = AuthorityUtils
      .commaSeparatedStringToAuthorityList( appUser.getRole());

      return new User(appUser.getUsername(), appUser.getPassword(), grantedAuthorities);
      }
      }

      // If user not found. Throw this exception.
      throw new UsernameNotFoundException("Username: " + username + " not found");

      }
      }


      WebSecurity



      @EnableWebSecurity(debug=true)
      @Order(1000)
      public class WebSecurity extends WebSecurityConfigurerAdapter {
      @Autowired
      private JwtConfig jwtConfig;

      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http
      .csrf().disable()
      // make sure we use stateless session; session won't be used to store user's state.
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and()
      // handle an authorized attempts
      .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
      .and()
      // Add a filter to validate the tokens with every request
      .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
      // authorization requests config
      .authorizeRequests()
      // allow all who are accessing "auth" service
      .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
      // must be an admin if trying to access admin area (authentication is also required here)
      .antMatchers("/v1/cooks").access("hasRole('ADMIN')")
      //for other uris
      // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
      // Any other request must be authenticated
      .anyRequest().authenticated();
      }


      }



      Controller



      @RestController


      public class CookController {

      @Autowired
      private CookService cookService;
      // Get All Cooks
      @GetMapping("/v1/cooks")
      public List<Cook> getAllCooks(){
      return cookService.getAllCooks();
      }


      application.properties



      zuul.routes.auth-service.path=/auth/**
      zuul.routes.auth-service.service-id=AUTH-SERVICE
      zuul.routes.auth-service.strip-prefix=false
      zuul.routes.auth-service.sensitive-headers=Cookie,Set-Cookie

      spring.application.name=auth-service
      server.port=9100
      eureka.client.service-url.default-zone=http://localhost:8761/eureka


      the call to v1/cooks always returns 401.
      What part of the configuration I am missing? I followed the documentation at https://medium.com/omarelgabrys-blog/microservices-with-spring-boot-authentication-with-jwt-part-3-fafc9d7187e8



      but I am completely lost now.
      Request url is
      GET http://localhost:9100/v1/cooks



      Response is
      {
      "timestamp": "2018-10-13T20:08:13.804+0000",
      "status": 401,
      "error": "Unauthorized",
      "message": "No message available",
      "path": "/v1/cooks"
      }



      pom.xml



       <dependencies>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-mail</artifactId>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      </dependency>
      <dependency>
      <groupId>org.springframework.restdocs</groupId>
      <artifactId>spring-restdocs-mockmvc</artifactId>
      <scope>test</scope>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.16</version>
      <scope>provided</scope>
      </dependency>
      <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.3.0-b170201.1204</version>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      <dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt</artifactId>
      <version>0.9.0</version>
      </dependency>
      <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      <dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.4.0</version>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <optional>true</optional>
      </dependency>
      </dependencies>


      EDIT: Added application.properties and dependies from pom










      share|improve this question















      I am new to Spring boot so please help me. I have got it working to the point where I am able to generate a Bearer Token with an unauthenticated request. Next I want to use this token to use with an endpoint so that my request is authenticated - this is where my trouble is coming in. I am always getting a 401, looks like something is wrong with my config. Here is my code



      public class ApplicationUser {

      private String username;
      private String password;
      private String role;

      public ApplicationUser(String username, String password, String role) {
      this.username = username;
      this.password = password;
      this.role = role;
      }

      public String getUsername() {
      return username;
      }

      public String getPassword() {
      return password;
      }

      public String getRole() {
      return role;
      }
      }


      JwtConfig Class:



      @Component("jwtConfig")
      public class JwtConfig {
      @Value("${security.jwt.uri:/auth/**}")
      private String Uri;

      @Value("${security.jwt.header:Authorization}")
      private String header;

      @Value("${security.jwt.prefix:Bearer }")
      private String prefix;

      @Value("${security.jwt.expiration:#{24*60*60}}")
      private int expiration;

      @Value("${security.jwt.secret:JwtSecretKey}")
      private String secret;

      public String getUri() {
      return Uri;
      }

      public String getHeader() {
      return header;
      }

      public String getPrefix() {
      return prefix;
      }

      public int getExpiration() {
      return expiration;
      }

      public String getSecret() {
      return secret;
      }


      }



      JwtTokenAuthenticationFilter



      public class JwtTokenAuthenticationFilter extends  OncePerRequestFilter {

      private final JwtConfig jwtConfig;

      public JwtTokenAuthenticationFilter(JwtConfig jwtConfig) {
      this.jwtConfig = jwtConfig;
      }

      @Override
      protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
      throws ServletException, IOException {

      // 1. get the authentication header. Tokens are supposed to be passed in the authentication header
      String header = request.getHeader(jwtConfig.getHeader());

      // 2. validate the header and check the prefix
      if(header == null || !header.startsWith(jwtConfig.getPrefix())) {
      chain.doFilter(request, response); // If not valid, go to the next filter.
      return;
      }

      // If there is no token provided and hence the user won't be authenticated.
      // It's Ok. Maybe the user accessing a public path or asking for a token.

      // All secured paths that needs a token are already defined and secured in config class.
      // And If user tried to access without access token, then he won't be authenticated and an exception will be thrown.

      // 3. Get the token
      String token = header.replace(jwtConfig.getPrefix(), "");

      try { // exceptions might be thrown in creating the claims if for example the token is expired

      // 4. Validate the token
      Claims claims = Jwts.parser()
      .setSigningKey(jwtConfig.getSecret().getBytes())
      .parseClaimsJws(token)
      .getBody();

      String username = claims.getSubject();
      if(username != null) {
      @SuppressWarnings("unchecked")
      List<String> authorities = (List<String>) claims.get("authorities");

      // 5. Create auth object
      // UsernamePasswordAuthenticationToken: A built-in object, used by spring to represent the current authenticated / being authenticated user.
      // It needs a list of authorities, which has type of GrantedAuthority interface, where SimpleGrantedAuthority is an implementation of that interface
      UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
      username, null, authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));

      // 6. Authenticate the user
      // Now, user is authenticated
      SecurityContextHolder.getContext().setAuthentication(auth);
      }

      } catch (Exception e) {
      // In case of failure. Make sure it's clear; so guarantee user won't be authenticated
      SecurityContextHolder.clearContext();
      }

      // go to the next filter in the filter chain
      chain.doFilter(request, response);
      }

      }


      JwtUsernameAndPasswordAuthenticationFilter



      public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter   {

      // We use auth manager to validate the user credentials
      private AuthenticationManager authManager;

      private final JwtConfig jwtConfig;

      public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authManager, JwtConfig jwtConfig) {
      this.authManager = authManager;
      this.jwtConfig = jwtConfig;

      // By default, UsernamePasswordAuthenticationFilter listens to "/login" path.
      // In our case, we use "/auth". So, we need to override the defaults.
      this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(jwtConfig.getUri(), "POST"));
      }

      @Override
      public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
      throws AuthenticationException {

      try {

      // 1. Get credentials from request
      UserCredentials creds = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class);

      // 2. Create auth object (contains credentials) which will be used by auth manager
      UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
      creds.getUsername(), creds.getPassword(), Collections.emptyList());

      // 3. Authentication manager authenticate the user, and use UserDetialsServiceImpl::loadUserByUsername() method to load the user.
      return authManager.authenticate(authToken);

      } catch (IOException e) {
      throw new RuntimeException(e);
      }
      }

      // Upon successful authentication, generate a token.
      // The 'auth' passed to successfulAuthentication() is the current authenticated user.
      @Override
      protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
      Authentication auth) throws IOException, ServletException {

      Long now = System.currentTimeMillis();
      String token = Jwts.builder()
      .setSubject(auth.getName())
      // Convert to list of strings.
      // This is important because it affects the way we get them back in the Gateway.
      .claim("authorities", auth.getAuthorities().stream()
      .map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
      .setIssuedAt(new Date(now))
      .setExpiration(new Date(now + jwtConfig.getExpiration() * 1000)) // in milliseconds
      .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())
      .compact();

      // Add token to header
      response.addHeader(jwtConfig.getHeader(), jwtConfig.getPrefix() + token);
      }

      // A (temporary) class just to represent the user credentials
      private static class UserCredentials {
      private String username, password;

      public String getUsername() {
      return username;
      }

      public void setUsername(String username) {
      this.username = username;
      }

      public String getPassword() {
      return password;
      }

      public void setPassword(String password) {
      this.password = password;
      }
      }
      }


      SecurityCredentialsConfig



      @Configuration
      @EnableWebSecurity(debug=true)
      public class SecurityCredentialsConfig extends WebSecurityConfigurerAdapter {

      @Autowired
      private UserDetailsServiceImpl userDetailsService;

      @Autowired
      private JwtConfig jwtConfig;

      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http
      .csrf().disable()
      // make sure we use stateless session; session won't be used to store user's state.
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and()
      // handle an authorized attempts
      .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
      .and()
      // Add a filter to validate user credentials and add token in the response header

      // What's the authenticationManager()?
      // An object provided by WebSecurityConfigurerAdapter, used to authenticate the user passing user's credentials
      // The filter needs this auth manager to authenticate the user.
      .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig))
      .authorizeRequests()
      // allow all POST requests
      .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
      // any other requests must be authenticated
      // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
      .anyRequest().authenticated();
      }

      // Spring has UserDetailsService interface, which can be overriden to provide our implementation for fetching user from database (or any other source).
      // The UserDetailsService object is used by the auth manager to load the user from database.
      // In addition, we need to define the password encoder also. So, auth manager can compare and verify passwords.
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
      }

      @Bean
      public BCryptPasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
      }
      }


      UserDetailsServiceImpl



      @Service
      public class UserDetailsServiceImpl implements UserDetailsService {

      @Autowired
      private BCryptPasswordEncoder encoder;

      @Override
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      final List<ApplicationUser> users = Arrays.asList(
      new ApplicationUser("omar",encoder.encode("12345"), "USER"),
      new ApplicationUser("admin", encoder.encode("12345"), "ADMIN")
      );

      for(ApplicationUser appUser: users) {
      if(appUser.getUsername().equals(username)) {
      List<GrantedAuthority> grantedAuthorities = AuthorityUtils
      .commaSeparatedStringToAuthorityList( appUser.getRole());

      return new User(appUser.getUsername(), appUser.getPassword(), grantedAuthorities);
      }
      }

      // If user not found. Throw this exception.
      throw new UsernameNotFoundException("Username: " + username + " not found");

      }
      }


      WebSecurity



      @EnableWebSecurity(debug=true)
      @Order(1000)
      public class WebSecurity extends WebSecurityConfigurerAdapter {
      @Autowired
      private JwtConfig jwtConfig;

      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http
      .csrf().disable()
      // make sure we use stateless session; session won't be used to store user's state.
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and()
      // handle an authorized attempts
      .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
      .and()
      // Add a filter to validate the tokens with every request
      .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
      // authorization requests config
      .authorizeRequests()
      // allow all who are accessing "auth" service
      .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
      // must be an admin if trying to access admin area (authentication is also required here)
      .antMatchers("/v1/cooks").access("hasRole('ADMIN')")
      //for other uris
      // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
      // Any other request must be authenticated
      .anyRequest().authenticated();
      }


      }



      Controller



      @RestController


      public class CookController {

      @Autowired
      private CookService cookService;
      // Get All Cooks
      @GetMapping("/v1/cooks")
      public List<Cook> getAllCooks(){
      return cookService.getAllCooks();
      }


      application.properties



      zuul.routes.auth-service.path=/auth/**
      zuul.routes.auth-service.service-id=AUTH-SERVICE
      zuul.routes.auth-service.strip-prefix=false
      zuul.routes.auth-service.sensitive-headers=Cookie,Set-Cookie

      spring.application.name=auth-service
      server.port=9100
      eureka.client.service-url.default-zone=http://localhost:8761/eureka


      the call to v1/cooks always returns 401.
      What part of the configuration I am missing? I followed the documentation at https://medium.com/omarelgabrys-blog/microservices-with-spring-boot-authentication-with-jwt-part-3-fafc9d7187e8



      but I am completely lost now.
      Request url is
      GET http://localhost:9100/v1/cooks



      Response is
      {
      "timestamp": "2018-10-13T20:08:13.804+0000",
      "status": 401,
      "error": "Unauthorized",
      "message": "No message available",
      "path": "/v1/cooks"
      }



      pom.xml



       <dependencies>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-mail</artifactId>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      </dependency>
      <dependency>
      <groupId>org.springframework.restdocs</groupId>
      <artifactId>spring-restdocs-mockmvc</artifactId>
      <scope>test</scope>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.16</version>
      <scope>provided</scope>
      </dependency>
      <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.3.0-b170201.1204</version>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      <dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt</artifactId>
      <version>0.9.0</version>
      </dependency>
      <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      <dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.4.0</version>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <optional>true</optional>
      </dependency>
      </dependencies>


      EDIT: Added application.properties and dependies from pom







      java spring-boot authentication http-status-code-401






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 20 '18 at 9:58









      Teocali

      1,5811430




      1,5811430










      asked Oct 13 '18 at 20:26









      kk1957

      2,13062346




      2,13062346
























          2 Answers
          2






          active

          oldest

          votes


















          1














          As looking your requirement, you really dont need multiple http security configurations until you are using multiple authentications for multiple paths(like for some path you would like to have jwt and for some you would like to have basic auth or auth2).



          so remove SecurityCredentialsConfig and update WebSecurity to below and you will be good.



          @Configuration
          @EnableWebSecurity(debug = true) // Enable security config. This annotation denotes config for spring security.
          public class WebSecurity extends WebSecurityConfigurerAdapter {
          @Autowired
          private JwtConfig jwtConfig;

          @Autowired
          private UserDetailsServiceImpl userDetailsService;

          @Override
          protected void configure(HttpSecurity http) throws Exception {
          http
          .csrf().disable()
          // make sure we use stateless session; session won't be used to store user's state.
          .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          .and()
          // authorization requests config
          .authorizeRequests()
          // allow all who are accessing "auth" service
          .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
          // must be an admin if trying to access admin area (authentication is also required here)
          .antMatchers("/v1/cooks/**").hasAuthority("ADMIN")
          //for other uris
          // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
          // Any other request must be authenticated
          .anyRequest().authenticated()
          .and()
          // handle an authorized attempts
          .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
          .and()
          // Add a filter to validate the tokens with every request
          .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
          .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig));
          }

          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
          }

          @Bean
          public BCryptPasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder();
          }
          }





          share|improve this answer























          • I did that, however now I am not able to use my first resource which is http://localhost:9100/auth/ which generates a token. It says, 404.
            – kk1957
            Oct 14 '18 at 14:51










          • @kk1957 define SecurityCredentialsConfig order 2..check my updated answer.
            – kj007
            Oct 14 '18 at 17:46










          • still same problem
            – kk1957
            Oct 15 '18 at 2:40










          • would you mind sharing your sample code at github..I can look at exactly..
            – kj007
            Oct 15 '18 at 2:51










          • github.com/kashifusmani/foodie
            – kk1957
            Oct 15 '18 at 3:08



















          0














          Try to add this




          /**




          on line in WebSecurity class,



          .antMatchers("/v1/cooks/**" ).access("hasRole('ADMIN')")


          please, if you can provide logs and version on spring boot and security dependencies this could help us much.






          share|improve this answer





















          • Still same problem.
            – kk1957
            Oct 14 '18 at 14:56










          • Logs are accessible at pastebin.com/eaBGW0ZR
            – kk1957
            Oct 14 '18 at 14:57










          • added pom dependencies in the original question, also added application.properties.
            – kk1957
            Oct 14 '18 at 14:59










          • Okay, I've taken a look on your logs, you are using last version of spring boot 2.0.5 this version asks that you work on spring security 5, could you remove all dependencies of security and jwt and add dependency below <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.5.RELEASE</version> </dependency>
            – Jonathan Johx
            Oct 15 '18 at 2:20












          • If you added it and it shows another error on your logs, you'll need to follow migration to spring security 5..
            – Jonathan Johx
            Oct 15 '18 at 2:22











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52797019%2fspringboot-bearer-token-authentication-giving-401%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          As looking your requirement, you really dont need multiple http security configurations until you are using multiple authentications for multiple paths(like for some path you would like to have jwt and for some you would like to have basic auth or auth2).



          so remove SecurityCredentialsConfig and update WebSecurity to below and you will be good.



          @Configuration
          @EnableWebSecurity(debug = true) // Enable security config. This annotation denotes config for spring security.
          public class WebSecurity extends WebSecurityConfigurerAdapter {
          @Autowired
          private JwtConfig jwtConfig;

          @Autowired
          private UserDetailsServiceImpl userDetailsService;

          @Override
          protected void configure(HttpSecurity http) throws Exception {
          http
          .csrf().disable()
          // make sure we use stateless session; session won't be used to store user's state.
          .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          .and()
          // authorization requests config
          .authorizeRequests()
          // allow all who are accessing "auth" service
          .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
          // must be an admin if trying to access admin area (authentication is also required here)
          .antMatchers("/v1/cooks/**").hasAuthority("ADMIN")
          //for other uris
          // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
          // Any other request must be authenticated
          .anyRequest().authenticated()
          .and()
          // handle an authorized attempts
          .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
          .and()
          // Add a filter to validate the tokens with every request
          .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
          .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig));
          }

          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
          }

          @Bean
          public BCryptPasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder();
          }
          }





          share|improve this answer























          • I did that, however now I am not able to use my first resource which is http://localhost:9100/auth/ which generates a token. It says, 404.
            – kk1957
            Oct 14 '18 at 14:51










          • @kk1957 define SecurityCredentialsConfig order 2..check my updated answer.
            – kj007
            Oct 14 '18 at 17:46










          • still same problem
            – kk1957
            Oct 15 '18 at 2:40










          • would you mind sharing your sample code at github..I can look at exactly..
            – kj007
            Oct 15 '18 at 2:51










          • github.com/kashifusmani/foodie
            – kk1957
            Oct 15 '18 at 3:08
















          1














          As looking your requirement, you really dont need multiple http security configurations until you are using multiple authentications for multiple paths(like for some path you would like to have jwt and for some you would like to have basic auth or auth2).



          so remove SecurityCredentialsConfig and update WebSecurity to below and you will be good.



          @Configuration
          @EnableWebSecurity(debug = true) // Enable security config. This annotation denotes config for spring security.
          public class WebSecurity extends WebSecurityConfigurerAdapter {
          @Autowired
          private JwtConfig jwtConfig;

          @Autowired
          private UserDetailsServiceImpl userDetailsService;

          @Override
          protected void configure(HttpSecurity http) throws Exception {
          http
          .csrf().disable()
          // make sure we use stateless session; session won't be used to store user's state.
          .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          .and()
          // authorization requests config
          .authorizeRequests()
          // allow all who are accessing "auth" service
          .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
          // must be an admin if trying to access admin area (authentication is also required here)
          .antMatchers("/v1/cooks/**").hasAuthority("ADMIN")
          //for other uris
          // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
          // Any other request must be authenticated
          .anyRequest().authenticated()
          .and()
          // handle an authorized attempts
          .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
          .and()
          // Add a filter to validate the tokens with every request
          .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
          .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig));
          }

          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
          }

          @Bean
          public BCryptPasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder();
          }
          }





          share|improve this answer























          • I did that, however now I am not able to use my first resource which is http://localhost:9100/auth/ which generates a token. It says, 404.
            – kk1957
            Oct 14 '18 at 14:51










          • @kk1957 define SecurityCredentialsConfig order 2..check my updated answer.
            – kj007
            Oct 14 '18 at 17:46










          • still same problem
            – kk1957
            Oct 15 '18 at 2:40










          • would you mind sharing your sample code at github..I can look at exactly..
            – kj007
            Oct 15 '18 at 2:51










          • github.com/kashifusmani/foodie
            – kk1957
            Oct 15 '18 at 3:08














          1












          1








          1






          As looking your requirement, you really dont need multiple http security configurations until you are using multiple authentications for multiple paths(like for some path you would like to have jwt and for some you would like to have basic auth or auth2).



          so remove SecurityCredentialsConfig and update WebSecurity to below and you will be good.



          @Configuration
          @EnableWebSecurity(debug = true) // Enable security config. This annotation denotes config for spring security.
          public class WebSecurity extends WebSecurityConfigurerAdapter {
          @Autowired
          private JwtConfig jwtConfig;

          @Autowired
          private UserDetailsServiceImpl userDetailsService;

          @Override
          protected void configure(HttpSecurity http) throws Exception {
          http
          .csrf().disable()
          // make sure we use stateless session; session won't be used to store user's state.
          .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          .and()
          // authorization requests config
          .authorizeRequests()
          // allow all who are accessing "auth" service
          .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
          // must be an admin if trying to access admin area (authentication is also required here)
          .antMatchers("/v1/cooks/**").hasAuthority("ADMIN")
          //for other uris
          // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
          // Any other request must be authenticated
          .anyRequest().authenticated()
          .and()
          // handle an authorized attempts
          .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
          .and()
          // Add a filter to validate the tokens with every request
          .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
          .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig));
          }

          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
          }

          @Bean
          public BCryptPasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder();
          }
          }





          share|improve this answer














          As looking your requirement, you really dont need multiple http security configurations until you are using multiple authentications for multiple paths(like for some path you would like to have jwt and for some you would like to have basic auth or auth2).



          so remove SecurityCredentialsConfig and update WebSecurity to below and you will be good.



          @Configuration
          @EnableWebSecurity(debug = true) // Enable security config. This annotation denotes config for spring security.
          public class WebSecurity extends WebSecurityConfigurerAdapter {
          @Autowired
          private JwtConfig jwtConfig;

          @Autowired
          private UserDetailsServiceImpl userDetailsService;

          @Override
          protected void configure(HttpSecurity http) throws Exception {
          http
          .csrf().disable()
          // make sure we use stateless session; session won't be used to store user's state.
          .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          .and()
          // authorization requests config
          .authorizeRequests()
          // allow all who are accessing "auth" service
          .antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
          // must be an admin if trying to access admin area (authentication is also required here)
          .antMatchers("/v1/cooks/**").hasAuthority("ADMIN")
          //for other uris
          // .antMatchers(HttpMethod.GET, "/v1/**").hasRole("USER")
          // Any other request must be authenticated
          .anyRequest().authenticated()
          .and()
          // handle an authorized attempts
          .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
          .and()
          // Add a filter to validate the tokens with every request
          .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig), UsernamePasswordAuthenticationFilter.class)
          .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig));
          }

          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
          }

          @Bean
          public BCryptPasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder();
          }
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Oct 15 '18 at 17:14

























          answered Oct 14 '18 at 8:37









          kj007

          2,61931326




          2,61931326












          • I did that, however now I am not able to use my first resource which is http://localhost:9100/auth/ which generates a token. It says, 404.
            – kk1957
            Oct 14 '18 at 14:51










          • @kk1957 define SecurityCredentialsConfig order 2..check my updated answer.
            – kj007
            Oct 14 '18 at 17:46










          • still same problem
            – kk1957
            Oct 15 '18 at 2:40










          • would you mind sharing your sample code at github..I can look at exactly..
            – kj007
            Oct 15 '18 at 2:51










          • github.com/kashifusmani/foodie
            – kk1957
            Oct 15 '18 at 3:08


















          • I did that, however now I am not able to use my first resource which is http://localhost:9100/auth/ which generates a token. It says, 404.
            – kk1957
            Oct 14 '18 at 14:51










          • @kk1957 define SecurityCredentialsConfig order 2..check my updated answer.
            – kj007
            Oct 14 '18 at 17:46










          • still same problem
            – kk1957
            Oct 15 '18 at 2:40










          • would you mind sharing your sample code at github..I can look at exactly..
            – kj007
            Oct 15 '18 at 2:51










          • github.com/kashifusmani/foodie
            – kk1957
            Oct 15 '18 at 3:08
















          I did that, however now I am not able to use my first resource which is http://localhost:9100/auth/ which generates a token. It says, 404.
          – kk1957
          Oct 14 '18 at 14:51




          I did that, however now I am not able to use my first resource which is http://localhost:9100/auth/ which generates a token. It says, 404.
          – kk1957
          Oct 14 '18 at 14:51












          @kk1957 define SecurityCredentialsConfig order 2..check my updated answer.
          – kj007
          Oct 14 '18 at 17:46




          @kk1957 define SecurityCredentialsConfig order 2..check my updated answer.
          – kj007
          Oct 14 '18 at 17:46












          still same problem
          – kk1957
          Oct 15 '18 at 2:40




          still same problem
          – kk1957
          Oct 15 '18 at 2:40












          would you mind sharing your sample code at github..I can look at exactly..
          – kj007
          Oct 15 '18 at 2:51




          would you mind sharing your sample code at github..I can look at exactly..
          – kj007
          Oct 15 '18 at 2:51












          github.com/kashifusmani/foodie
          – kk1957
          Oct 15 '18 at 3:08




          github.com/kashifusmani/foodie
          – kk1957
          Oct 15 '18 at 3:08













          0














          Try to add this




          /**




          on line in WebSecurity class,



          .antMatchers("/v1/cooks/**" ).access("hasRole('ADMIN')")


          please, if you can provide logs and version on spring boot and security dependencies this could help us much.






          share|improve this answer





















          • Still same problem.
            – kk1957
            Oct 14 '18 at 14:56










          • Logs are accessible at pastebin.com/eaBGW0ZR
            – kk1957
            Oct 14 '18 at 14:57










          • added pom dependencies in the original question, also added application.properties.
            – kk1957
            Oct 14 '18 at 14:59










          • Okay, I've taken a look on your logs, you are using last version of spring boot 2.0.5 this version asks that you work on spring security 5, could you remove all dependencies of security and jwt and add dependency below <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.5.RELEASE</version> </dependency>
            – Jonathan Johx
            Oct 15 '18 at 2:20












          • If you added it and it shows another error on your logs, you'll need to follow migration to spring security 5..
            – Jonathan Johx
            Oct 15 '18 at 2:22
















          0














          Try to add this




          /**




          on line in WebSecurity class,



          .antMatchers("/v1/cooks/**" ).access("hasRole('ADMIN')")


          please, if you can provide logs and version on spring boot and security dependencies this could help us much.






          share|improve this answer





















          • Still same problem.
            – kk1957
            Oct 14 '18 at 14:56










          • Logs are accessible at pastebin.com/eaBGW0ZR
            – kk1957
            Oct 14 '18 at 14:57










          • added pom dependencies in the original question, also added application.properties.
            – kk1957
            Oct 14 '18 at 14:59










          • Okay, I've taken a look on your logs, you are using last version of spring boot 2.0.5 this version asks that you work on spring security 5, could you remove all dependencies of security and jwt and add dependency below <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.5.RELEASE</version> </dependency>
            – Jonathan Johx
            Oct 15 '18 at 2:20












          • If you added it and it shows another error on your logs, you'll need to follow migration to spring security 5..
            – Jonathan Johx
            Oct 15 '18 at 2:22














          0












          0








          0






          Try to add this




          /**




          on line in WebSecurity class,



          .antMatchers("/v1/cooks/**" ).access("hasRole('ADMIN')")


          please, if you can provide logs and version on spring boot and security dependencies this could help us much.






          share|improve this answer












          Try to add this




          /**




          on line in WebSecurity class,



          .antMatchers("/v1/cooks/**" ).access("hasRole('ADMIN')")


          please, if you can provide logs and version on spring boot and security dependencies this could help us much.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 14 '18 at 5:30









          Jonathan Johx

          867211




          867211












          • Still same problem.
            – kk1957
            Oct 14 '18 at 14:56










          • Logs are accessible at pastebin.com/eaBGW0ZR
            – kk1957
            Oct 14 '18 at 14:57










          • added pom dependencies in the original question, also added application.properties.
            – kk1957
            Oct 14 '18 at 14:59










          • Okay, I've taken a look on your logs, you are using last version of spring boot 2.0.5 this version asks that you work on spring security 5, could you remove all dependencies of security and jwt and add dependency below <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.5.RELEASE</version> </dependency>
            – Jonathan Johx
            Oct 15 '18 at 2:20












          • If you added it and it shows another error on your logs, you'll need to follow migration to spring security 5..
            – Jonathan Johx
            Oct 15 '18 at 2:22


















          • Still same problem.
            – kk1957
            Oct 14 '18 at 14:56










          • Logs are accessible at pastebin.com/eaBGW0ZR
            – kk1957
            Oct 14 '18 at 14:57










          • added pom dependencies in the original question, also added application.properties.
            – kk1957
            Oct 14 '18 at 14:59










          • Okay, I've taken a look on your logs, you are using last version of spring boot 2.0.5 this version asks that you work on spring security 5, could you remove all dependencies of security and jwt and add dependency below <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.5.RELEASE</version> </dependency>
            – Jonathan Johx
            Oct 15 '18 at 2:20












          • If you added it and it shows another error on your logs, you'll need to follow migration to spring security 5..
            – Jonathan Johx
            Oct 15 '18 at 2:22
















          Still same problem.
          – kk1957
          Oct 14 '18 at 14:56




          Still same problem.
          – kk1957
          Oct 14 '18 at 14:56












          Logs are accessible at pastebin.com/eaBGW0ZR
          – kk1957
          Oct 14 '18 at 14:57




          Logs are accessible at pastebin.com/eaBGW0ZR
          – kk1957
          Oct 14 '18 at 14:57












          added pom dependencies in the original question, also added application.properties.
          – kk1957
          Oct 14 '18 at 14:59




          added pom dependencies in the original question, also added application.properties.
          – kk1957
          Oct 14 '18 at 14:59












          Okay, I've taken a look on your logs, you are using last version of spring boot 2.0.5 this version asks that you work on spring security 5, could you remove all dependencies of security and jwt and add dependency below <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.5.RELEASE</version> </dependency>
          – Jonathan Johx
          Oct 15 '18 at 2:20






          Okay, I've taken a look on your logs, you are using last version of spring boot 2.0.5 this version asks that you work on spring security 5, could you remove all dependencies of security and jwt and add dependency below <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.5.RELEASE</version> </dependency>
          – Jonathan Johx
          Oct 15 '18 at 2:20














          If you added it and it shows another error on your logs, you'll need to follow migration to spring security 5..
          – Jonathan Johx
          Oct 15 '18 at 2:22




          If you added it and it shows another error on your logs, you'll need to follow migration to spring security 5..
          – Jonathan Johx
          Oct 15 '18 at 2:22


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52797019%2fspringboot-bearer-token-authentication-giving-401%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Paul Cézanne

          UIScrollView CustomStickyHeader Resize height generates problems when scroll is too fast

          Angular material date-picker (MatDatepicker) auto completes the date on focus out