parent
b496ad4d86
commit
c3d2effc1d
|
@ -20,12 +20,11 @@ import org.springframework.core.ResolvableType;
|
|||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.AuthorizationRequestUriBuilder;
|
||||
import org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
|
||||
import org.springframework.security.oauth2.client.jwt.JwtDecoderRegistry;
|
||||
import org.springframework.security.oauth2.client.jwt.NimbusJwtDecoderRegistry;
|
||||
|
@ -79,7 +78,7 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
|
|||
return this;
|
||||
}
|
||||
|
||||
public OAuth2LoginConfigurer<B> authorizedClientService(OAuth2AuthorizedClientService<OAuth2AuthorizedClient> authorizedClientService) {
|
||||
public OAuth2LoginConfigurer<B> authorizedClientService(OAuth2AuthorizedClientService authorizedClientService) {
|
||||
Assert.notNull(authorizedClientService, "authorizedClientService cannot be null");
|
||||
this.getBuilder().setSharedObject(OAuth2AuthorizedClientService.class, authorizedClientService);
|
||||
return this;
|
||||
|
@ -318,8 +317,8 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
|
|||
return this.getBuilder().getSharedObject(ApplicationContext.class).getBean(ClientRegistrationRepository.class);
|
||||
}
|
||||
|
||||
private OAuth2AuthorizedClientService<OAuth2AuthorizedClient> getAuthorizedClientService() {
|
||||
OAuth2AuthorizedClientService<OAuth2AuthorizedClient> authorizedClientService =
|
||||
private OAuth2AuthorizedClientService getAuthorizedClientService() {
|
||||
OAuth2AuthorizedClientService authorizedClientService =
|
||||
this.getBuilder().getSharedObject(OAuth2AuthorizedClientService.class);
|
||||
if (authorizedClientService == null) {
|
||||
authorizedClientService = this.getAuthorizedClientServiceBean();
|
||||
|
@ -328,7 +327,7 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
|
|||
return authorizedClientService;
|
||||
}
|
||||
|
||||
private OAuth2AuthorizedClientService<OAuth2AuthorizedClient> getAuthorizedClientServiceBean() {
|
||||
private OAuth2AuthorizedClientService getAuthorizedClientServiceBean() {
|
||||
return this.getBuilder().getSharedObject(ApplicationContext.class).getBean(OAuth2AuthorizedClientService.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package org.springframework.security.oauth2.client;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.client.oidc.OidcAuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -33,14 +32,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
* @since 5.0
|
||||
* @see OAuth2AuthorizedClientService
|
||||
* @see OAuth2AuthorizedClient
|
||||
* @see OidcAuthorizedClient
|
||||
* @see ClientRegistration
|
||||
* @see Authentication
|
||||
*
|
||||
* @param <T> The type of <i>OAuth 2.0 Authorized Client</i>
|
||||
*/
|
||||
public final class InMemoryOAuth2AuthorizedClientService<T extends OAuth2AuthorizedClient> implements OAuth2AuthorizedClientService<T> {
|
||||
private final Map<String, T> authorizedClients = new ConcurrentHashMap<>();
|
||||
public final class InMemoryOAuth2AuthorizedClientService implements OAuth2AuthorizedClientService {
|
||||
private final Map<String, OAuth2AuthorizedClient> authorizedClients = new ConcurrentHashMap<>();
|
||||
private final ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
public InMemoryOAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository) {
|
||||
|
@ -49,37 +45,36 @@ public final class InMemoryOAuth2AuthorizedClientService<T extends OAuth2Authori
|
|||
}
|
||||
|
||||
@Override
|
||||
public T loadAuthorizedClient(String clientRegistrationId, Authentication principal) {
|
||||
public <T extends OAuth2AuthorizedClient> T loadAuthorizedClient(String clientRegistrationId, String principalName) {
|
||||
Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
|
||||
Assert.notNull(principal, "principal cannot be null");
|
||||
Assert.hasText(principalName, "principalName cannot be empty");
|
||||
ClientRegistration registration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId);
|
||||
if (registration == null) {
|
||||
return null;
|
||||
}
|
||||
return this.authorizedClients.get(this.getIdentifier(registration, principal));
|
||||
return (T) this.authorizedClients.get(this.getIdentifier(registration, principalName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAuthorizedClient(T authorizedClient, Authentication principal) {
|
||||
public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal) {
|
||||
Assert.notNull(authorizedClient, "authorizedClient cannot be null");
|
||||
Assert.notNull(principal, "principal cannot be null");
|
||||
this.authorizedClients.put(this.getIdentifier(
|
||||
authorizedClient.getClientRegistration(), principal), authorizedClient);
|
||||
authorizedClient.getClientRegistration(), principal.getName()), authorizedClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T removeAuthorizedClient(String clientRegistrationId, Authentication principal) {
|
||||
public void removeAuthorizedClient(String clientRegistrationId, String principalName) {
|
||||
Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
|
||||
Assert.notNull(principal, "principal cannot be null");
|
||||
Assert.hasText(principalName, "principalName cannot be empty");
|
||||
ClientRegistration registration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId);
|
||||
if (registration == null) {
|
||||
return null;
|
||||
if (registration != null) {
|
||||
this.authorizedClients.remove(this.getIdentifier(registration, principalName));
|
||||
}
|
||||
return this.authorizedClients.remove(this.getIdentifier(registration, principal));
|
||||
}
|
||||
|
||||
private String getIdentifier(ClientRegistration registration, Authentication principal) {
|
||||
String identifier = "[" + registration.getRegistrationId() + "][" + principal.getName() + "]";
|
||||
private String getIdentifier(ClientRegistration registration, String principalName) {
|
||||
String identifier = "[" + registration.getRegistrationId() + "][" + principalName + "]";
|
||||
return Base64.getEncoder().encodeToString(identifier.getBytes());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
package org.springframework.security.oauth2.client;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.client.oidc.OidcAuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
|
||||
/**
|
||||
* Implementations of this interface are responsible for the management
|
||||
|
@ -30,18 +30,16 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
|
|||
* @author Joe Grandja
|
||||
* @since 5.0
|
||||
* @see OAuth2AuthorizedClient
|
||||
* @see OidcAuthorizedClient
|
||||
* @see ClientRegistration
|
||||
* @see Authentication
|
||||
*
|
||||
* @param <T> The type of <i>OAuth 2.0 Authorized Client</i>
|
||||
* @see OAuth2AccessToken
|
||||
*/
|
||||
public interface OAuth2AuthorizedClientService<T extends OAuth2AuthorizedClient> {
|
||||
public interface OAuth2AuthorizedClientService {
|
||||
|
||||
T loadAuthorizedClient(String clientRegistrationId, Authentication principal);
|
||||
<T extends OAuth2AuthorizedClient> T loadAuthorizedClient(String clientRegistrationId, String principalName);
|
||||
|
||||
void saveAuthorizedClient(T authorizedClient, Authentication principal);
|
||||
void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal);
|
||||
|
||||
T removeAuthorizedClient(String clientRegistrationId, Authentication principal);
|
||||
void removeAuthorizedClient(String clientRegistrationId, String principalName);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* http://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.client.oidc;
|
||||
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A representation of an OpenID Connect 1.0 <i>"Authorized Client"</i>.
|
||||
* <p>
|
||||
* A client is considered <i>"authorized"</i> when the End-User (Resource Owner)
|
||||
* grants authorization to the Client to access its protected resources.
|
||||
* <p>
|
||||
* This class associates the {@link #getClientRegistration() Client}
|
||||
* to the {@link #getAccessToken() Access Token}
|
||||
* granted/authorized by the {@link #getPrincipalName() Resource Owner}, along with
|
||||
* the {@link #getIdToken() ID Token} which contains Claims about the authentication of the End-User.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.0
|
||||
* @see OAuth2AuthorizedClient
|
||||
* @see OidcIdToken
|
||||
*/
|
||||
public class OidcAuthorizedClient extends OAuth2AuthorizedClient {
|
||||
private final OidcIdToken idToken;
|
||||
|
||||
public OidcAuthorizedClient(ClientRegistration clientRegistration, String principalName,
|
||||
OAuth2AccessToken accessToken, OidcIdToken idToken) {
|
||||
|
||||
super(clientRegistration, principalName, accessToken);
|
||||
Assert.notNull(idToken, "idToken cannot be null");
|
||||
this.idToken = idToken;
|
||||
}
|
||||
|
||||
public OidcIdToken getIdToken() {
|
||||
return this.idToken;
|
||||
}
|
||||
}
|
|
@ -62,7 +62,7 @@ import java.util.List;
|
|||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.0
|
||||
* @see OidcAuthorizationCodeAuthenticationToken
|
||||
* @see OAuth2LoginAuthenticationToken
|
||||
* @see OAuth2AccessTokenResponseClient
|
||||
* @see OidcUserService
|
||||
* @see OidcUser
|
||||
|
@ -158,13 +158,12 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
|
|||
Collection<? extends GrantedAuthority> mappedAuthorities =
|
||||
this.authoritiesMapper.mapAuthorities(oidcUser.getAuthorities());
|
||||
|
||||
OidcAuthorizationCodeAuthenticationToken authenticationResult = new OidcAuthorizationCodeAuthenticationToken(
|
||||
OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken(
|
||||
authorizationCodeAuthentication.getClientRegistration(),
|
||||
authorizationCodeAuthentication.getAuthorizationExchange(),
|
||||
oidcUser,
|
||||
mappedAuthorities,
|
||||
accessToken,
|
||||
idToken);
|
||||
accessToken);
|
||||
authenticationResult.setDetails(authorizationCodeAuthentication.getDetails());
|
||||
|
||||
return authenticationResult;
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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
|
||||
*
|
||||
* http://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.client.oidc.authentication;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* An {@link OAuth2LoginAuthenticationToken} for <i>OpenID Connect 1.0 Authentication</i>,
|
||||
* which leverages the <i>Authorization Code Flow</i>.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.0
|
||||
* @see OAuth2LoginAuthenticationToken
|
||||
* @see OidcIdToken
|
||||
* @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth">3.1 Authorization Code Flow</a>
|
||||
*/
|
||||
public class OidcAuthorizationCodeAuthenticationToken extends OAuth2LoginAuthenticationToken {
|
||||
private OidcIdToken idToken;
|
||||
|
||||
/**
|
||||
* This constructor should be used when the Authentication Request/Response is complete.
|
||||
*
|
||||
* @param clientRegistration
|
||||
* @param authorizationExchange
|
||||
*/
|
||||
public OidcAuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration,
|
||||
OAuth2AuthorizationExchange authorizationExchange) {
|
||||
|
||||
super(clientRegistration, authorizationExchange);
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor should be used when the Token Request/Response is complete,
|
||||
* which indicates that the Authorization Code Flow has fully completed
|
||||
* and OpenID Connect 1.0 Authentication has been achieved.
|
||||
*
|
||||
* @param clientRegistration
|
||||
* @param authorizationExchange
|
||||
* @param principal
|
||||
* @param authorities
|
||||
* @param accessToken
|
||||
* @param idToken
|
||||
*/
|
||||
public OidcAuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration,
|
||||
OAuth2AuthorizationExchange authorizationExchange,
|
||||
OidcUser principal,
|
||||
Collection<? extends GrantedAuthority> authorities,
|
||||
OAuth2AccessToken accessToken,
|
||||
OidcIdToken idToken) {
|
||||
|
||||
super(clientRegistration, authorizationExchange, principal, authorities, accessToken);
|
||||
Assert.notNull(idToken, "idToken cannot be null");
|
||||
this.idToken = idToken;
|
||||
}
|
||||
|
||||
public OidcIdToken getIdToken() {
|
||||
return this.idToken;
|
||||
}
|
||||
}
|
|
@ -81,18 +81,18 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce
|
|||
public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/oauth2/code/*";
|
||||
private static final String AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE = "authorization_request_not_found";
|
||||
private ClientRegistrationRepository clientRegistrationRepository;
|
||||
private OAuth2AuthorizedClientService<OAuth2AuthorizedClient> authorizedClientService;
|
||||
private OAuth2AuthorizedClientService authorizedClientService;
|
||||
private AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository =
|
||||
new HttpSessionOAuth2AuthorizationRequestRepository();
|
||||
|
||||
public OAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository,
|
||||
OAuth2AuthorizedClientService<OAuth2AuthorizedClient> authorizedClientService) {
|
||||
OAuth2AuthorizedClientService authorizedClientService) {
|
||||
this(DEFAULT_FILTER_PROCESSES_URI, clientRegistrationRepository, authorizedClientService);
|
||||
}
|
||||
|
||||
public OAuth2LoginAuthenticationFilter(String filterProcessesUrl,
|
||||
ClientRegistrationRepository clientRegistrationRepository,
|
||||
OAuth2AuthorizedClientService<OAuth2AuthorizedClient> authorizedClientService) {
|
||||
OAuth2AuthorizedClientService authorizedClientService) {
|
||||
super(filterProcessesUrl);
|
||||
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
|
||||
Assert.notNull(authorizedClientService, "authorizedClientService cannot be null");
|
||||
|
@ -137,8 +137,7 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce
|
|||
oauth2Authentication.getName(),
|
||||
authenticationResult.getAccessToken());
|
||||
|
||||
this.authorizedClientService.saveAuthorizedClient(
|
||||
authorizedClient, oauth2Authentication);
|
||||
this.authorizedClientService.saveAuthorizedClient(authorizedClient, oauth2Authentication);
|
||||
|
||||
return oauth2Authentication;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
|
||||
|
@ -397,8 +396,8 @@ public class OAuth2LoginApplicationTests {
|
|||
private ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
@Bean
|
||||
public OAuth2AuthorizedClientService<OAuth2AuthorizedClient> authorizedClientService() {
|
||||
return new InMemoryOAuth2AuthorizedClientService<>(this.clientRegistrationRepository);
|
||||
public OAuth2AuthorizedClientService authorizedClientService() {
|
||||
return new InMemoryOAuth2AuthorizedClientService(this.clientRegistrationRepository);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
|
||||
|
@ -33,7 +32,7 @@ public class OAuth2LoginConfig {
|
|||
private ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
@Bean
|
||||
public OAuth2AuthorizedClientService<OAuth2AuthorizedClient> authorizedClientService() {
|
||||
return new InMemoryOAuth2AuthorizedClientService<>(this.clientRegistrationRepository);
|
||||
public OAuth2AuthorizedClientService authorizedClientService() {
|
||||
return new InMemoryOAuth2AuthorizedClientService(this.clientRegistrationRepository);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ public class MainController {
|
|||
|
||||
private OAuth2AuthorizedClient getAuthorizedClient(OAuth2AuthenticationToken authentication) {
|
||||
return this.authorizedClientService.loadAuthorizedClient(
|
||||
authentication.getAuthorizedClientRegistrationId(), authentication);
|
||||
authentication.getAuthorizedClientRegistrationId(), authentication.getName());
|
||||
}
|
||||
|
||||
private ExchangeFilterFunction oauth2Credentials(OAuth2AuthorizedClient authorizedClient) {
|
||||
|
|
Loading…
Reference in New Issue