I've been working on this for a while and the video I used to help me is from 2019 so it's a bit outdated but I thought that I could work through the problems. The program runs but when I try using postman I get a 401 unauthorized error:
Here is the jwtutil.java file code:
package com.stdbankjwtauth.authsystem.util; import java.util.Map; import java.util.function.Function; import java.util.Date; import java.util.HashMap; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; @Service public class JwtUtil { private String SECRET_KEY = "secret"; public String extractUsername(String token) { return extractClaim(token, Claims::getSubject); } public Date extractExpiration(String token) { return extractClaim(token,Claims::getExpiration); } public <T> T extractClaim(String token, Function<Claims,T> claimsResolver) { final Claims claims = extractAllClaims(token); return claimsResolver.apply(claims); } private Claims extractAllClaims(String token) { return Jwts.parser().setSigningKey(SECRET_KEY).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.getUsername()); } private String createToken(Map<String,Object> claims, String Subject) { return Jwts.builder().setClaims(claims).setSubject(Subject).setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis()+1000*60*60*10)) .signWith(SignatureAlgorithm.HS256,SECRET_KEY).compact(); } public boolean validateToken(String token, UserDetails userDetails){ final String username = extractUsername(token); return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); } } AuthenticationRequest.java
package com.stdbankjwtauth.authsystem.models; public class AuthenticationRequest { private String username; private String password; public AuthenticationRequest(String Username,String Password) { this.username = Username; this.password = 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; } } AuthenticationResponse.java
package com.stdbankjwtauth.authsystem.models; public class AuthenticationResponse { private final String jwt; public AuthenticationResponse(String Jwt) { this.jwt = Jwt; } public String getJwt() { return jwt; } } AuthenticationEndpoint.java
package com.stdbankjwtauth.authsystem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; 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.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.stdbankjwtauth.authsystem.models.AuthenticationRequest; import com.stdbankjwtauth.authsystem.models.AuthenticationResponse; import com.stdbankjwtauth.authsystem.util.JwtUtil; @RestController public class AuthenticateEnpoint { @Autowired private AuthenticationManager authenticationManager; @Autowired private UserDetailsService userDetailsService; @Autowired private JwtUtil jwtTokenUtil; @PostMapping("/authenticates") public ResponseEntity <?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception{ try { authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(),authenticationRequest.getPassword()) ); }catch(BadCredentialsException e) { throw new Exception("Incorrect username or password",e); } final UserDetails userDetails = userDetailsService .loadUserByUsername(authenticationRequest.getUsername()); final String jwt = jwtTokenUtil.generateToken(userDetails); return ResponseEntity.ok(new AuthenticationResponse(jwt)); } } SecurityConfigurer
package com.stdbankjwtauth.authsystem; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; import org.springframework.security.config.http.SessionCreationPolicy; @Configuration @EnableWebSecurity public class SecurirtyConfigurer extends WebSecurityConfiguration { protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.getDefaultUserDetailsService(); } @Bean public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception { return http.getSharedObject(AuthenticationManagerBuilder.class) .build(); } protected void configure(HttpSecurity http) throws Exception{ http .csrf() .disable() .authorizeHttpRequests().requestMatchers("/authenticates").permitAll() .anyRequest().authenticated() .and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); } } FileBasedAuthSystem.java
package com.stdbankjwtauth.authsystem.services; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.ArrayList; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.stereotype.Service; @Configuration @Service public class FileBasedUserDetailsService { private static final String FILE_PATH = "C:\\repos\\STDBank-JWT-Auth-System\\stdbank-jwt-auth\\credentials.txt"; @Bean public InMemoryUserDetailsManager userDetailsService() { List<String> lines = new ArrayList<>(); try { lines = Files.readAllLines(Paths.get(FILE_PATH)); }catch (Exception e) { e.printStackTrace(); } for (String line : lines) { String[] parts = line.split(":"); PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); UserDetails user = User.withUsername(parts[0]) .password(encoder.encode(parts[1])) .roles("USER") .build(); return new InMemoryUserDetailsManager(user); } throw new UsernameNotFoundException("Username not found: "+ lines); } } Here's a link to youtube video I used https://www.youtube.com/watch?v=X80nJ5T7YpE&t=81s