Polish gh-470
This commit is contained in:
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.context.Context;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* A context that holds an {@link OAuth2AuthorizationConsent.Builder} and (optionally) additional information
|
||||
* and is used when customizing the building of {@link OAuth2AuthorizationConsent}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
* @since 0.2.1
|
||||
* @see Context
|
||||
*/
|
||||
public final class OAuth2AuthorizationConsentContext implements Context {
|
||||
private final Map<Object, Object> context;
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2AuthorizationConsentContext} using the provided parameters.
|
||||
*
|
||||
* @param context a {@code Map} of additional context information
|
||||
*/
|
||||
private OAuth2AuthorizationConsentContext(@Nullable Map<Object, Object> context) {
|
||||
this.context = new HashMap<>();
|
||||
if (!CollectionUtils.isEmpty(context)) {
|
||||
this.context.putAll(context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2AuthorizationConsent.Builder authorization consent builder}.
|
||||
*
|
||||
* @return the {@link OAuth2AuthorizationConsent.Builder}
|
||||
*/
|
||||
public OAuth2AuthorizationConsent.Builder getAuthorizationConsentBuilder() {
|
||||
return get(OAuth2AuthorizationConsent.Builder.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Authentication} representing the {@code Principal} resource owner (or client).
|
||||
*
|
||||
* @param <T> the type of the {@code Authentication}
|
||||
* @return the {@link Authentication} representing the {@code Principal} resource owner (or client)
|
||||
*/
|
||||
@Nullable
|
||||
public <T extends Authentication> T getPrincipal() {
|
||||
return get(Builder.PRINCIPAL_AUTHENTICATION_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link RegisteredClient registered client}.
|
||||
*
|
||||
* @return the {@link RegisteredClient}, or {@code null} if not available
|
||||
*/
|
||||
@Nullable
|
||||
public RegisteredClient getRegisteredClient() {
|
||||
return get(RegisteredClient.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2Authorization authorization}.
|
||||
*
|
||||
* @return the {@link OAuth2Authorization}, or {@code null} if not available
|
||||
*/
|
||||
@Nullable
|
||||
public OAuth2Authorization getAuthorization() {
|
||||
return get(OAuth2Authorization.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2AuthorizationRequest authorization request}.
|
||||
*
|
||||
* @return the {@link OAuth2AuthorizationRequest}, or {@code null} if not available
|
||||
*/
|
||||
@Nullable
|
||||
public OAuth2AuthorizationRequest getAuthorizationRequest() {
|
||||
return get(OAuth2AuthorizationRequest.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <V> V get(Object key) {
|
||||
return (V) this.context.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasKey(Object key) {
|
||||
return this.context.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Builder} with the provided {@link OAuth2AuthorizationConsent.Builder}.
|
||||
*
|
||||
* @param authorizationConsentBuilder the {@link OAuth2AuthorizationConsent.Builder} to initialize the builder
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public static OAuth2AuthorizationConsentContext.Builder with(OAuth2AuthorizationConsent.Builder authorizationConsentBuilder) {
|
||||
return new Builder(authorizationConsentBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for {@link OAuth2AuthorizationConsentContext}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private static final String PRINCIPAL_AUTHENTICATION_KEY =
|
||||
Authentication.class.getName().concat(".PRINCIPAL");
|
||||
private final Map<Object, Object> context = new HashMap<>();
|
||||
|
||||
private Builder(OAuth2AuthorizationConsent.Builder authorizationConsentBuilder) {
|
||||
Assert.notNull(authorizationConsentBuilder, "authorizationConsentBuilder cannot be null");
|
||||
put(OAuth2AuthorizationConsent.Builder.class, authorizationConsentBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Authentication} representing the {@code Principal} resource owner (or client).
|
||||
*
|
||||
* @param principal the {@link Authentication} representing the {@code Principal} resource owner (or client)
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder principal(Authentication principal) {
|
||||
return put(PRINCIPAL_AUTHENTICATION_KEY, principal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link RegisteredClient registered client}.
|
||||
*
|
||||
* @param registeredClient the {@link RegisteredClient}
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder registeredClient(RegisteredClient registeredClient) {
|
||||
return put(RegisteredClient.class, registeredClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OAuth2Authorization authorization}.
|
||||
*
|
||||
* @param authorization the {@link OAuth2Authorization}
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder authorization(OAuth2Authorization authorization) {
|
||||
return put(OAuth2Authorization.class, authorization);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OAuth2AuthorizationRequest authorization request}.
|
||||
*
|
||||
* @param authorizationRequest the {@link OAuth2AuthorizationRequest}
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder authorizationRequest(OAuth2AuthorizationRequest authorizationRequest) {
|
||||
return put(OAuth2AuthorizationRequest.class, authorizationRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates an attribute.
|
||||
*
|
||||
* @param key the key for the attribute
|
||||
* @param value the value of the attribute
|
||||
* @return the {@link OAuth2TokenContext.AbstractBuilder} for further configuration
|
||||
*/
|
||||
public Builder put(Object key, Object value) {
|
||||
Assert.notNull(key, "key cannot be null");
|
||||
Assert.notNull(value, "value cannot be null");
|
||||
this.context.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code Consumer} of the attributes {@code Map}
|
||||
* allowing the ability to add, replace, or remove.
|
||||
*
|
||||
* @param contextConsumer a {@link Consumer} of the attributes {@code Map}
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder context(Consumer<Map<Object, Object>> contextConsumer) {
|
||||
contextConsumer.accept(this.context);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new {@link OAuth2AuthorizationConsentContext}.
|
||||
*
|
||||
* @return the {@link OAuth2AuthorizationConsentContext}
|
||||
*/
|
||||
public OAuth2AuthorizationConsentContext build() {
|
||||
return new OAuth2AuthorizationConsentContext(this.context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,12 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
|
||||
@@ -47,7 +47,6 @@ import org.springframework.security.oauth2.core.endpoint.PkceParameterNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
@@ -62,6 +61,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* used in the Authorization Code Grant.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @author Steve Riesenberg
|
||||
* @since 0.1.2
|
||||
* @see OAuth2AuthorizationCodeRequestAuthenticationToken
|
||||
* @see OAuth2AuthorizationCodeAuthenticationProvider
|
||||
@@ -84,7 +84,7 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
private final OAuth2AuthorizationConsentService authorizationConsentService;
|
||||
private Supplier<String> authorizationCodeGenerator = DEFAULT_AUTHORIZATION_CODE_GENERATOR::generateKey;
|
||||
private Function<String, OAuth2AuthenticationValidator> authenticationValidatorResolver = DEFAULT_AUTHENTICATION_VALIDATOR_RESOLVER;
|
||||
private Customizer<OAuth2AuthorizationConsentContext> authorizationConsentCustomizer;
|
||||
private Consumer<OAuth2AuthorizationConsentAuthenticationContext> authorizationConsentCustomizer;
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2AuthorizationCodeRequestAuthenticationProvider} using the provided parameters.
|
||||
@@ -149,25 +149,26 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Customizer} providing access to the {@link OAuth2AuthorizationConsentContext} containing an
|
||||
* {@link OAuth2AuthorizationConsent.Builder}.
|
||||
* Sets the {@code Consumer} providing access to the {@link OAuth2AuthorizationConsentAuthenticationContext}
|
||||
* containing an {@link OAuth2AuthorizationConsent.Builder} and additional context information.
|
||||
*
|
||||
* <p>
|
||||
* The following context attributes are available:
|
||||
* <ul>
|
||||
* <li>The {@link OAuth2AuthorizationConsent.Builder} used to build the authorization consent
|
||||
* prior to {@link OAuth2AuthorizationConsentService#save(OAuth2AuthorizationConsent)}</li>
|
||||
* <li>The {@link Authentication authentication principal} of type
|
||||
* {@link OAuth2AuthorizationCodeRequestAuthenticationToken}</li>
|
||||
* prior to {@link OAuth2AuthorizationConsentService#save(OAuth2AuthorizationConsent)}.</li>
|
||||
* <li>The {@link Authentication} of type
|
||||
* {@link OAuth2AuthorizationCodeRequestAuthenticationToken}.</li>
|
||||
* <li>The {@link RegisteredClient} associated with the authorization request.</li>
|
||||
* <li>The {@link OAuth2Authorization} associated with the state token presented in the
|
||||
* authorization consent request.</li>
|
||||
* <li>The {@link OAuth2AuthorizationRequest} requiring the resource owner's consent.</li>
|
||||
* <li>The {@link OAuth2AuthorizationRequest} associated with the authorization consent request.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param authorizationConsentCustomizer the {@link Customizer} providing access to the
|
||||
* {@link OAuth2AuthorizationConsentContext} containing an {@link OAuth2AuthorizationConsent.Builder}
|
||||
* @param authorizationConsentCustomizer the {@code Consumer} providing access to the
|
||||
* {@link OAuth2AuthorizationConsentAuthenticationContext} containing an {@link OAuth2AuthorizationConsent.Builder}
|
||||
*/
|
||||
public void setAuthorizationConsentCustomizer(Customizer<OAuth2AuthorizationConsentContext> authorizationConsentCustomizer) {
|
||||
public void setAuthorizationConsentCustomizer(Consumer<OAuth2AuthorizationConsentAuthenticationContext> authorizationConsentCustomizer) {
|
||||
Assert.notNull(authorizationConsentCustomizer, "authorizationConsentCustomizer cannot be null");
|
||||
this.authorizationConsentCustomizer = authorizationConsentCustomizer;
|
||||
}
|
||||
@@ -328,8 +329,8 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
Set<String> currentAuthorizedScopes = currentAuthorizationConsent != null ?
|
||||
currentAuthorizationConsent.getScopes() : Collections.emptySet();
|
||||
|
||||
if (authorizedScopes.isEmpty() && currentAuthorizedScopes.isEmpty()
|
||||
&& authorizationCodeRequestAuthentication.getAdditionalParameters().isEmpty()) {
|
||||
if (authorizedScopes.isEmpty() && currentAuthorizedScopes.isEmpty() &&
|
||||
authorizationCodeRequestAuthentication.getAdditionalParameters().isEmpty()) {
|
||||
// Authorization consent denied
|
||||
this.authorizationService.remove(authorization);
|
||||
throwError(OAuth2ErrorCodes.ACCESS_DENIED, OAuth2ParameterNames.CLIENT_ID,
|
||||
@@ -360,15 +361,14 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
|
||||
if (this.authorizationConsentCustomizer != null) {
|
||||
// @formatter:off
|
||||
OAuth2AuthorizationConsentContext authorizationConsentContext =
|
||||
OAuth2AuthorizationConsentContext.with(authorizationConsentBuilder)
|
||||
.principal(authorizationCodeRequestAuthentication)
|
||||
OAuth2AuthorizationConsentAuthenticationContext authorizationConsentAuthenticationContext =
|
||||
OAuth2AuthorizationConsentAuthenticationContext.with(authorizationCodeRequestAuthentication, authorizationConsentBuilder)
|
||||
.registeredClient(registeredClient)
|
||||
.authorization(authorization)
|
||||
.authorizationRequest(authorizationRequest)
|
||||
.build();
|
||||
// @formatter:on
|
||||
this.authorizationConsentCustomizer.customize(authorizationConsentContext);
|
||||
this.authorizationConsentCustomizer.accept(authorizationConsentAuthenticationContext);
|
||||
}
|
||||
|
||||
OAuth2AuthorizationConsent authorizationConsent = authorizationConsentBuilder.build();
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.authentication;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.authentication.OAuth2AuthenticationContext;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An {@link OAuth2AuthenticationContext} that holds an {@link OAuth2AuthorizationConsent.Builder} and additional information
|
||||
* and is used when customizing the building of the {@link OAuth2AuthorizationConsent}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
* @author Joe Grandja
|
||||
* @since 0.2.1
|
||||
* @see OAuth2AuthenticationContext
|
||||
* @see OAuth2AuthorizationConsent
|
||||
*/
|
||||
public final class OAuth2AuthorizationConsentAuthenticationContext extends OAuth2AuthenticationContext {
|
||||
|
||||
private OAuth2AuthorizationConsentAuthenticationContext(Map<Object, Object> context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2AuthorizationConsent.Builder authorization consent builder}.
|
||||
*
|
||||
* @return the {@link OAuth2AuthorizationConsent.Builder}
|
||||
*/
|
||||
public OAuth2AuthorizationConsent.Builder getAuthorizationConsent() {
|
||||
return get(OAuth2AuthorizationConsent.Builder.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link RegisteredClient registered client}.
|
||||
*
|
||||
* @return the {@link RegisteredClient}
|
||||
*/
|
||||
public RegisteredClient getRegisteredClient() {
|
||||
return get(RegisteredClient.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2Authorization authorization}.
|
||||
*
|
||||
* @return the {@link OAuth2Authorization}
|
||||
*/
|
||||
public OAuth2Authorization getAuthorization() {
|
||||
return get(OAuth2Authorization.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2AuthorizationRequest authorization request}.
|
||||
*
|
||||
* @return the {@link OAuth2AuthorizationRequest}
|
||||
*/
|
||||
public OAuth2AuthorizationRequest getAuthorizationRequest() {
|
||||
return get(OAuth2AuthorizationRequest.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Builder} with the provided {@link Authentication} and {@link OAuth2AuthorizationConsent.Builder}.
|
||||
*
|
||||
* @param authentication the {@link Authentication}
|
||||
* @param authorizationConsentBuilder the {@link OAuth2AuthorizationConsent.Builder}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public static Builder with(Authentication authentication, OAuth2AuthorizationConsent.Builder authorizationConsentBuilder) {
|
||||
return new Builder(authentication, authorizationConsentBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for {@link OAuth2AuthorizationConsentAuthenticationContext}.
|
||||
*/
|
||||
public static final class Builder extends AbstractBuilder<OAuth2AuthorizationConsentAuthenticationContext, Builder> {
|
||||
|
||||
private Builder(Authentication authentication, OAuth2AuthorizationConsent.Builder authorizationConsentBuilder) {
|
||||
super(authentication);
|
||||
Assert.notNull(authorizationConsentBuilder, "authorizationConsentBuilder cannot be null");
|
||||
put(OAuth2AuthorizationConsent.Builder.class, authorizationConsentBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link RegisteredClient registered client}.
|
||||
*
|
||||
* @param registeredClient the {@link RegisteredClient}
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder registeredClient(RegisteredClient registeredClient) {
|
||||
return put(RegisteredClient.class, registeredClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OAuth2Authorization authorization}.
|
||||
*
|
||||
* @param authorization the {@link OAuth2Authorization}
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder authorization(OAuth2Authorization authorization) {
|
||||
return put(OAuth2Authorization.class, authorization);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OAuth2AuthorizationRequest authorization request}.
|
||||
*
|
||||
* @param authorizationRequest the {@link OAuth2AuthorizationRequest}
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder authorizationRequest(OAuth2AuthorizationRequest authorizationRequest) {
|
||||
return put(OAuth2AuthorizationRequest.class, authorizationRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new {@link OAuth2AuthorizationConsentAuthenticationContext}.
|
||||
*
|
||||
* @return the {@link OAuth2AuthorizationConsentAuthenticationContext}
|
||||
*/
|
||||
public OAuth2AuthorizationConsentAuthenticationContext build() {
|
||||
Assert.notNull(get(RegisteredClient.class), "registeredClient cannot be null");
|
||||
Assert.notNull(get(OAuth2Authorization.class), "authorization cannot be null");
|
||||
Assert.notNull(get(OAuth2AuthorizationRequest.class), "authorizationRequest cannot be null");
|
||||
return new OAuth2AuthorizationConsentAuthenticationContext(getContext());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.source.JWKSource;
|
||||
@@ -55,7 +56,6 @@ import org.springframework.mock.http.client.MockClientHttpResponse;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
|
||||
@@ -83,13 +83,13 @@ import org.springframework.security.oauth2.server.authorization.JdbcOAuth2Author
|
||||
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationConsentAuthenticationContext;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
@@ -131,6 +131,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
* @author Joe Grandja
|
||||
* @author Daniel Garnier-Moiroux
|
||||
* @author Dmitriy Dubson
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class OAuth2AuthorizationCodeGrantTests {
|
||||
private static final String DEFAULT_AUTHORIZATION_ENDPOINT_URI = "/oauth2/authorize";
|
||||
@@ -582,8 +583,6 @@ public class OAuth2AuthorizationCodeGrantTests {
|
||||
.andExpect(jsonPath("$.refresh_token").isNotEmpty())
|
||||
.andExpect(jsonPath("$.scope").doesNotExist())
|
||||
.andReturn();
|
||||
|
||||
String json = mvcResult.getResponse().getContentAsString();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -822,7 +821,7 @@ public class OAuth2AuthorizationCodeGrantTests {
|
||||
return context -> {
|
||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(context.getAuthorizationGrantType()) &&
|
||||
OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
|
||||
OAuth2AuthorizationConsent authorizationConsent = authorizationConsentService.findById(
|
||||
OAuth2AuthorizationConsent authorizationConsent = this.authorizationConsentService.findById(
|
||||
context.getRegisteredClient().getId(), context.getPrincipal().getName());
|
||||
|
||||
Set<String> authorities = new HashSet<>();
|
||||
@@ -840,21 +839,22 @@ public class OAuth2AuthorizationCodeGrantTests {
|
||||
this.registeredClientRepository,
|
||||
this.authorizationService,
|
||||
this.authorizationConsentService);
|
||||
authorizationCodeRequestAuthenticationProvider.setAuthorizationConsentCustomizer(new ConsentCustomizer());
|
||||
authorizationCodeRequestAuthenticationProvider.setAuthorizationConsentCustomizer(new AuthorizationConsentCustomizer());
|
||||
|
||||
return authorizationCodeRequestAuthenticationProvider;
|
||||
}
|
||||
|
||||
static class ConsentCustomizer implements Customizer<OAuth2AuthorizationConsentContext> {
|
||||
static class AuthorizationConsentCustomizer implements Consumer<OAuth2AuthorizationConsentAuthenticationContext> {
|
||||
|
||||
@Override
|
||||
public void customize(OAuth2AuthorizationConsentContext authorizationConsentContext) {
|
||||
public void accept(OAuth2AuthorizationConsentAuthenticationContext authorizationConsentAuthenticationContext) {
|
||||
OAuth2AuthorizationConsent.Builder authorizationConsentBuilder =
|
||||
authorizationConsentContext.getAuthorizationConsentBuilder();
|
||||
authorizationConsentAuthenticationContext.getAuthorizationConsent();
|
||||
OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication =
|
||||
authorizationConsentContext.getPrincipal();
|
||||
authorizationConsentAuthenticationContext.getAuthentication();
|
||||
Map<String, Object> additionalParameters =
|
||||
authorizationCodeRequestAuthentication.getAdditionalParameters();
|
||||
RegisteredClient registeredClient = authorizationConsentContext.getRegisteredClient();
|
||||
RegisteredClient registeredClient = authorizationConsentAuthenticationContext.getRegisteredClient();
|
||||
ClientSettings clientSettings = registeredClient.getClientSettings();
|
||||
|
||||
Set<String> requestedAuthorities = authorities((String) additionalParameters.get("authority"));
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2AuthorizationConsentContext}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class OAuth2AuthorizationConsentContextTests {
|
||||
|
||||
@Test
|
||||
public void withWhenAuthorizationConsentBuilderNullThenIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> OAuth2AuthorizationConsentContext.with(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("authorizationConsentBuilder cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWhenValueNullThenThrowIllegalArgumentException() {
|
||||
OAuth2AuthorizationConsentContext.Builder builder = OAuth2AuthorizationConsentContext
|
||||
.with(OAuth2AuthorizationConsent.withId("some-client", "some-principal"));
|
||||
assertThatThrownBy(() -> builder.principal(null))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> builder.registeredClient(null))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> builder.authorization(null))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> builder.authorizationRequest(null))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> builder.put(null, ""))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildWhenAllValuesProvidedThenAllValuesAreSet() {
|
||||
OAuth2AuthorizationConsent.Builder authorizationConsentBuilder = OAuth2AuthorizationConsent
|
||||
.withId("some-client", "some-principal");
|
||||
TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "password");
|
||||
OAuth2AuthorizationCodeRequestAuthenticationToken authentication =
|
||||
OAuth2AuthorizationCodeRequestAuthenticationToken.with("test-client", principal)
|
||||
.authorizationUri("https://provider.com/oauth2/authorize")
|
||||
.build();
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization().build();
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
|
||||
OAuth2AuthorizationConsentContext context = OAuth2AuthorizationConsentContext
|
||||
.with(authorizationConsentBuilder)
|
||||
.principal(authentication)
|
||||
.registeredClient(registeredClient)
|
||||
.authorization(authorization)
|
||||
.authorizationRequest(authorizationRequest)
|
||||
.put("custom-key-1", "custom-value-1")
|
||||
.context(ctx -> ctx.put("custom-key-2", "custom-value-2"))
|
||||
.build();
|
||||
|
||||
assertThat(context.getAuthorizationConsentBuilder()).isEqualTo(authorizationConsentBuilder);
|
||||
assertThat(context.<OAuth2AuthorizationCodeRequestAuthenticationToken>getPrincipal()).isEqualTo(authentication);
|
||||
assertThat(context.getRegisteredClient()).isEqualTo(registeredClient);
|
||||
assertThat(context.getAuthorization()).isEqualTo(authorization);
|
||||
assertThat(context.getAuthorizationRequest()).isEqualTo(authorizationRequest);
|
||||
assertThat(context.<String>get("custom-key-1")).isEqualTo("custom-value-1");
|
||||
assertThat(context.<String>get("custom-key-2")).isEqualTo("custom-value-2");
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -29,7 +30,6 @@ import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
|
||||
@@ -44,7 +44,6 @@ import org.springframework.security.oauth2.core.endpoint.PkceParameterNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
||||
@@ -68,6 +67,7 @@ import static org.mockito.Mockito.when;
|
||||
* Tests for {@link OAuth2AuthorizationCodeRequestAuthenticationProvider}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
|
||||
private static final OAuth2TokenType STATE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.STATE);
|
||||
@@ -804,7 +804,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
|
||||
.thenReturn(authorization);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Customizer<OAuth2AuthorizationConsentContext> authorizationConsentCustomizer = mock(Customizer.class);
|
||||
Consumer<OAuth2AuthorizationConsentAuthenticationContext> authorizationConsentCustomizer = mock(Consumer.class);
|
||||
this.authenticationProvider.setAuthorizationConsentCustomizer(authorizationConsentCustomizer);
|
||||
|
||||
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult =
|
||||
@@ -812,14 +812,16 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
|
||||
|
||||
assertAuthorizationConsentRequestWithAuthorizationCodeResult(registeredClient, authorization, authenticationResult);
|
||||
|
||||
ArgumentCaptor<OAuth2AuthorizationConsentContext> contextCaptor = ArgumentCaptor.forClass(OAuth2AuthorizationConsentContext.class);
|
||||
verify(authorizationConsentCustomizer).customize(contextCaptor.capture());
|
||||
ArgumentCaptor<OAuth2AuthorizationConsentAuthenticationContext> authenticationContextCaptor =
|
||||
ArgumentCaptor.forClass(OAuth2AuthorizationConsentAuthenticationContext.class);
|
||||
verify(authorizationConsentCustomizer).accept(authenticationContextCaptor.capture());
|
||||
|
||||
OAuth2AuthorizationConsentContext context = contextCaptor.getValue();
|
||||
assertThat((Authentication) context.getPrincipal()).isEqualTo(authentication);
|
||||
assertThat(context.get(OAuth2AuthorizationConsent.Builder.class)).isInstanceOf(OAuth2AuthorizationConsent.Builder.class);
|
||||
assertThat(context.get(OAuth2Authorization.class)).isInstanceOf(OAuth2Authorization.class);
|
||||
assertThat(context.get(OAuth2AuthorizationRequest.class)).isInstanceOf(OAuth2AuthorizationRequest.class);
|
||||
OAuth2AuthorizationConsentAuthenticationContext authenticationContext = authenticationContextCaptor.getValue();
|
||||
assertThat(authenticationContext.<Authentication>getAuthentication()).isEqualTo(authentication);
|
||||
assertThat(authenticationContext.getAuthorizationConsent()).isNotNull();
|
||||
assertThat(authenticationContext.getRegisteredClient()).isEqualTo(registeredClient);
|
||||
assertThat(authenticationContext.getAuthorization()).isEqualTo(authorization);
|
||||
assertThat(authenticationContext.getAuthorizationRequest()).isEqualTo(authorizationRequest);
|
||||
}
|
||||
|
||||
private void assertAuthorizationConsentRequestWithAuthorizationCodeResult(
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.authentication;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
|
||||
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2AuthorizationConsentAuthenticationContext}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class OAuth2AuthorizationConsentAuthenticationContextTests {
|
||||
private final RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
private final OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(this.registeredClient).build();
|
||||
private final Authentication principal = this.authorization.getAttribute(Principal.class.getName());
|
||||
private final OAuth2AuthorizationRequest authorizationRequest = this.authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
private final OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication =
|
||||
OAuth2AuthorizationCodeRequestAuthenticationToken.with(this.registeredClient.getClientId(), this.principal)
|
||||
.authorizationUri(this.authorizationRequest.getAuthorizationUri())
|
||||
.build();
|
||||
private final OAuth2AuthorizationConsent.Builder authorizationConsentBuilder =
|
||||
OAuth2AuthorizationConsent.withId(this.authorization.getRegisteredClientId(), this.authorization.getPrincipalName());
|
||||
|
||||
@Test
|
||||
public void withWhenAuthenticationNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> OAuth2AuthorizationConsentAuthenticationContext.with(null, this.authorizationConsentBuilder))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("authentication cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withWhenAuthorizationConsentBuilderNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> OAuth2AuthorizationConsentAuthenticationContext.with(this.authorizationCodeRequestAuthentication, null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("authorizationConsentBuilder cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWhenValueNullThenThrowIllegalArgumentException() {
|
||||
OAuth2AuthorizationConsentAuthenticationContext.Builder builder =
|
||||
OAuth2AuthorizationConsentAuthenticationContext.with(this.authorizationCodeRequestAuthentication, this.authorizationConsentBuilder);
|
||||
|
||||
assertThatThrownBy(() -> builder.registeredClient(null))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> builder.authorization(null))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> builder.authorizationRequest(null))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> builder.put(null, ""))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildWhenRequiredValueNullThenThrowIllegalArgumentException() {
|
||||
OAuth2AuthorizationConsentAuthenticationContext.Builder builder =
|
||||
OAuth2AuthorizationConsentAuthenticationContext.with(this.authorizationCodeRequestAuthentication, this.authorizationConsentBuilder);
|
||||
|
||||
assertThatThrownBy(builder::build)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("registeredClient cannot be null");
|
||||
builder.registeredClient(this.registeredClient);
|
||||
|
||||
assertThatThrownBy(builder::build)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("authorization cannot be null");
|
||||
builder.authorization(this.authorization);
|
||||
|
||||
assertThatThrownBy(builder::build)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("authorizationRequest cannot be null");
|
||||
builder.authorizationRequest(this.authorizationRequest);
|
||||
|
||||
builder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildWhenAllValuesProvidedThenAllValuesAreSet() {
|
||||
OAuth2AuthorizationConsentAuthenticationContext context =
|
||||
OAuth2AuthorizationConsentAuthenticationContext.with(this.authorizationCodeRequestAuthentication, this.authorizationConsentBuilder)
|
||||
.registeredClient(this.registeredClient)
|
||||
.authorization(this.authorization)
|
||||
.authorizationRequest(this.authorizationRequest)
|
||||
.put("custom-key-1", "custom-value-1")
|
||||
.context(ctx -> ctx.put("custom-key-2", "custom-value-2"))
|
||||
.build();
|
||||
|
||||
assertThat(context.<Authentication>getAuthentication()).isEqualTo(this.authorizationCodeRequestAuthentication);
|
||||
assertThat(context.getAuthorizationConsent()).isEqualTo(this.authorizationConsentBuilder);
|
||||
assertThat(context.getRegisteredClient()).isEqualTo(this.registeredClient);
|
||||
assertThat(context.getAuthorization()).isEqualTo(this.authorization);
|
||||
assertThat(context.getAuthorizationRequest()).isEqualTo(this.authorizationRequest);
|
||||
assertThat(context.<String>get("custom-key-1")).isEqualTo("custom-value-1");
|
||||
assertThat(context.<String>get("custom-key-2")).isEqualTo("custom-value-2");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user