Skip to content

Split responsibility of ServerHttpBearerAuthenticationConverter #2

@eximius313

Description

@eximius313

I think ServerHttpBearerAuthenticationConverter should be used only for preparing the token for further processing:

Mono.justOrEmpty(serverWebExchange)
                .map(JWTAuthorizationPayload::extract)

while authenticating the token:

map(VerifySignedJWT::check)
                .map(UsernamePasswordAuthenticationFromJWTToken::create)

is the responsibility of JWTReactiveAuthenticationManager

By the way - instead of providing own implementation of JWTAuthorizationWebFilter just do:

@Component
public class JWTAuthenticationWebFilter extends AuthenticationWebFilter {

    public JWTAuthenticationWebFilter(final JWTAuthenticationManager authenticationManager,
            final ServerHttpBearerAuthenticationConverter converter,
            final UnauthorizedAuthenticationEntryPoint entryPoint) {
        super(authenticationManager);
        setAuthenticationConverter(converter);
        setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(entryPoint));
        setRequiresAuthenticationMatcher(new JWTHeadersExchangeMatcher()); //this is necessary to match headers. Requests without JWT header should not be taken into account by this filter
    }
    private static class JWTHeadersExchangeMatcher implements ServerWebExchangeMatcher {

        @Override
        public Mono<MatchResult> matches(final ServerWebExchange exchange) {
            return Mono.just(exchange)
                    .map(ServerWebExchange::getRequest)
                    .map(ServerHttpRequest::getHeaders)
                    .filter(h -> h.containsKey("some JWT header"))
                    .flatMap($ -> MatchResult.match())
                    .switchIfEmpty(MatchResult.notMatch());
        }
    }
}

And don't forget to set:

        http
            .exceptionHandling()
                .authenticationEntryPoint(new UnauthorizedAuthenticationEntryPoint ())
            .and()

where

@Component
public class UnauthorizedAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {

	@Override
	public Mono<Void> commence(final ServerWebExchange exchange, final AuthenticationException e) {
		return Mono.fromRunnable(() -> exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED));
	}
}

otherwise SpringSecurity will still display BasicAuth on requests without headers

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions