Przeglądaj źródła

set token expiration based on user role

Daniel Bohry 1 miesiąc temu
rodzic
commit
02a347306f

+ 2 - 2
src/main/java/com/danielbohry/authservice/api/AuthController.java

@@ -27,14 +27,14 @@ public class AuthController {
     @PostMapping("register")
     public ResponseEntity<AuthenticationResponse> register(@RequestBody AuthenticationRequest request) {
         log.info("Registering new username [{}]", request.getUsername());
-        var response = service.signup(request);
+        var response = service.register(request);
         return ResponseEntity.status(CREATED).body(response);
     }
 
     @PostMapping("authenticate")
     public ResponseEntity<AuthenticationResponse> authenticate(@RequestBody AuthenticationRequest request) {
         log.info("Authenticating username [{}]", request.getUsername());
-        var response = service.signin(request);
+        var response = service.authenticate(request);
         return ResponseEntity.ok(response);
     }
 

+ 2 - 3
src/main/java/com/danielbohry/authservice/service/auth/AuthService.java

@@ -5,7 +5,6 @@ import com.danielbohry.authservice.api.dto.AuthenticationResponse;
 import com.danielbohry.authservice.domain.ApplicationUser;
 import com.danielbohry.authservice.service.user.UserService;
 import lombok.AllArgsConstructor;
-import org.checkerframework.checker.nullness.qual.NonNull;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
@@ -35,14 +34,14 @@ public class AuthService implements UserDetailsService {
         return new User(user.getUsername(), user.getPassword(), authorities);
     }
 
-    public AuthenticationResponse signup(AuthenticationRequest request) {
+    public AuthenticationResponse register(AuthenticationRequest request) {
         UserDetails user = buildUserDetails(request);
         ApplicationUser saved = service.create(convert(user));
         Authentication authentication = jwtService.generateToken(saved);
         return buildResponse(saved.getId(), authentication);
     }
 
-    public AuthenticationResponse signin(AuthenticationRequest request) {
+    public AuthenticationResponse authenticate(AuthenticationRequest request) {
         authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
             request.getUsername(), request.getPassword())
         );

+ 35 - 17
src/main/java/com/danielbohry/authservice/service/auth/JwtService.java

@@ -10,9 +10,7 @@ import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.stereotype.Service;
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 import java.util.function.Function;
 
 import static java.lang.System.currentTimeMillis;
@@ -25,6 +23,15 @@ public class JwtService {
     @Value("${jwt.secret}")
     private String secret;
 
+    private static final Map<String, Long> ROLE_EXPIRATION_HOURS = Map.of(
+            "ADMIN", 1L,
+            "SERVICE", 12L,
+            "VPN", 24L,
+            "USER", 48L
+    );
+
+    private static final List<String> ROLE_PRIORITY = List.of("ADMIN", "SERVICE", "VPN");
+
     public String extractUsername(String token) {
         return extractClaim(token, Claims::getSubject);
     }
@@ -41,9 +48,9 @@ public class JwtService {
     public Authentication generateToken(UserDetails userDetails) {
         Map<String, Object> claims = new HashMap<>();
         claims.put(
-            "authorities", userDetails.getAuthorities().stream()
-                .map(GrantedAuthority::getAuthority)
-                .collect(toSet())
+                "authorities", userDetails.getAuthorities().stream()
+                        .map(GrantedAuthority::getAuthority)
+                        .collect(toSet())
         );
         return generateToken(claims, userDetails);
     }
@@ -58,30 +65,41 @@ public class JwtService {
     }
 
     private Authentication generateToken(Map<String, Object> claims, UserDetails userDetails) {
-        Date expirationDate = new Date(currentTimeMillis() + 1000 * 60 * 60 * 48);
+        Date expirationDate = new Date(currentTimeMillis() + 1000 * 60 * 60 * hoursByRole(claims));
         String token = Jwts.builder().setClaims(claims)
-            .setSubject(userDetails.getUsername())
-            .setIssuedAt(new Date(currentTimeMillis()))
-            .setExpiration(expirationDate)
-            .signWith(SignatureAlgorithm.HS256, secret).compact();
+                .setSubject(userDetails.getUsername())
+                .setIssuedAt(new Date(currentTimeMillis()))
+                .setExpiration(expirationDate)
+                .signWith(SignatureAlgorithm.HS256, secret).compact();
 
         return new Authentication(token,
-            expirationDate.toInstant(),
-            userDetails.getUsername(),
-            userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority).toList()
+                expirationDate.toInstant(),
+                userDetails.getUsername(),
+                userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority).toList()
         );
     }
 
     private Claims extractAllClaims(String token) {
         try {
             return Jwts.parser()
-                .setSigningKey(secret)
-                .parseClaimsJws(token)
-                .getBody();
+                    .setSigningKey(secret)
+                    .parseClaimsJws(token)
+                    .getBody();
         } catch (ExpiredJwtException e) {
             log.warn("Expired JWT token [{}]", e.getClaims());
             return e.getClaims();
         }
     }
 
+    private long hoursByRole(Map<String, Object> claims) {
+        @SuppressWarnings("unchecked")
+        Set<String> authorities = (Set<String>) claims.get("authorities");
+
+        return ROLE_PRIORITY.stream()
+                .filter(authorities::contains)
+                .findFirst()
+                .map(ROLE_EXPIRATION_HOURS::get)
+                .orElse(48L);
+    }
+
 }