feat: Add InMemoryOAuth2AuthorizationService for development or testing (#1854)

pull/1856/head
guqing 2022-04-19 16:06:09 +08:00 committed by GitHub
parent eee58989fe
commit ad562b4917
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 480 additions and 35 deletions

View File

@ -30,10 +30,10 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter; import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import run.halo.app.identity.authentication.InMemoryOAuth2AuthorizationService;
import run.halo.app.identity.authentication.JwtDaoAuthenticationProvider; import run.halo.app.identity.authentication.JwtDaoAuthenticationProvider;
import run.halo.app.identity.authentication.JwtGenerator; import run.halo.app.identity.authentication.JwtGenerator;
import run.halo.app.identity.authentication.JwtUsernamePasswordAuthenticationFilter; import run.halo.app.identity.authentication.JwtUsernamePasswordAuthenticationFilter;
import run.halo.app.identity.authentication.OAuth2AuthorizationService;
import run.halo.app.identity.authentication.ProviderContextFilter; import run.halo.app.identity.authentication.ProviderContextFilter;
import run.halo.app.identity.authentication.ProviderSettings; import run.halo.app.identity.authentication.ProviderSettings;
import run.halo.app.identity.entrypoint.JwtAccessDeniedHandler; import run.halo.app.identity.entrypoint.JwtAccessDeniedHandler;
@ -110,7 +110,8 @@ public class WebSecurityConfig {
@Bean @Bean
JwtDaoAuthenticationProvider jwtDaoAuthenticationProvider() { JwtDaoAuthenticationProvider jwtDaoAuthenticationProvider() {
JwtDaoAuthenticationProvider authenticationProvider = JwtDaoAuthenticationProvider authenticationProvider =
new JwtDaoAuthenticationProvider(jwtGenerator(), new OAuth2AuthorizationService()); new JwtDaoAuthenticationProvider(jwtGenerator(),
new InMemoryOAuth2AuthorizationService());
authenticationProvider.setUserDetailsService(userDetailsService()); authenticationProvider.setUserDetailsService(userDetailsService());
authenticationProvider.setPasswordEncoder(passwordEncoder()); authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider; return authenticationProvider;

View File

@ -0,0 +1,169 @@
package run.halo.app.identity.authentication;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.lang.Nullable;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.util.Assert;
/**
* An {@link OAuth2AuthorizationService} that stores {@link OAuth2Authorization}'s in-memory.<p>
* <b>NOTE:</b> This implementation should ONLY be used during development/testing.
*
* @author guqing
* @see OAuth2AuthorizationService
* @since 2.0.0
*/
public class InMemoryOAuth2AuthorizationService implements OAuth2AuthorizationService {
private int maxInitializedAuthorizations = 100;
/*
* Stores "initialized" (uncompleted) authorizations, where an access token has not yet been
* granted.
* This state occurs with the authorization_code grant flow during the user consent step OR
* when the code is returned in the authorization response but the access token request is
* not yet initiated.
*/
private Map<String, OAuth2Authorization> initializedAuthorizations =
Collections.synchronizedMap(new MaxSizeHashMap<>(this.maxInitializedAuthorizations));
/*
* Stores "completed" authorizations, where an access token has been granted.
*/
private final Map<String, OAuth2Authorization> authorizations = new ConcurrentHashMap<>();
/*
* Constructor used for testing only.
*/
public InMemoryOAuth2AuthorizationService(int maxInitializedAuthorizations) {
this.maxInitializedAuthorizations = maxInitializedAuthorizations;
this.initializedAuthorizations =
Collections.synchronizedMap(new MaxSizeHashMap<>(this.maxInitializedAuthorizations));
}
/**
* Constructs an {@code InMemoryOAuth2AuthorizationService}.
*/
public InMemoryOAuth2AuthorizationService() {
this(Collections.emptyList());
}
/**
* Constructs an {@code InMemoryOAuth2AuthorizationService} using the provided parameters.
*
* @param authorizations the authorization(s)
*/
public InMemoryOAuth2AuthorizationService(OAuth2Authorization... authorizations) {
this(Arrays.asList(authorizations));
}
/**
* Constructs an {@code InMemoryOAuth2AuthorizationService} using the provided parameters.
*
* @param authorizations the authorization(s)
*/
public InMemoryOAuth2AuthorizationService(List<OAuth2Authorization> authorizations) {
Assert.notNull(authorizations, "authorizations cannot be null");
authorizations.forEach(authorization -> {
Assert.notNull(authorization, "authorization cannot be null");
Assert.isTrue(!this.authorizations.containsKey(authorization.getId()),
"The authorization must be unique. Found duplicate identifier: "
+ authorization.getId());
this.authorizations.put(authorization.getId(), authorization);
});
}
@Override
public void save(OAuth2Authorization authorization) {
Assert.notNull(authorization, "authorization cannot be null");
if (isComplete(authorization)) {
this.authorizations.put(authorization.getId(), authorization);
} else {
this.initializedAuthorizations.put(authorization.getId(), authorization);
}
}
@Override
public void remove(OAuth2Authorization authorization) {
Assert.notNull(authorization, "authorization cannot be null");
if (isComplete(authorization)) {
this.authorizations.remove(authorization.getId(), authorization);
} else {
this.initializedAuthorizations.remove(authorization.getId(), authorization);
}
}
@Nullable
@Override
public OAuth2Authorization findById(String id) {
Assert.hasText(id, "id cannot be empty");
OAuth2Authorization authorization = this.authorizations.get(id);
return authorization != null
? authorization :
this.initializedAuthorizations.get(id);
}
@Nullable
@Override
public OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType) {
Assert.hasText(token, "token cannot be empty");
for (OAuth2Authorization authorization : this.authorizations.values()) {
if (hasToken(authorization, token, tokenType)) {
return authorization;
}
}
for (OAuth2Authorization authorization : this.initializedAuthorizations.values()) {
if (hasToken(authorization, token, tokenType)) {
return authorization;
}
}
return null;
}
private static boolean isComplete(OAuth2Authorization authorization) {
return authorization.getAccessToken() != null;
}
private static boolean hasToken(OAuth2Authorization authorization, String token,
@Nullable OAuth2TokenType tokenType) {
if (tokenType == null) {
return matchesAccessToken(authorization, token)
|| matchesRefreshToken(authorization, token);
} else if (OAuth2TokenType.ACCESS_TOKEN.equals(tokenType)) {
return matchesAccessToken(authorization, token);
} else if (OAuth2TokenType.REFRESH_TOKEN.equals(tokenType)) {
return matchesRefreshToken(authorization, token);
}
return false;
}
private static boolean matchesAccessToken(OAuth2Authorization authorization, String token) {
OAuth2Authorization.Token<OAuth2AccessToken> accessToken =
authorization.getToken(OAuth2AccessToken.class);
return accessToken != null && accessToken.getToken().getTokenValue().equals(token);
}
private static boolean matchesRefreshToken(OAuth2Authorization authorization, String token) {
OAuth2Authorization.Token<OAuth2RefreshToken> refreshToken =
authorization.getToken(OAuth2RefreshToken.class);
return refreshToken != null && refreshToken.getToken().getTokenValue().equals(token);
}
private static final class MaxSizeHashMap<K, V> extends LinkedHashMap<K, V> {
private final int maxSize;
private MaxSizeHashMap(int maxSize) {
this.maxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > this.maxSize;
}
}
}

View File

@ -8,6 +8,7 @@ import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClaimAccessor; import org.springframework.security.oauth2.core.ClaimAccessor;
import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
@ -21,7 +22,6 @@ import org.springframework.security.oauth2.core.OAuth2Token;
* @since 2.0.0 * @since 2.0.0
*/ */
public class JwtDaoAuthenticationProvider extends DaoAuthenticationProvider { public class JwtDaoAuthenticationProvider extends DaoAuthenticationProvider {
private static final OAuth2TokenType PASSWORD_TOKEN = new OAuth2TokenType("password");
private static final String ERROR_URI = private static final String ERROR_URI =
"https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"; "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator; private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
@ -41,18 +41,6 @@ public class JwtDaoAuthenticationProvider extends DaoAuthenticationProvider {
(UsernamePasswordAuthenticationToken) super.createSuccessAuthentication(principal, (UsernamePasswordAuthenticationToken) super.createSuccessAuthentication(principal,
authentication, user); authentication, user);
OAuth2Authorization authorization = this.authorizationService.findByUsername(
usernamePasswordAuthenticationToken.getName(), PASSWORD_TOKEN);
OAuth2Authorization.Token<OAuth2RefreshToken> refreshToken =
authorization.getRefreshToken();
if (refreshToken == null || !refreshToken.isActive()) {
// As per https://tools.ietf.org/html/rfc6749#section-5.2
// invalid_grant: The provided authorization grant (e.g., authorization code,
// resource owner credentials) or refresh token is invalid, expired, revoked [...].
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT);
}
Set<String> scopes = usernamePasswordAuthenticationToken.getAuthorities().stream() Set<String> scopes = usernamePasswordAuthenticationToken.getAuthorities().stream()
.map(GrantedAuthority::getAuthority).collect(Collectors.toSet()); .map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
@ -61,7 +49,10 @@ public class JwtDaoAuthenticationProvider extends DaoAuthenticationProvider {
.providerContext(ProviderContextHolder.getProviderContext()) .providerContext(ProviderContextHolder.getProviderContext())
.authorizedScopes(scopes); .authorizedScopes(scopes);
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.from(authorization); OAuth2Authorization.Builder authorizationBuilder = new OAuth2Authorization.Builder()
.principalName(authentication.getName())
.authorizationGrantType(AuthorizationGrantType.PASSWORD)
.attribute(OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME, scopes);
// ----- Access token ----- // ----- Access token -----
OAuth2TokenContext tokenContext = OAuth2TokenContext tokenContext =
@ -89,7 +80,7 @@ public class JwtDaoAuthenticationProvider extends DaoAuthenticationProvider {
ProviderContextHolder.getProviderContext().providerSettings(); ProviderContextHolder.getProviderContext().providerSettings();
// ----- Refresh token ----- // ----- Refresh token -----
OAuth2RefreshToken currentRefreshToken = refreshToken.getToken(); OAuth2RefreshToken currentRefreshToken = null;
if (!providerSettings.isReuseRefreshTokens()) { if (!providerSettings.isReuseRefreshTokens()) {
tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.REFRESH_TOKEN).build(); tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.REFRESH_TOKEN).build();
OAuth2Token generatedRefreshToken = this.tokenGenerator.generate(tokenContext); OAuth2Token generatedRefreshToken = this.tokenGenerator.generate(tokenContext);

View File

@ -9,6 +9,7 @@ import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken; import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.security.oauth2.core.OAuth2Token; import org.springframework.security.oauth2.core.OAuth2Token;
@ -31,6 +32,7 @@ public class OAuth2Authorization implements Serializable {
private String id; private String id;
private String principalName; private String principalName;
private AuthorizationGrantType authorizationGrantType;
private Map<Class<? extends OAuth2Token>, Token<?>> tokens; private Map<Class<? extends OAuth2Token>, Token<?>> tokens;
private Map<String, Object> attributes; private Map<String, Object> attributes;
@ -55,6 +57,16 @@ public class OAuth2Authorization implements Serializable {
return this.principalName; return this.principalName;
} }
/**
* Returns the {@link AuthorizationGrantType authorization grant type} used for the
* authorization.
*
* @return the {@link AuthorizationGrantType} used for the authorization
*/
public AuthorizationGrantType getAuthorizationGrantType() {
return this.authorizationGrantType;
}
/** /**
* Returns the {@link Token} of type {@link OAuth2AccessToken}. * Returns the {@link Token} of type {@link OAuth2AccessToken}.
* *
@ -319,6 +331,7 @@ public class OAuth2Authorization implements Serializable {
public static class Builder implements Serializable { public static class Builder implements Serializable {
private String id; private String id;
private String principalName; private String principalName;
private AuthorizationGrantType authorizationGrantType;
private Map<Class<? extends OAuth2Token>, Token<?>> tokens = new HashMap<>(); private Map<Class<? extends OAuth2Token>, Token<?>> tokens = new HashMap<>();
private final Map<String, Object> attributes = new HashMap<>(); private final Map<String, Object> attributes = new HashMap<>();
@ -344,6 +357,18 @@ public class OAuth2Authorization implements Serializable {
return this; return this;
} }
/**
* Sets the {@link AuthorizationGrantType authorization grant type} used for the
* authorization.
*
* @param authorizationGrantType the {@link AuthorizationGrantType}
* @return the {@link Builder}
*/
public Builder authorizationGrantType(AuthorizationGrantType authorizationGrantType) {
this.authorizationGrantType = authorizationGrantType;
return this;
}
/** /**
* Sets the {@link OAuth2AccessToken access token}. * Sets the {@link OAuth2AccessToken access token}.
* *
@ -444,6 +469,7 @@ public class OAuth2Authorization implements Serializable {
} }
authorization.id = this.id; authorization.id = this.id;
authorization.principalName = this.principalName; authorization.principalName = this.principalName;
authorization.authorizationGrantType = this.authorizationGrantType;
authorization.tokens = Collections.unmodifiableMap(this.tokens); authorization.tokens = Collections.unmodifiableMap(this.tokens);
authorization.attributes = Collections.unmodifiableMap(this.attributes); authorization.attributes = Collections.unmodifiableMap(this.attributes);
return authorization; return authorization;

View File

@ -1,27 +1,45 @@
package run.halo.app.identity.authentication; package run.halo.app.identity.authentication;
import java.time.Instant; import org.springframework.lang.Nullable;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
/** /**
* @author guqing * @author guqing
* @since 2.0.0 * @since 2.0.0
*/ */
public class OAuth2AuthorizationService { public interface OAuth2AuthorizationService {
OAuth2Authorization findByUsername(String username, OAuth2TokenType oauth2TokenType) { /**
// TODO to be implementation * Returns the {@link OAuth2Authorization} containing the provided {@code token},
return new OAuth2Authorization.Builder().id("id") * or {@code null} if not found.
.accessToken(new OAuth2AccessToken( *
OAuth2AccessToken.TokenType.BEARER, "token", Instant.now(), * @param token the token credential
Instant.now().plusMillis(123))) * @param tokenType the {@link OAuth2TokenType token type}
.refreshToken( * @return the {@link OAuth2Authorization} if found, otherwise {@code null}
new OAuth2RefreshToken("refresh_token", Instant.now())) */
.principalName("guqing") @Nullable
.build(); OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType);
}
/**
* Saves the {@link OAuth2Authorization}.
*
* @param authorization the {@link OAuth2Authorization}
*/
void save(OAuth2Authorization authorization);
/**
* Removes the {@link OAuth2Authorization}.
*
* @param authorization the {@link OAuth2Authorization}
*/
void remove(OAuth2Authorization authorization);
/**
* Returns the {@link OAuth2Authorization} identified by the provided {@code id},
* or {@code null} if not found.
*
* @param id the authorization identifier
* @return the {@link OAuth2Authorization} if found, otherwise {@code null}
*/
@Nullable
OAuth2Authorization findById(String id);
void save(OAuth2Authorization authorization) {
// TODO to be implementation
}
} }

View File

@ -0,0 +1,240 @@
package run.halo.app.authentication;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.time.Instant;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import run.halo.app.identity.authentication.InMemoryOAuth2AuthorizationService;
import run.halo.app.identity.authentication.OAuth2Authorization;
import run.halo.app.identity.authentication.OAuth2AuthorizationService;
import run.halo.app.identity.authentication.OAuth2TokenType;
/**
* An {@link OAuth2AuthorizationService} that stores {@link OAuth2Authorization}'s in-memory.<p>
* <b>NOTE:</b> This implementation should ONLY be used during development/testing.
*
* @author guqing
* @see OAuth2AuthorizationService
* @since 2.0.0
*/
public class InMemoryOAuth2AuthorizationServiceTest {
private static final String ID = "id";
private static final String PRINCIPAL_NAME = "principal";
private static final AuthorizationGrantType AUTHORIZATION_GRANT_TYPE =
AuthorizationGrantType.PASSWORD;
private static final OAuth2AccessToken TOKEN =
new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access_token",
Instant.now(), Instant.now().plusSeconds(256));
private InMemoryOAuth2AuthorizationService authorizationService;
@BeforeEach
public void setup() {
this.authorizationService = new InMemoryOAuth2AuthorizationService();
}
@Test
public void constructorVarargsWhenAuthorizationNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new InMemoryOAuth2AuthorizationService((OAuth2Authorization) null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorization cannot be null");
}
@Test
public void constructorListWhenAuthorizationsNullThenThrowIllegalArgumentException() {
assertThatThrownBy(
() -> new InMemoryOAuth2AuthorizationService((List<OAuth2Authorization>) null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorizations cannot be null");
}
@Test
public void constructorWhenDuplicateAuthorizationsThenThrowIllegalArgumentException() {
OAuth2Authorization authorization = new OAuth2Authorization.Builder()
.id(ID)
.principalName(PRINCIPAL_NAME)
.authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
.token(TOKEN)
.build();
assertThatThrownBy(
() -> new InMemoryOAuth2AuthorizationService(authorization, authorization))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("The authorization must be unique. Found duplicate identifier: id");
}
@Test
public void saveWhenAuthorizationNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.authorizationService.save(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorization cannot be null");
}
@Test
public void saveWhenAuthorizationNewThenSaved() {
OAuth2Authorization expectedAuthorization = new OAuth2Authorization.Builder()
.id(ID)
.principalName(PRINCIPAL_NAME)
.authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
.token(TOKEN)
.build();
this.authorizationService.save(expectedAuthorization);
OAuth2Authorization authorization = this.authorizationService.findByToken(
TOKEN.getTokenValue(), OAuth2TokenType.ACCESS_TOKEN);
assertThat(authorization).isEqualTo(expectedAuthorization);
}
@Test
public void saveWhenAuthorizationExistsThenUpdated() {
OAuth2Authorization originalAuthorization = new OAuth2Authorization.Builder()
.id(ID)
.principalName(PRINCIPAL_NAME)
.authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
.token(TOKEN)
.build();
this.authorizationService.save(originalAuthorization);
OAuth2Authorization authorization = this.authorizationService.findById(
originalAuthorization.getId());
assertThat(authorization).isEqualTo(originalAuthorization);
OAuth2Authorization updatedAuthorization = OAuth2Authorization.from(authorization)
.attribute("custom-name-1", "custom-value-1")
.build();
this.authorizationService.save(updatedAuthorization);
authorization = this.authorizationService.findById(
updatedAuthorization.getId());
assertThat(authorization).isEqualTo(updatedAuthorization);
assertThat(authorization).isNotEqualTo(originalAuthorization);
}
@Test
public void saveWhenInitializedAuthorizationsReachMaxThenOldestRemoved() {
int maxInitializedAuthorizations = 5;
InMemoryOAuth2AuthorizationService authorizationService =
new InMemoryOAuth2AuthorizationService(maxInitializedAuthorizations);
OAuth2Authorization initialAuthorization = new OAuth2Authorization.Builder()
.id(ID + "-initial")
.principalName(PRINCIPAL_NAME)
.authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
.attribute(OAuth2ParameterNames.STATE, "state-initial")
.build();
authorizationService.save(initialAuthorization);
OAuth2Authorization authorization =
authorizationService.findById(initialAuthorization.getId());
assertThat(authorization).isEqualTo(initialAuthorization);
}
@Test
public void removeWhenAuthorizationNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.authorizationService.remove(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorization cannot be null");
}
@Test
public void removeWhenAuthorizationProvidedThenRemoved() {
OAuth2Authorization expectedAuthorization = new OAuth2Authorization.Builder()
.id(ID)
.principalName(PRINCIPAL_NAME)
.authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
.token(TOKEN)
.build();
this.authorizationService.save(expectedAuthorization);
OAuth2Authorization authorization = this.authorizationService.findByToken(
TOKEN.getTokenValue(), OAuth2TokenType.ACCESS_TOKEN);
assertThat(authorization).isEqualTo(expectedAuthorization);
this.authorizationService.remove(expectedAuthorization);
authorization = this.authorizationService.findByToken(
TOKEN.getTokenValue(), OAuth2TokenType.ACCESS_TOKEN);
assertThat(authorization).isNull();
}
@Test
public void findByIdWhenIdNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.authorizationService.findById(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("id cannot be empty");
}
@Test
public void findByTokenWhenTokenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(
() -> this.authorizationService.findByToken(null, OAuth2TokenType.ACCESS_TOKEN))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("token cannot be empty");
}
@Test
public void findByTokenWhenAccessTokenExistsThenFound() {
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
"access-token", Instant.now().minusSeconds(60), Instant.now());
OAuth2Authorization authorization = new OAuth2Authorization.Builder()
.id(ID)
.principalName(PRINCIPAL_NAME)
.authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
.token(TOKEN)
.accessToken(accessToken)
.build();
this.authorizationService.save(authorization);
OAuth2Authorization result = this.authorizationService.findByToken(
accessToken.getTokenValue(), OAuth2TokenType.ACCESS_TOKEN);
assertThat(authorization).isEqualTo(result);
result = this.authorizationService.findByToken(accessToken.getTokenValue(), null);
assertThat(authorization).isEqualTo(result);
}
@Test
public void findByTokenWhenRefreshTokenExistsThenFound() {
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now());
OAuth2Authorization authorization = new OAuth2Authorization.Builder()
.id(ID)
.principalName(PRINCIPAL_NAME)
.authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
.refreshToken(refreshToken)
.build();
this.authorizationService.save(authorization);
OAuth2Authorization result = this.authorizationService.findByToken(
refreshToken.getTokenValue(), OAuth2TokenType.REFRESH_TOKEN);
assertThat(authorization).isEqualTo(result);
result = this.authorizationService.findByToken(refreshToken.getTokenValue(), null);
assertThat(authorization).isEqualTo(result);
}
@Test
public void findByTokenWhenWrongTokenTypeThenNotFound() {
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now());
OAuth2Authorization authorization = new OAuth2Authorization.Builder()
.id(ID)
.principalName(PRINCIPAL_NAME)
.authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
.refreshToken(refreshToken)
.build();
this.authorizationService.save(authorization);
OAuth2Authorization result = this.authorizationService.findByToken(
refreshToken.getTokenValue(), OAuth2TokenType.ACCESS_TOKEN);
assertThat(result).isNull();
}
@Test
public void findByTokenWhenTokenDoesNotExistThenNull() {
OAuth2Authorization result = this.authorizationService.findByToken(
"access-token", OAuth2TokenType.ACCESS_TOKEN);
assertThat(result).isNull();
}
}