Untitled

mail@pastecode.io avatarunknown
java
a month ago
5.0 kB
3
Indexable
Never
package com.decode.msapp.apigw.config;

import com.decode.msapp.apigw.exceptions.AuthHeaderMissingException;
import com.decode.msapp.apigw.exceptions.CantValidateTokenException;
import com.decode.msapp.apigw.service.JwtService;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

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

@Component
@Slf4j
/* Filters inbound requests for auth Token, might consider to use GlobalFilter
    for requests to ALL microservices */
public class AuthFilter extends AbstractGatewayFilterFactory<AuthFilter.Config> {
    private final RouteValidator routeValidator;
    private final WebClient webClient;
    private final JwtService jwtService;
    private static String AUTH_ERROR_PAGE_URL;

    public AuthFilter(RouteValidator routeValidator, WebClient.Builder webClientBuilder, JwtService jwtService) {
        super(Config.class);
        this.routeValidator=routeValidator;
        this.webClient=webClientBuilder.build();
        this.jwtService=jwtService;
    }

    @Override
    public GatewayFilter apply(Config config) {
        return ((exchange, chain) -> {
            ServerHttpRequest request = null;
            if (routeValidator.isSecured.test(exchange.getRequest())) {
                if (!exchange.getRequest().getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {
                    log.error("No authorization Token was provided in the request's header");
                    return chain.filter(getModifiedExchange(exchange));
                }

                String authHeader = exchange.getRequest().getHeaders().get(HttpHeaders.AUTHORIZATION).get(0);
                if (authHeader!=null && authHeader.startsWith("Bearer ")) {
                    authHeader = authHeader.substring(7);
                    var authHeaderSearch = authHeader;
                    Mono<String> result;
                    try {
                        result = webClient.get()
                                .uri(uriBuilder -> uriBuilder.path("/users/validate")
                                        .queryParam("token", authHeaderSearch)
                                        .build())
                                .retrieve()
                                .bodyToMono(String.class)
                                .onErrorResume(Exception.class, throwable -> Mono.error(new CantValidateTokenException("")))
                        ;

                        result
                            .onErrorResume(Exception.class, throwable -> Mono.error(new CantValidateTokenException("")))
                            .subscribe(e -> log.info("Tocken check result is: " + e))
                        ;

                        /* Adding User information to request payload */
                        var userNameJWT=jwtService.extractUsername(authHeader);
                        var userRoleJWT=jwtService.extractUserRole(authHeader);
                        request = exchange.getRequest()
                                .mutate()
                                .header("loggedInUser", userNameJWT)
                                .header("loggedInRole", userRoleJWT)
                                .build();

                    } catch (Exception e) {
                        log.error("The Token was invalid or can't be checked. Exception: {}, Message: {} ", e.getClass(), e.getMessage());
                        return chain.filter(getModifiedExchange(exchange));
                    }
                }


            }

                return chain.filter(exchange.mutate().request(request).build());
            });
    }

    /* Redirects to auth error page if there was no Token, or it's invalid */
    private static ServerWebExchange getModifiedExchange(ServerWebExchange exchange) {
        log.info("No token was found, redirecting to auth page: {}", AUTH_ERROR_PAGE_URL);
        ServerHttpRequest modifiedRequest = exchange.getRequest()
                    .mutate()
                    .uri(URI.create(AUTH_ERROR_PAGE_URL))
                    .build();
        return exchange.mutate().request(modifiedRequest).build();
    }

    public static class Config {
    }

    //Setter for static URL
    @Value("${app.authfailurl}")
    public void setURLStatic(String url){
        AuthFilter.AUTH_ERROR_PAGE_URL = url;
    }
}