0

I have a problem with the JWT authentication token. when i'm testing login with postman first time it gave me token but after rebooting inteliij I get 403 forbidden in postman and in intelij the error (JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted. ) (Here I use Postman). this is my code

package com.example.demo.Configiration;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@Component
public class JwtUtils {
    private String Secret = "671491AE98362741F722202EED3288E8FF2508B35315ADBF75EEB3195A926B40";

    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }

    public Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    public Boolean hasClaim(String token, String claimName) {
        final Claims claims = extractAllClaims(token);
        return claims.get(claimName) != null;
    }

    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return c

type here

laimsResolver.apply(claims);
    }

    private Claims extractAllClaims(String token) {
        return Jwts.parser().setSigningKey(Secret).parseClaimsJws(token).getBody();
    }

    private Boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }
    public String generateToken(UserDetails userDetails){
        Map<String,Object> claims=new HashMap<>();
        return createToken(claims,userDetails);
    }
    public String generateToken(UserDetails userDetails,Map<String,Object> claims){
        return createToken(claims,userDetails);
    }
    private String createToken(Map<String,Object> claims,UserDetails userDetails){
        return Jwts.builder().setClaims(claims).setSubject(userDetails.getUsername())
                .claim("authorities",userDetails.getAuthorities())
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(24)))
                .signWith(SignatureAlgorithm.HS256,Secret).compact();
    }
    public Boolean isTokenValide(String token, UserDetails userDetails) {
        final String userName = extractUsername(token);
        return (userName.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
  /*  private Key getSigningKey() {
        byte[] keyBytes= Decoders.BASE64.decode(Secret);
        return Keys.hmacShaKeyFor(keyBytes);
    }*/
}


package com.example.demo.Configiration;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableWebSecurity
@RequiredArgsConstructor
@Configuration
public class SecurityConfig {
    private final JwtAuthFilter jwtAuthFilter;
    private final AuthenticationProvider authenticationProvider;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
         httpSecurity
                 .csrf().disable()
                .authorizeRequests()
                 .requestMatchers("/hello/login")
                 .permitAll()
                .anyRequest()
                .authenticated()
                 .and()
                 .sessionManagement()
                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                 .and()
                 .authenticationProvider(authenticationProvider)
                 .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
         return httpSecurity.build();
    }
}

package com.example.demo.Configiration;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

import static org.springframework.http.HttpHeaders.AUTHORIZATION;
@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
    private final UserDetailsService userDetailsService;
    private final JwtUtils jwtUtils;
    private final Dto dto;


    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
    final  String authHeader=request.getHeader(AUTHORIZATION);
    final  String userEmail;
    final  String jwtToken;
    if (authHeader==null || !authHeader.startsWith("Bearer")){
        filterChain.doFilter(request,response);
        return;
    }
    jwtToken=authHeader.substring(7);
    userEmail=jwtUtils.extractUsername(jwtToken);
    if (userEmail !=null && SecurityContextHolder.getContext().getAuthentication()==null){
        UserDetails userDetails=dto.findUserbyemail(userEmail);
      //  final Boolean isTokenValid;
        if (jwtUtils.isTokenValide(jwtToken,userDetails)){
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken=
                    new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
            usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        }
    }
    filterChain.doFilter(request,response);
    }
}

package com.example.demo.Configiration;

import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Repository;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Repository
public class Dto {
    private final static List<UserDetails> APPLICATION_USERS= Arrays.asList(
            new User(
                    "aymen@gmail.com",
                    "aymen",
                    Collections.singleton(new SimpleGrantedAuthority("ROLE_ADMIN"))
            ),
            new User(
                    "messikh@gmail.com",
                    "messikh",
                    Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))
            )
    );
    public  UserDetails findUserbyemail(String email){
        return APPLICATION_USERS
                .stream().filter(u -> u.getUsername().equals(email))
                .findFirst().orElseThrow(() -> new UsernameNotFoundException("No user was found"));
    }
}

package com.example.demo.Configiration;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class AppConfig {
    private final Dto dto;

    @Bean
    public AuthenticationProvider authenticationProvider() {
        final DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService());
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return daoAuthenticationProvider;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
       // return NoOpPasswordEncoder.getInstance();
        return new BCryptPasswordEncoder();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
                return dto.findUserbyemail(email);
            }
        };
    }
        @Bean
        public AuthenticationManager authenticationManager (AuthenticationConfiguration configuration) throws Exception
        {
            return configuration.getAuthenticationManager();
        }
}

package com.example.demo;

import lombok.*;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AuthentificationRequest {
    private String email;
    private String password;
}

package com.example.demo.Controller;

import com.example.demo.AuthentificationRequest;
import com.example.demo.Configiration.Dto;
import com.example.demo.Configiration.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/hello")
@RequiredArgsConstructor
public class Hello {
    private final AuthenticationManager authenticationManager;
    private final UserDetailsService userDetailsService;
    private  final JwtUtils jwtUtils;
    private final Dto dto;
    @GetMapping("/hello1")
    public ResponseEntity<String> hello1(){
        return ResponseEntity.ok("aaaaaaaaaaaaaaaa");
    }
    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestBody AuthentificationRequest request){
        authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(request.getEmail(),request.getPassword())
        );
        final UserDetails user=dto.findUserbyemail(request.getEmail());
        if (user!=null){
            return ResponseEntity.ok(jwtUtils.generateToken(user));
        }
        return ResponseEntity.status(400).body("ssssssssss");
    }
}

4.0.0 org.springframework.boot spring-boot-starter-parent 3.0.6 com.example demo2 0.0.1-SNAPSHOT demo2 demo2 <java.version>17</java.version> org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                    </exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

  • 2
    Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Aug 15 '23 at 11:24

1 Answers1

0

The issue could come from the fact that you are signing your token using .signWith(SignatureAlgorithm.HS256,Secret) and to get the claims in extractAllClaims you are using only the secret directly so it cannot retrieve the proper information to validate your token Jwts.parser().setSigningKey(Secret).parseClaimsJws(token).getBody();

Also I want to point out that the methods you are using to sign your token is deprecated as per the documentation take a look the documentation/Parser Doc and you can make the proper adjustments. Also for reference you can check this out Static secret as byte[], Key or String?

Tavo Sanchez
  • 141
  • 6