Search in sources :

Example 51 with Mono

use of reactor.core.publisher.Mono in project spring-security by spring-projects.

the class JwtBearerReactiveOAuth2AuthorizedClientProvider method authorize.

/**
 * Attempt to authorize (or re-authorize) the
 * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided
 * {@code context}. Returns an empty {@code Mono} if authorization (or
 * re-authorization) is not supported, e.g. the client's
 * {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} is
 * not {@link AuthorizationGrantType#JWT_BEARER jwt-bearer} OR the
 * {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired.
 * @param context the context that holds authorization-specific state for the client
 * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if
 * authorization is not supported
 */
@Override
public Mono<OAuth2AuthorizedClient> authorize(OAuth2AuthorizationContext context) {
    Assert.notNull(context, "context cannot be null");
    ClientRegistration clientRegistration = context.getClientRegistration();
    if (!AuthorizationGrantType.JWT_BEARER.equals(clientRegistration.getAuthorizationGrantType())) {
        return Mono.empty();
    }
    OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient();
    if (authorizedClient != null && !hasTokenExpired(authorizedClient.getAccessToken())) {
        // need for re-authorization
        return Mono.empty();
    }
    // @formatter:off
    return this.jwtAssertionResolver.apply(context).map((jwt) -> new JwtBearerGrantRequest(clientRegistration, jwt)).flatMap(this.accessTokenResponseClient::getTokenResponse).onErrorMap(OAuth2AuthorizationException.class, (ex) -> new ClientAuthorizationException(ex.getError(), clientRegistration.getRegistrationId(), ex)).map((tokenResponse) -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken()));
// @formatter:on
}
Also used : OAuth2AuthorizationException(org.springframework.security.oauth2.core.OAuth2AuthorizationException) Mono(reactor.core.publisher.Mono) ReactiveOAuth2AccessTokenResponseClient(org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient) Instant(java.time.Instant) Function(java.util.function.Function) ClientRegistration(org.springframework.security.oauth2.client.registration.ClientRegistration) Duration(java.time.Duration) Clock(java.time.Clock) WebClientReactiveJwtBearerTokenResponseClient(org.springframework.security.oauth2.client.endpoint.WebClientReactiveJwtBearerTokenResponseClient) Jwt(org.springframework.security.oauth2.jwt.Jwt) AuthorizationGrantType(org.springframework.security.oauth2.core.AuthorizationGrantType) OAuth2Token(org.springframework.security.oauth2.core.OAuth2Token) JwtBearerGrantRequest(org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest) Assert(org.springframework.util.Assert) OAuth2AuthorizationException(org.springframework.security.oauth2.core.OAuth2AuthorizationException) ClientRegistration(org.springframework.security.oauth2.client.registration.ClientRegistration) JwtBearerGrantRequest(org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest)

Example 52 with Mono

use of reactor.core.publisher.Mono in project spring-security by spring-projects.

the class RefreshTokenReactiveOAuth2AuthorizedClientProvider method authorize.

/**
 * Attempt to re-authorize the
 * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided
 * {@code context}. Returns an empty {@code Mono} if re-authorization is not
 * supported, e.g. the client is not authorized OR the
 * {@link OAuth2AuthorizedClient#getRefreshToken() refresh token} is not available for
 * the authorized client OR the {@link OAuth2AuthorizedClient#getAccessToken() access
 * token} is not expired.
 *
 * <p>
 * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes}
 * are supported:
 * <ol>
 * <li>{@code "org.springframework.security.oauth2.client.REQUEST_SCOPE"} (optional) -
 * a {@code String[]} of scope(s) to be requested by the
 * {@link OAuth2AuthorizationContext#getClientRegistration() client}</li>
 * </ol>
 * @param context the context that holds authorization-specific state for the client
 * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if
 * re-authorization is not supported
 */
