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
}
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()));
}
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()));
}
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
}
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");
}
Aggregations