1
0
mirror of synced 2026-08-02 08:17:03 +00:00

Add OAuth2AuthorizedClientService

Fixes gh-4726
This commit is contained in:
Joe Grandja
2017-10-28 06:42:32 -04:00
parent f0b0cfc4fd
commit 16e69d06b4
7 changed files with 176 additions and 2 deletions
@@ -0,0 +1,85 @@
/*
* 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;
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;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* An {@link OAuth2AuthorizedClientService} that stores
* {@link OAuth2AuthorizedClient Authorized Client(s)} <i>in-memory</i>.
*
* @author Joe Grandja
* @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<>();
private final ClientRegistrationRepository clientRegistrationRepository;
public InMemoryOAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository) {
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
this.clientRegistrationRepository = clientRegistrationRepository;
}
@Override
public T loadAuthorizedClient(String clientRegistrationId, Authentication principal) {
Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
Assert.notNull(principal, "principal cannot be null");
ClientRegistration registration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId);
if (registration == null) {
return null;
}
return this.authorizedClients.get(this.getIdentifier(registration, principal));
}
@Override
public void saveAuthorizedClient(T 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);
}
@Override
public T removeAuthorizedClient(String clientRegistrationId, Authentication principal) {
Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
Assert.notNull(principal, "principal cannot be null");
ClientRegistration registration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId);
if (registration == null) {
return null;
}
return this.authorizedClients.remove(this.getIdentifier(registration, principal));
}
private String getIdentifier(ClientRegistration registration, Authentication principal) {
String identifier = "[" + registration.getRegistrationId() + "][" + principal.getName() + "]";
return Base64.getEncoder().encodeToString(identifier.getBytes());
}
}
@@ -33,7 +33,6 @@ import org.springframework.util.Assert;
* @since 5.0
* @see ClientRegistration
* @see OAuth2AccessToken
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-5.1">Section 5.1 Access Token Response</a>
*/
public class OAuth2AuthorizedClient {
private final ClientRegistration clientRegistration;
@@ -0,0 +1,47 @@
/*
* 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;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.oidc.OidcAuthorizedClient;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
/**
* Implementations of this interface are responsible for the management
* of {@link OAuth2AuthorizedClient Authorized Client(s)}, which provide the purpose
* of associating an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} to a
* {@link OAuth2AuthorizedClient#getClientRegistration() Client} and <i>Resource Owner</i>,
* who is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal}
* that originally granted the authorization.
*
* @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>
*/
public interface OAuth2AuthorizedClientService<T extends OAuth2AuthorizedClient> {
T loadAuthorizedClient(String clientRegistrationId, Authentication principal);
void saveAuthorizedClient(T authorizedClient, Authentication principal);
T removeAuthorizedClient(String clientRegistrationId, Authentication principal);
}
@@ -36,7 +36,6 @@ import org.springframework.util.Assert;
* @since 5.0
* @see OAuth2AuthorizedClient
* @see OidcIdToken
* @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse">3.1.3.3 Successful Token Response</a>
*/
public class OidcAuthorizedClient extends OAuth2AuthorizedClient {
private final OidcIdToken idToken;
@@ -19,6 +19,7 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken;
import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider;
@@ -84,6 +85,7 @@ 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 AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository =
new HttpSessionOAuth2AuthorizationRequestRepository();
private OAuth2TokenRepository<OAuth2AccessToken> accessTokenRepository = new InMemoryAccessTokenRepository();
@@ -100,6 +102,7 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce
public void afterPropertiesSet() {
super.afterPropertiesSet();
Assert.notNull(this.clientRegistrationRepository, "clientRegistrationRepository cannot be null");
Assert.notNull(this.authorizedClientService, "authorizedClientService cannot be null");
}
@Override
@@ -140,6 +143,9 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce
OAuth2AuthenticationToken<OAuth2User, OAuth2AuthorizedClient> oauth2Authentication =
(OAuth2AuthenticationToken<OAuth2User, OAuth2AuthorizedClient>) this.getAuthenticationManager().authenticate(authorizationCodeAuthentication);
this.authorizedClientService.saveAuthorizedClient(
oauth2Authentication.getAuthorizedClient(), oauth2Authentication);
this.accessTokenRepository.saveToken(
oauth2Authentication.getAuthorizedClient().getAccessToken(),
oauth2Authentication.getAuthorizedClient().getClientRegistration(),
@@ -153,6 +159,11 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce
this.clientRegistrationRepository = clientRegistrationRepository;
}
public final void setAuthorizedClientService(OAuth2AuthorizedClientService<OAuth2AuthorizedClient> authorizedClientService) {
Assert.notNull(authorizedClientService, "authorizedClientService cannot be null");
this.authorizedClientService = authorizedClientService;
}
public final void setAuthorizationRequestRepository(AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository) {
Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null");
this.authorizationRequestRepository = authorizationRequestRepository;
@@ -28,6 +28,7 @@ import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
@@ -184,6 +185,7 @@ public class OAuth2LoginAuthenticationFilterTests {
OAuth2LoginAuthenticationFilter filter = new OAuth2LoginAuthenticationFilter();
filter.setClientRegistrationRepository(clientRegistrationRepository);
filter.setAuthenticationManager(authenticationManager);
filter.setAuthorizedClientService(mock(OAuth2AuthorizedClientService.class));
return filter;
}