@Override
public Mono<OAuth2AuthorizedClient> authorize(OAuth2AuthorizationContext context) {
    Assert.notNull(context, "context cannot be null");
    OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient();
    if (authorizedClient == null || authorizedClient.getRefreshToken() == null || !hasTokenExpired(authorizedClient.getAccessToken())) {
        return Mono.empty();
    }
    Object requestScope = context.getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME);
    Set<String> scopes = Collections.emptySet();
    if (requestScope != null) {
        Assert.isInstanceOf(String[].class, requestScope, "The context attribute must be of type String[] '" + OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'");
        scopes = new HashSet<>(Arrays.asList((String[]) requestScope));
    }
    ClientRegistration clientRegistration = context.getClientRegistration();
    OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration, authorizedClient.getAccessToken(), authorizedClient.getRefreshToken(), scopes);
    return Mono.just(refreshTokenGrantRequest).flatMap(this.accessTokenResponseClient::getTokenResponse).onErrorMap(OAuth2AuthorizationException.class, (e) -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e)).map((tokenResponse) -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()));
}
Also used : OAuth2AuthorizationException(org.springframework.security.oauth2.core.OAuth2AuthorizationException) Arrays(java.util.Arrays) WebClientReactiveRefreshTokenTokenResponseClient(org.springframework.security.oauth2.client.endpoint.WebClientReactiveRefreshTokenTokenResponseClient) OAuth2AuthorizationException(org.springframework.security.oauth2.core.OAuth2AuthorizationException) Set(java.util.Set) Mono(reactor.core.publisher.Mono) ReactiveOAuth2AccessTokenResponseClient(org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient) Instant(java.time.Instant) ClientRegistration(org.springframework.security.oauth2.client.registration.ClientRegistration) HashSet(java.util.HashSet) OAuth2RefreshTokenGrantRequest(org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest) Duration(java.time.Duration) Clock(java.time.Clock) Collections(java.util.Collections) AuthorizationGrantType(org.springframework.security.oauth2.core.AuthorizationGrantType) OAuth2Token(org.springframework.security.oauth2.core.OAuth2Token) Assert(org.springframework.util.Assert) ClientRegistration(org.springframework.security.oauth2.client.registration.ClientRegistration) OAuth2RefreshTokenGrantRequest(org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest)

Example 53 with Mono

use of reactor.core.publisher.Mono in project spring-security by spring-projects.

the class PasswordReactiveOAuth2AuthorizedClientProvider method authorize.

/**
 * Attempt to authorize (or re-authorize) the
 * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided
 * {@code context}. Returns an empty {@code Mono} if authorization (or
 * re-authorization) is not supported, e.g. the client's
 * {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} is
 * not {@link AuthorizationGrantType#PASSWORD password} OR the
 * {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME username} and/or
 * {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME password} attributes are
 * not available in the provided {@code context} OR the
 * {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired.
 *
 * <p>
 * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes}
 * are supported:
 * <ol>
 * <li>{@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME} (required) - a
 * {@code String} value for the resource owner's username</li>
 * <li>{@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME} (required) - a
 * {@code String} value for the resource owner's password</li>
 * </ol>
 * @param context the context that holds authorization-specific state for the client
 * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if
 * authorization (or re-authorization) is not supported
 */
