Skip to content

Commit

Permalink
Logging api requests with invalid tokens
Browse files Browse the repository at this point in the history
Fixed request with invalid token with internal server error
  • Loading branch information
Alf-Melmac committed Oct 5, 2021
1 parent 870ceec commit 4e17a02
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package de.webalf.slotbot.configuration.authentication.api;

import de.webalf.slotbot.exception.ForbiddenException;
import de.webalf.slotbot.model.authentication.ApiToken;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.NonNull;
import org.springframework.security.core.Authentication;
Expand All @@ -11,6 +12,7 @@
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
Expand All @@ -28,12 +30,18 @@
* @since 23.09.2020
*/
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class TokenAuthFilter extends OncePerRequestFilter {
@Value("${slotbot.auth.token.name:slotbot-auth-token}")
private String tokenName;

private final TokenAuthProvider tokenAuthProvider;
private final HandlerExceptionResolver resolver;

@Autowired
public TokenAuthFilter(TokenAuthProvider tokenAuthProvider, @Qualifier("handlerExceptionResolver") HandlerExceptionResolver resolver) {
this.tokenAuthProvider = tokenAuthProvider;
this.resolver = resolver;
}

@Override
protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws IOException, ServletException {
Expand All @@ -42,15 +50,22 @@ protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServlet

// if there is an auth token, create an Authentication object
if (authToken != null) {
final Authentication auth = new SlotbotAuthentication(authToken, mapAuthorities(authToken));
Set<GrantedAuthority> grantedAuthorities;
try {
grantedAuthorities = mapAuthorities(authToken);
} catch (ForbiddenException ex) {
resolver.resolveException(request, response, null, ex);
return;
}
final Authentication auth = new SlotbotAuthentication(authToken, grantedAuthorities);
SecurityContextHolder.getContext().setAuthentication(auth);
}

// forward the request
filterChain.doFilter(request, response);
}

private Set<GrantedAuthority> mapAuthorities(@NotBlank String token) {
private Set<GrantedAuthority> mapAuthorities(@NotBlank String token) throws ForbiddenException {
final ApiToken apiToken = tokenAuthProvider.getApiToken(token);
return Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + apiToken.getType().name()));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package de.webalf.slotbot.configuration.authentication.api;

import de.webalf.slotbot.exception.ForbiddenException;
import de.webalf.slotbot.model.authentication.ApiToken;
import de.webalf.slotbot.repository.ApiTokenRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

Expand All @@ -15,6 +16,7 @@
*/
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Slf4j
public class TokenAuthProvider implements AuthenticationProvider {
private final ApiTokenRepository apiTokenRepository;

Expand All @@ -28,8 +30,11 @@ public boolean supports(Class<?> arg0) {
return (SlotbotAuthentication.class.isAssignableFrom(arg0));
}

ApiToken getApiToken(String token) {
ApiToken getApiToken(String token) throws ForbiddenException {
return apiTokenRepository.findById(token)
.orElseThrow(() -> new BadCredentialsException("Invalid token '" + token + "'"));
.orElseThrow(() -> {
log.warn("Received request with invalid token {}", token);
return new ForbiddenException("Invalid token '" + token + "'");
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package de.webalf.slotbot.exception;

import org.springframework.core.annotation.Order;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

import static de.webalf.slotbot.exception.RestResponseEntityExceptionHandler.determineHttpStatus;

/**
* Handles exceptions matched by {@link RestControllerAdvice}.
* <p>
* This translates exceptions to human-readable and valuable error messages for the caller.
*
* @author Alf
* @since 05.10.2021
*/
@RestControllerAdvice
@Order(3)
public class OtherResponseEntityExceptionHandler {
@ExceptionHandler(ForbiddenException.class)
protected ResponseEntity<?> handleConflict(RuntimeException ex, HttpServletRequest request) {
return new ResponseEntity<>(
ExceptionResponse.builder()
.errorMessage(ex.getMessage())
.requestedURI(request.getRequestURI())
.build(),
determineHttpStatus(ex));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
import java.util.stream.Collectors;

/**
* Handles exceptions thrown in all layers.
* Handles exceptions thrown in controllers annotated with {@link RestController}.
* <p>
* This translated exceptions to human readable and valuable error messages for the caller.
* This translates exceptions to human-readable and valuable error messages for the caller.
*
* @author Alf
* @since 09.08.2020
Expand Down Expand Up @@ -80,7 +80,7 @@ private String determineErrorMessage(Exception e) {
* @param e exception to check
* @return annotated Status or HttpStatus.INTERNAL_SERVER_ERROR
*/
private HttpStatus determineHttpStatus(Exception e) {
static HttpStatus determineHttpStatus(Exception e) {
if (e instanceof BadCredentialsException) {
return HttpStatus.UNAUTHORIZED;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
import org.springframework.web.servlet.view.RedirectView;

/**
* Handles exceptions thrown in controllers annotated with {@link Controller}.
* <p>
* This translates exceptions to human-readable and valuable error messages for the caller.
*
* @author Alf
* @since 09.06.2021
*/
@ControllerAdvice(annotations = Controller.class)
@Order(2)
@Slf4j
public class WebResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
public class WebResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler(value = {ResourceNotFoundException.class, MethodArgumentTypeMismatchException.class})
protected RedirectView handleConflict(RuntimeException ex) {
Expand Down

0 comments on commit 4e17a02

Please sign in to comment.