private Mono<Authentication> currentAuthentication() { return ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .defaultIfEmpty(ANONYMOUS_USER_TOKEN); }
@Test public void setContextAndClearAndGetContextThenEmitsEmpty() { SecurityContext expectedContext = new SecurityContextImpl( new TestingAuthenticationToken("user", "password", "ROLE_USER")); Mono<SecurityContext> context = Mono.subscriberContext() .flatMap( c -> ReactiveSecurityContextHolder.getContext()) .subscriberContext(ReactiveSecurityContextHolder.clearContext()) .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(expectedContext))); StepVerifier.create(context) .verifyComplete(); }
@Test public void demo() { Authentication authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); Mono<String> messageByUsername = ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .map(Authentication::getName) .flatMap(this::findMessageByUsername) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)); StepVerifier.create(messageByUsername) .expectNext("Hi user") .verifyComplete(); }
@Test public void setContextAndGetContextThenEmitsContext() { SecurityContext expectedContext = new SecurityContextImpl( new TestingAuthenticationToken("user", "password", "ROLE_USER")); Mono<SecurityContext> context = Mono.subscriberContext() .flatMap( c -> ReactiveSecurityContextHolder.getContext()) .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(expectedContext))); StepVerifier.create(context) .expectNext(expectedContext) .verifyComplete(); }
/** * A shortcut for {@link #withSecurityContext(Mono)} * @param authentication the {@link Authentication} to be used * @return a Reactor {@link Context} that contains the {@code Mono<SecurityContext>} */ public static Context withAuthentication(Authentication authentication) { return withSecurityContext(Mono.just(new SecurityContextImpl(authentication))); } }
private Object resolveArgument(MethodParameter methodParameter) { return this.argumentResolver.resolveArgument(methodParameter, null, null) .subscriberContext(this.authentication == null ? Context.empty() : ReactiveSecurityContextHolder.withAuthentication(this.authentication)) .block(); }
private Mono<Void> logout(WebFilterExchange webFilterExchange, Authentication authentication) { return this.logoutHandler.logout(webFilterExchange, authentication) .then(this.logoutSuccessHandler .onLogoutSuccess(webFilterExchange, authentication)) .subscriberContext(ReactiveSecurityContextHolder.clearContext()); }
/** * A shortcut for {@link #withSecurityContext(Mono)} * @param authentication the {@link Authentication} to be used * @return a Reactor {@link Context} that contains the {@code Mono<SecurityContext>} */ public static Context withAuthentication(Authentication authentication) { return withSecurityContext(Mono.just(new SecurityContextImpl(authentication))); } }
@Test public void filterWhenDefaultOAuth2AuthorizedClientFalseThenEmpty() { ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) .build(); OAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections .singletonMap("user", "rob"), "user"); OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(user, user.getAuthorities(), "client-id"); this.function .filter(request, this.exchange) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) .block(); List<ClientRequest> requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); verifyZeroInteractions(this.clientRegistrationRepository, this.authorizedClientRepository); }
private Mono<Authentication> currentAuthentication() { return ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .defaultIfEmpty(ANONYMOUS_USER_TOKEN); }
@Test public void setAuthenticationAndGetContextThenEmitsContext() { Authentication expectedAuthentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); Mono<Authentication> authentication = Mono.subscriberContext() .flatMap( c -> ReactiveSecurityContextHolder.getContext()) .map(SecurityContext::getAuthentication) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expectedAuthentication)); StepVerifier.create(authentication) .expectNext(expectedAuthentication) .verifyComplete(); } }
/** * A shortcut for {@link #withSecurityContext(Mono)} * @param authentication the {@link Authentication} to be used * @return a Reactor {@link Context} that contains the {@code Mono<SecurityContext>} */ public static Context withAuthentication(Authentication authentication) { return withSecurityContext(Mono.just(new SecurityContextImpl(authentication))); } }
@Test public void filterWhenClientCredentialsTokenNotExpiredThenUseCurrentToken() { TestingAuthenticationToken authentication = new TestingAuthenticationToken("test", "this"); ClientRegistration registration = TestClientRegistrations.clientCredentials().build(); this.function = new ServerOAuth2AuthorizedClientExchangeFilterFunction(this.authorizedClientRepository, this.authorizedClientResolver); OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(registration, "principalName", this.accessToken, null); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) .attributes(oauth2AuthorizedClient(authorizedClient)) .build(); this.function.filter(request, this.exchange) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) .block(); verify(this.authorizedClientResolver, never()).clientCredentials(any(), any(), any()); verify(this.authorizedClientResolver, never()).createDefaultedRequest(any(), any(), any()); List<ClientRequest> requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); ClientRequest request1 = requests.get(0); assertThat(request1.headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo("Bearer token-0"); assertThat(request1.url().toASCIIString()).isEqualTo("https://example.com"); assertThat(request1.method()).isEqualTo(HttpMethod.GET); assertThat(getBody(request1)).isEmpty(); }
private ServerWebExchangeMatcher createAttemptAuthenticationRequestMatcher() { PathPatternParserServerWebExchangeMatcher loginPathMatcher = new PathPatternParserServerWebExchangeMatcher("/login/oauth2/code/{registrationId}"); ServerWebExchangeMatcher notAuthenticatedMatcher = e -> ReactiveSecurityContextHolder.getContext() .flatMap(p -> ServerWebExchangeMatcher.MatchResult.notMatch()) .switchIfEmpty(ServerWebExchangeMatcher.MatchResult.match()); return new AndServerWebExchangeMatcher(loginPathMatcher, notAuthenticatedMatcher); }
@Override public Context currentContext() { Context context = delegate.currentContext(); if (context.hasKey(CONTEXT_DEFAULTED_ATTR_NAME)) { return context; } context = context.put(CONTEXT_DEFAULTED_ATTR_NAME, Boolean.TRUE); Authentication authentication = securityContext.getAuthentication(); if (authentication == null) { return context; } Context toMerge = ReactiveSecurityContextHolder.withSecurityContext( Mono.just(this.securityContext)); return toMerge.putAll(context); }
@Test public void filterWhenClientRegistrationIdFromAuthenticationThenAuthorizedClientResolved() { this.function.setDefaultOAuth2AuthorizedClient(true); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", this.accessToken, refreshToken); when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(Mono.just(authorizedClient)); when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(this.registration)); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) .build(); OAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections .singletonMap("user", "rob"), "user"); OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(user, user.getAuthorities(), "client-id"); this.function .filter(request, this.exchange) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) .block(); List<ClientRequest> requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); ClientRequest request0 = requests.get(0); assertThat(request0.headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo("Bearer token-0"); assertThat(request0.url().toASCIIString()).isEqualTo("https://example.com"); assertThat(request0.method()).isEqualTo(HttpMethod.GET); assertThat(getBody(request0)).isEmpty(); }
Mono<Authentication> toInvoke = ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .defaultIfEmpty(this.anonymous)
@Override public Context currentContext() { Context context = delegate.currentContext(); if (context.hasKey(CONTEXT_DEFAULTED_ATTR_NAME)) { return context; } context = context.put(CONTEXT_DEFAULTED_ATTR_NAME, Boolean.TRUE); Authentication authentication = securityContext.getAuthentication(); if (authentication == null) { return context; } Context toMerge = ReactiveSecurityContextHolder.withSecurityContext( Mono.just(this.securityContext)); return toMerge.putAll(context); }
.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) .block();
private Mono<Void> onAuthenticationSuccess(Authentication authentication, WebFilterExchange webFilterExchange) { OAuth2AuthorizationCodeAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeAuthenticationToken) authentication; OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( authenticationResult.getClientRegistration(), authenticationResult.getName(), authenticationResult.getAccessToken(), authenticationResult.getRefreshToken()); return this.authenticationSuccessHandler .onAuthenticationSuccess(webFilterExchange, authentication) .then(ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .defaultIfEmpty(this.anonymousToken) .flatMap(principal -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, webFilterExchange.getExchange())) ); } }