@Override
public Mono<OAuth2AuthorizedClient> authorize(OAuth2AuthorizationContext context) {
    Assert.notNull(context, "context cannot be null");
    ClientRegistration clientRegistration = context.getClientRegistration();
    OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient();
    if (!AuthorizationGrantType.PASSWORD.equals(clientRegistration.getAuthorizationGrantType())) {
        return Mono.empty();
    }
    String username = context.getAttribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME);
    String password = context.getAttribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME);
    if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
        return Mono.empty();
    }
    if (authorizedClient != null && !hasTokenExpired(authorizedClient.getAccessToken())) {
        // need for re-authorization
        return Mono.empty();
    }
    if (authorizedClient != null && hasTokenExpired(authorizedClient.getAccessToken()) && authorizedClient.getRefreshToken() != null) {
        // handle the refresh
        return Mono.empty();
    }
    OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest(clientRegistration, username, password);
    return Mono.just(passwordGrantRequest).flatMap(this.accessTokenResponseClient::getTokenResponse).onErrorMap(OAuth2AuthorizationException.class, (e) -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e)).map((tokenResponse) -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken(), tokenResponse.getRefreshToken()));
}
Also used : OAuth2AuthorizationException(org.springframework.security.oauth2.core.OAuth2AuthorizationException) OAuth2AuthorizationException(org.springframework.security.oauth2.core.OAuth2AuthorizationException) Mono(reactor.core.publisher.Mono) ReactiveOAuth2AccessTokenResponseClient(org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient) OAuth2PasswordGrantRequest(org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest) Instant(java.time.Instant) ClientRegistration(org.springframework.security.oauth2.client.registration.ClientRegistration) WebClientReactivePasswordTokenResponseClient(org.springframework.security.oauth2.client.endpoint.WebClientReactivePasswordTokenResponseClient) Duration(java.time.Duration) Clock(java.time.Clock) AuthorizationGrantType(org.springframework.security.oauth2.core.AuthorizationGrantType) OAuth2Token(org.springframework.security.oauth2.core.OAuth2Token) Assert(org.springframework.util.Assert) StringUtils(org.springframework.util.StringUtils) ClientRegistration(org.springframework.security.oauth2.client.registration.ClientRegistration) OAuth2PasswordGrantRequest(org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest)

Example 54 with Mono

use of reactor.core.publisher.Mono in project spring-security by spring-projects.

the class OAuth2AuthorizationCodeGrantWebFilter method onAuthenticationSuccess.

private Mono<Void> onAuthenticationSuccess(Authentication authentication, WebFilterExchange webFilterExchange) {
    OAuth2AuthorizationCodeAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeAuthenticationToken) authentication;
    OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(authenticationResult.getClientRegistration(), authenticationResult.getName(), authenticationResult.getAccessToken(), authenticationResult.getRefreshToken());
    // @formatter:off
    return this.authenticationSuccessHandler.onAuthenticationSuccess(webFilterExchange, authentication).then(ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication).defaultIfEmpty(this.anonymousToken).flatMap((principal) -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, webFilterExchange.getExchange())));
// @formatter:on
}
Also used : OAuth2ParameterNames(org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames) UriComponentsBuilder(org.springframework.web.util.UriComponentsBuilder) ServerWebExchangeMatcher(org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher) OAuth2AuthorizationException(org.springframework.security.oauth2.core.OAuth2AuthorizationException) ServerWebExchange(org.springframework.web.server.ServerWebExchange) ServerAuthenticationConverter(org.springframework.security.web.server.authentication.ServerAuthenticationConverter) WebFilterExchange(org.springframework.security.web.server.WebFilterExchange) OAuth2AuthorizationCodeAuthenticationToken(org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken) ReactiveSecurityContextHolder(org.springframework.security.core.context.ReactiveSecurityContextHolder) WebFilter(org.springframework.web.server.WebFilter) Map(java.util.Map) ReactiveAuthenticationManager(org.springframework.security.authentication.ReactiveAuthenticationManager) WebSessionServerRequestCache(org.springframework.security.web.server.savedrequest.WebSessionServerRequestCache) AuthenticationException(org.springframework.security.core.AuthenticationException) URI(java.net.URI) AuthorizationRequestRepository(org.springframework.security.oauth2.client.web.AuthorizationRequestRepository) LinkedHashSet(java.util.LinkedHashSet) WebFilterChain(org.springframework.web.server.WebFilterChain) OAuth2AuthorizationResponse(org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse) ReactiveClientRegistrationRepository(org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository) ServerRequestCache(org.springframework.security.web.server.savedrequest.ServerRequestCache) OAuth2AuthenticationException(org.springframework.security.oauth2.core.OAuth2AuthenticationException) OAuth2AuthorizationRequest(org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest) Set(java.util.Set) Mono(reactor.core.publisher.Mono) ServerAuthenticationSuccessHandler(org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler) OAuth2AuthorizedClient(org.springframework.security.oauth2.client.OAuth2AuthorizedClient) Objects(java.util.Objects) List(java.util.List) SecurityContext(org.springframework.security.core.context.SecurityContext) AnonymousAuthenticationToken(org.springframework.security.authentication.AnonymousAuthenticationToken) Authentication(org.springframework.security.core.Authentication) AuthorityUtils(org.springframework.security.core.authority.AuthorityUtils) RedirectServerAuthenticationSuccessHandler(org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler) ServerAuthenticationFailureHandler(org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler) Assert(org.springframework.util.Assert) UriComponents(org.springframework.web.util.UriComponents) OAuth2AuthorizationCodeAuthenticationToken(org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken) OAuth2AuthorizedClient(org.springframework.security.oauth2.client.OAuth2AuthorizedClient)

