Skip to content

Commit

Permalink
feat: Add custom JWT error messages for authentication failures (issue
Browse files Browse the repository at this point in the history
  • Loading branch information
JinnJarBurger committed Oct 25, 2024
1 parent 76b7372 commit a1d82c3
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dev.nmarulo.depensaapp.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import dev.nmarulo.depensaapp.commons.dtos.ErrorRes;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.jwt.JwtException;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URI;

@Component
@RequiredArgsConstructor
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

private final AuthenticationEntryPoint delegate = new BearerTokenAuthenticationEntryPoint();

private final ObjectMapper mapper;

@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {

this.delegate.commence(request, response, authException);

if (authException.getCause() instanceof JwtException jwtException) {
var problemDetail = ProblemDetail.forStatus(HttpStatus.UNAUTHORIZED);

problemDetail.setType(URI.create("https://tools.ietf.org/html/rfc6750#section-3.1"));
problemDetail.setInstance(URI.create(request.getRequestURI()));
problemDetail.setProperty("errorCode", "invalid_token");
problemDetail.setProperty("description", jwtException.getMessage());
problemDetail.setTitle("Invalid Token");

response.setContentType("application/json");

mapper.writeValue(response.getWriter(), new ErrorRes(problemDetail));
}
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.nmarulo.depensaapp.configuration;
package dev.nmarulo.depensaapp.security;

import com.nimbusds.jose.KeyLengthException;
import com.nimbusds.jose.crypto.MACSigner;
Expand All @@ -8,6 +8,7 @@
import dev.nmarulo.depensaapp.app.users.UserRepository;
import dev.nmarulo.depensaapp.commons.component.LocalMessage;
import dev.nmarulo.depensaapp.commons.converter.CustomJwtAuthenticationConverter;
import dev.nmarulo.depensaapp.configuration.AppProperties;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -43,6 +44,8 @@ public class WebSecurityConfig {

private final LocalMessage localeMessage;

private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.securityMatcher(appProperties.getPathPrefix() + "/**")
Expand Down Expand Up @@ -105,7 +108,8 @@ public JwtDecoder jwtDecoder() throws KeyLengthException {
private Customizer<OAuth2ResourceServerConfigurer<HttpSecurity>> configOAuth2() {
final var converter = new CustomJwtAuthenticationConverter(this.userRepository, this.localeMessage);

return oauth -> oauth.jwt(jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(converter));
return oauth -> oauth.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.jwt(jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(converter));
}

}

0 comments on commit a1d82c3

Please sign in to comment.