Skip to content

Commit

Permalink
Add JWT Service
Browse files Browse the repository at this point in the history
  • Loading branch information
sdikyarts committed May 25, 2024
1 parent 1b3f9eb commit 55e4ef9
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 0 deletions.
5 changes: 5 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ dependencies {
runtimeOnly("io.micrometer:micrometer-registry-prometheus:1.12.5")
implementation("org.springframework.boot:spring-boot-starter-actuator:3.2.5")
implementation("me.paulschwarz:spring-dotenv:4.0.0")
implementation("io.jsonwebtoken:jjwt-api:0.12.5")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-webflux")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.5")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.5")
}

tasks.register<Test>("unitTest") {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package snackscription.subscriptionadmin.config;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import snackscription.subscriptionadmin.utils.JWTUtils;

import java.io.IOException;
import java.util.Collections;

@Component
public class JWTAuthFilter extends OncePerRequestFilter {

private final JWTUtils jwtUtils;

public JWTAuthFilter(JWTUtils jwtUtils) {
this.jwtUtils = jwtUtils;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwtToken;

if (authHeader == null || authHeader.isBlank()) {
filterChain.doFilter(request, response);
return;
}

jwtToken = authHeader.substring(7);

if (jwtUtils.isTokenValid(jwtToken)) {
String role = jwtUtils.extractRole(jwtToken);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
null, null, Collections.singletonList(() -> role));
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}

filterChain.doFilter(request, response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package snackscription.subscriptionadmin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import snackscription.subscriptionadmin.utils.JWTUtils;

public class SecurityConfig {
private final JWTUtils jwtUtils;

public SecurityConfig(JWTUtils jwtUtils) {
this.jwtUtils = jwtUtils;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorizeRequests ->
authorizeRequests.requestMatchers("/adminSubscription/**", "/public/**").permitAll()
.anyRequest().authenticated())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(new JWTAuthFilter(jwtUtils), UsernamePasswordAuthenticationFilter.class);

return httpSecurity.build();
}
}
41 changes: 41 additions & 0 deletions src/main/java/snackscription/subscriptionadmin/utils/JWTUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package snackscription.subscriptionadmin.utils;


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;
import java.util.function.Function;

@Component
public class JWTUtils {
private final SecretKey KEY;

public JWTUtils(@Value("${JWT_SECRET}") String jwtSecret) {
byte[] keyBytes = Base64.getDecoder().decode(jwtSecret.getBytes(StandardCharsets.UTF_8));
this.KEY = new SecretKeySpec(keyBytes, "HmacSHA256");
}

public String extractRole(String token) {
return extractClaims(token, claims -> claims.get("role", String.class));
}

private <T> T extractClaims(String token, Function<Claims, T> claimsTFunction){
return claimsTFunction.apply(Jwts.parser().verifyWith(KEY).build().parseSignedClaims(token).getPayload());
}

public boolean isTokenValid(String token) {
return !isTokenExpired(token);
}

public boolean isTokenExpired(String token) {
return extractClaims(token, Claims::getExpiration).before(new Date());
}
}

0 comments on commit 55e4ef9

Please sign in to comment.