Example 55 with Mono

use of reactor.core.publisher.Mono in project spring-security by spring-projects.

the class OAuth2BodyExtractorsTests method oauth2AccessTokenResponseWhenValidThenCreated.

@Test
public void oauth2AccessTokenResponseWhenValidThenCreated() {
    BodyExtractor<Mono<OAuth2AccessTokenResponse>, ReactiveHttpInputMessage> extractor = OAuth2BodyExtractors.oauth2AccessTokenResponse();
    MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK);
    response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
    // @formatter:off
    response.setBody("{\n" + "       \"access_token\":\"2YotnFZFEjr1zCsicMWpAA\",\n" + "       \"token_type\":\"Bearer\",\n" + "       \"expires_in\":3600,\n" + "       \"refresh_token\":\"tGzv3JOkF0XG5Qx2TlKWIA\",\n" + "       \"example_parameter\":\"example_value\"\n" + "     }");
    // @formatter:on
    Instant now = Instant.now();
    OAuth2AccessTokenResponse result = extractor.extract(response, this.context).block();
    assertThat(result.getAccessToken().getTokenValue()).isEqualTo("2YotnFZFEjr1zCsicMWpAA");
    assertThat(result.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER);
    assertThat(result.getAccessToken().getExpiresAt()).isBetween(now.plusSeconds(3600), now.plusSeconds(3600 + 2));
    assertThat(result.getRefreshToken().getTokenValue()).isEqualTo("tGzv3JOkF0XG5Qx2TlKWIA");
    assertThat(result.getAdditionalParameters()).containsEntry("example_parameter", "example_value");
}
Also used : OAuth2AccessTokenResponse(org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse) Mono(reactor.core.publisher.Mono) Instant(java.time.Instant) ReactiveHttpInputMessage(org.springframework.http.ReactiveHttpInputMessage) MockClientHttpResponse(org.springframework.mock.http.client.reactive.MockClientHttpResponse) Test(org.junit.jupiter.api.Test)

Aggregations

Mono (reactor.core.publisher.Mono)308 Test (org.junit.jupiter.api.Test)143 StepVerifier (reactor.test.StepVerifier)117 List (java.util.List)116 Flux (reactor.core.publisher.Flux)110 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)102 Collections (java.util.Collections)85 Map (java.util.Map)75 HttpStatus (org.springframework.http.HttpStatus)66 ServerWebExchange (org.springframework.web.server.ServerWebExchange)65 Duration (java.time.Duration)60 ArrayList (java.util.ArrayList)58 Test (org.junit.Test)53 MockServerHttpRequest (org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest)52 DataBuffer (org.springframework.core.io.buffer.DataBuffer)51 Assert (org.springframework.util.Assert)49 Mockito.mock (org.mockito.Mockito.mock)48 MockServerWebExchange (org.springframework.web.testfixture.server.MockServerWebExchange)46 Optional (java.util.Optional)44 StandardCharsets (java.nio.charset.StandardCharsets)43