mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-01 14:41:46 +00:00
ACS-6601 Implement Repository OIDC Compliance (#2447)
* ACS-6677 Enhance OIDC Configuration Flexibility (#2426) * ACS-6603 Implement OIDC Compliance (#2442) * ACS-6677 Enhance OIDC Configuration Flexibility * ACS-6677 Revert changing http header * ACS-6677 Add unit test to suite * ACS-6677 Rename var * ACS-6677 Fix PMD issues * ACS-6677 Fix PMD issues * ACS-6677 Improve code * ACS-6677 Fix compatibility * ACS-6677 Add JwtAudienceValidator * ACS-6677 Change domain * ACS-6603 Oidc compliance * ACS-6603 Add Auth0 test * ACS-6603 Reformat * ACS-6603 Enable User Info Endpoint test + Refactor * ACS-6603 Change test condition * ACS-6603 Add state parameter + reformat stream * ACS-6603 Use enum type
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
package org.alfresco;
|
||||
|
||||
import org.alfresco.repo.security.authentication.identityservice.ClientRegistrationProviderUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacadeFactoryBeanTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceJITProvisioningHandlerUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.LazyInstantiatingIdentityServiceFacadeUnitTest;
|
||||
@@ -151,6 +152,7 @@ import org.junit.runners.Suite;
|
||||
AdminConsoleAuthenticationCookiesServiceUnitTest.class,
|
||||
AdminConsoleHttpServletRequestWrapperUnitTest.class,
|
||||
IdentityServiceAdminConsoleAuthenticatorUnitTest.class,
|
||||
ClientRegistrationProviderUnitTest.class,
|
||||
org.alfresco.repo.security.authentication.CompositePasswordEncoderTest.class,
|
||||
org.alfresco.repo.security.authentication.PasswordHashingTest.class,
|
||||
org.alfresco.repo.security.authority.script.ScriptAuthorityService_RegExTest.class,
|
||||
|
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.nimbusds.oauth2.sdk.ParseException;
|
||||
import com.nimbusds.oauth2.sdk.Scope;
|
||||
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
|
||||
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacadeFactoryBean.ClientRegistrationProvider;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
public class ClientRegistrationProviderUnitTest
|
||||
{
|
||||
private static final String CLIENT_ID = "alfresco";
|
||||
private static final String OPENID_CONFIGURATION = "{\"token_endpoint\":\"https://login.serviceonline.alfresco/common/oauth2/v2.0/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_post\",\"private_key_jwt\",\"client_secret_basic\"],\"jwks_uri\":\"https://login.serviceonline.alfresco/common/discovery/v2.0/keys\",\"response_modes_supported\":[\"query\",\"fragment\",\"form_post\"],\"subject_types_supported\":[\"pairwise\"],\"id_token_signing_alg_values_supported\":[\"RS256\"],\"response_types_supported\":[\"code\",\"id_token\",\"code id_token\",\"id_token token\"],\"scopes_supported\":[\"openid\",\"profile\",\"email\",\"offline_access\"],\"issuer\":\"https://login.serviceonline.alfresco/alfresco/v2.0\",\"request_uri_parameter_supported\":false,\"userinfo_endpoint\":\"https://graph.service.alfresco/oidc/userinfo\",\"authorization_endpoint\":\"https://login.serviceonline.alfresco/common/oauth2/v2.0/authorize\",\"device_authorization_endpoint\":\"https://login.serviceonline.alfresco/common/oauth2/v2.0/devicecode\",\"http_logout_supported\":true,\"frontchannel_logout_supported\":true,\"end_session_endpoint\":\"https://login.serviceonline.alfresco/common/oauth2/v2.0/logout\",\"claims_supported\":[\"sub\",\"iss\",\"cloud_instance_name\",\"cloud_instance_host_name\",\"cloud_graph_host_name\",\"msgraph_host\",\"aud\",\"exp\",\"iat\",\"auth_time\",\"acr\",\"nonce\",\"preferred_username\",\"name\",\"tid\",\"ver\",\"at_hash\",\"c_hash\",\"email\"],\"kerberos_endpoint\":\"https://login.serviceonline.alfresco/common/kerberos\",\"tenant_region_scope\":null,\"cloud_instance_name\":\"serviceonline.alfresco\",\"cloud_graph_host_name\":\"graph.oidc.net\",\"msgraph_host\":\"graph.service.alfresco\",\"rbac_url\":\"https://pas.oidc.alfresco\"}";
|
||||
private static final String DISCOVERY_PATH_SEGMENTS = "/.well-known/openid-configuration";
|
||||
private static final String AUTH_SERVER = "https://login.serviceonline.alfresco";
|
||||
|
||||
private IdentityServiceConfig config;
|
||||
private RestTemplate restTemplate;
|
||||
private OIDCProviderMetadata oidcResponse;
|
||||
|
||||
private ArgumentCaptor<RequestEntity> requestEntityCaptor = ArgumentCaptor.forClass(RequestEntity.class);
|
||||
|
||||
@Before
|
||||
public void setup() throws ParseException
|
||||
{
|
||||
config = new IdentityServiceConfig();
|
||||
config.setAuthServerUrl(AUTH_SERVER);
|
||||
config.setResource(CLIENT_ID);
|
||||
|
||||
restTemplate = mock(RestTemplate.class);
|
||||
ResponseEntity responseEntity = mock(ResponseEntity.class);
|
||||
when(restTemplate.exchange(requestEntityCaptor.capture(), eq(String.class))).thenReturn(responseEntity);
|
||||
when(responseEntity.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
when(responseEntity.hasBody()).thenReturn(true);
|
||||
when(responseEntity.getBody()).thenReturn("");
|
||||
|
||||
oidcResponse = spy(OIDCProviderMetadata.parse(OPENID_CONFIGURATION));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateClientRegistration()
|
||||
{
|
||||
config.setIssuerUrl("https://login.serviceonline.alfresco/alfresco/v2.0");
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
ClientRegistration clientRegistration = new ClientRegistrationProvider(config).createClientRegistration(
|
||||
restTemplate);
|
||||
assertThat(clientRegistration).isNotNull();
|
||||
assertThat(clientRegistration.getClientId()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getAuthorizationUri()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getTokenUri()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getJwkSetUri()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getIssuerUri()).isNotNull();
|
||||
assertThat(requestEntityCaptor.getValue().getUrl().toASCIIString()).isEqualTo(
|
||||
AUTH_SERVER + DISCOVERY_PATH_SEGMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateClientRegistrationWithoutIssuerConfigured()
|
||||
{
|
||||
config.setIssuerUrl(null);
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
ClientRegistration clientRegistration = new ClientRegistrationProvider(config).createClientRegistration(
|
||||
restTemplate);
|
||||
assertThat(clientRegistration).isNotNull();
|
||||
assertThat(clientRegistration.getClientId()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getAuthorizationUri()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getTokenUri()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getJwkSetUri()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint()).isNotNull();
|
||||
assertThat(clientRegistration.getProviderDetails().getIssuerUri()).isNotNull();
|
||||
assertThat(requestEntityCaptor.getValue().getUrl().toASCIIString()).isEqualTo(
|
||||
AUTH_SERVER + DISCOVERY_PATH_SEGMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowIdentityServiceExceptionIfIssuerIsNotValid()
|
||||
{
|
||||
config.setIssuerUrl("https://invalidissuer.alfresco");
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
assertThrows(IdentityServiceException.class,
|
||||
() -> new ClientRegistrationProvider(config).createClientRegistration(restTemplate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowIdentityServiceExceptionIfIssuerIsNull()
|
||||
{
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
when(oidcResponse.getIssuer()).thenReturn(null);
|
||||
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
assertThrows(IdentityServiceException.class,
|
||||
() -> new ClientRegistrationProvider(config).createClientRegistration(restTemplate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowIdentityServiceExceptionIfTokenEndpointIsNull()
|
||||
{
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
when(oidcResponse.getTokenEndpointURI()).thenReturn(null);
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
assertThrows(IdentityServiceException.class,
|
||||
() -> new ClientRegistrationProvider(config).createClientRegistration(restTemplate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowIdentityServiceExceptionIfAuthorizationEndpointIsNull()
|
||||
{
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
when(oidcResponse.getAuthorizationEndpointURI()).thenReturn(null);
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
assertThrows(IdentityServiceException.class,
|
||||
() -> new ClientRegistrationProvider(config).createClientRegistration(restTemplate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowIdentityServiceExceptionIfUserInfoEndpointIsNull()
|
||||
{
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
when(oidcResponse.getUserInfoEndpointURI()).thenReturn(null);
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
assertThrows(IdentityServiceException.class,
|
||||
() -> new ClientRegistrationProvider(config).createClientRegistration(restTemplate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowIdentityServiceExceptionIfJWKSetEndpointIsNull()
|
||||
{
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
when(oidcResponse.getJWKSetURI()).thenReturn(null);
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
assertThrows(IdentityServiceException.class,
|
||||
() -> new ClientRegistrationProvider(config).createClientRegistration(restTemplate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateDiscoveryEndpointWithRealm()
|
||||
{
|
||||
config.setRealm("alfresco");
|
||||
config.setIssuerUrl("https://login.serviceonline.alfresco/alfresco/v2.0");
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
new ClientRegistrationProvider(config).createClientRegistration(restTemplate);
|
||||
assertThat(requestEntityCaptor.getValue().getUrl().toASCIIString()).isEqualTo(
|
||||
AUTH_SERVER + "/realms/alfresco" + DISCOVERY_PATH_SEGMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSetAllSupportedScopes()
|
||||
{
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
ClientRegistration clientRegistration = new ClientRegistrationProvider(config).createClientRegistration(
|
||||
restTemplate);
|
||||
assertThat(
|
||||
clientRegistration.getScopes().containsAll(
|
||||
Set.of("openid", "profile", "email"))).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSetOneSupportedScope()
|
||||
{
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
when(oidcResponse.getScopes()).thenReturn(new Scope("openid"));
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
ClientRegistration clientRegistration = new ClientRegistrationProvider(config).createClientRegistration(
|
||||
restTemplate);
|
||||
assertThat(clientRegistration.getScopes().size()).isEqualTo(1);
|
||||
assertThat(clientRegistration.getScopes().stream().findFirst().get()).isEqualTo("openid");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateDiscoveryEndpointFromIssuer()
|
||||
{
|
||||
config.setAuthServerUrl(null);
|
||||
config.setIssuerUrl("https://login.serviceonline.alfresco/alfresco/v2.0");
|
||||
try (MockedStatic<OIDCProviderMetadata> providerMetadata = Mockito.mockStatic(OIDCProviderMetadata.class))
|
||||
{
|
||||
providerMetadata.when(() -> OIDCProviderMetadata.parse(any(String.class))).thenReturn(oidcResponse);
|
||||
|
||||
new ClientRegistrationProvider(config).createClientRegistration(restTemplate);
|
||||
assertThat(requestEntityCaptor.getValue().getUrl().toASCIIString()).isEqualTo(
|
||||
"https://login.serviceonline.alfresco/alfresco/v2.0" + DISCOVERY_PATH_SEGMENTS);
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -29,10 +29,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.nimbusds.openid.connect.sdk.claims.PersonClaims;
|
||||
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacadeFactoryBean.JwtAudienceValidator;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacadeFactoryBean.JwtDecoderProvider;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacadeFactoryBean.JwtIssuerValidator;
|
||||
import org.junit.Test;
|
||||
@@ -45,11 +49,14 @@ import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
public class IdentityServiceFacadeFactoryBeanTest
|
||||
{
|
||||
private static final String EXPECTED_ISSUER = "expected-issuer";
|
||||
private static final String EXPECTED_AUDIENCE = "expected-audience";
|
||||
|
||||
@Test
|
||||
public void shouldCreateJwtDecoderWithoutIDSWhenPublicKeyIsProvided()
|
||||
{
|
||||
final IdentityServiceConfig config = mock(IdentityServiceConfig.class);
|
||||
when(config.getRealmKey()).thenReturn("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAve3MabX/rp3LbE7/zNqKxuid8WT7y4qSXsNaiPvl/OVbNWW/cu5td1VndItYhH6/gL7Z5W/r4MOeTlz/fOdXfjrRJou2f3UiPQwLV9RdOH3oS4/BUe+sviD8Q3eRfWBWWz3yw8f2YNtD4bMztIMMjqthvwdEEb9S9jbxxD0o71Bsrz/FwPi7HhSDA+Z/p01Hct8m4wx13ZlKRd4YjyC12FBmi9MSgsrFuWzyQHhHTeBDoALpfuiut3rhVxUtFmVTpy6p9vil7C5J5pok4MXPH0dJCyDNQz05ww5+fD+tfksIEpFeokRpN226F+P21oQVFUWwYIaXaFlG/hfvwmnlfQIDAQAB");
|
||||
when(config.isClientIdValidationDisabled()).thenReturn(true);
|
||||
|
||||
final ProviderDetails providerDetails = mock(ProviderDetails.class);
|
||||
when(providerDetails.getIssuerUri()).thenReturn("https://my.issuer");
|
||||
@@ -108,12 +115,78 @@ public class IdentityServiceFacadeFactoryBeanTest
|
||||
assertThat(validationResult.getErrors()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailWithNotMatchingAudienceList()
|
||||
{
|
||||
final JwtAudienceValidator audienceValidator = new JwtAudienceValidator(EXPECTED_AUDIENCE);
|
||||
|
||||
final OAuth2TokenValidatorResult validationResult = audienceValidator.validate(
|
||||
tokenWithAudience(List.of("different-audience")));
|
||||
assertThat(validationResult).isNotNull();
|
||||
assertThat(validationResult.hasErrors()).isTrue();
|
||||
assertThat(validationResult.getErrors()).hasSize(1);
|
||||
|
||||
final OAuth2Error error = validationResult.getErrors().iterator().next();
|
||||
assertThat(error).isNotNull();
|
||||
assertThat(error.getDescription()).contains(EXPECTED_AUDIENCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailWithNullAudience()
|
||||
{
|
||||
final JwtAudienceValidator audienceValidator = new JwtAudienceValidator(EXPECTED_AUDIENCE);
|
||||
|
||||
final OAuth2TokenValidatorResult validationResult = audienceValidator.validate(tokenWithAudience(null));
|
||||
assertThat(validationResult).isNotNull();
|
||||
assertThat(validationResult.hasErrors()).isTrue();
|
||||
assertThat(validationResult.getErrors()).hasSize(1);
|
||||
|
||||
final OAuth2Error error = validationResult.getErrors().iterator().next();
|
||||
assertThat(error).isNotNull();
|
||||
assertThat(error.getDescription()).contains(EXPECTED_AUDIENCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSucceedWithMatchingAudienceList()
|
||||
{
|
||||
final JwtAudienceValidator audienceValidator = new JwtAudienceValidator(EXPECTED_AUDIENCE);
|
||||
|
||||
final OAuth2TokenValidatorResult validationResult = audienceValidator.validate(
|
||||
tokenWithAudience(List.of(EXPECTED_AUDIENCE)));
|
||||
assertThat(validationResult).isNotNull();
|
||||
assertThat(validationResult.hasErrors()).isFalse();
|
||||
assertThat(validationResult.getErrors()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSucceedWithMatchingSingleAudience()
|
||||
{
|
||||
final JwtAudienceValidator audienceValidator = new JwtAudienceValidator(EXPECTED_AUDIENCE);
|
||||
|
||||
final Jwt token = Jwt.withTokenValue(UUID.randomUUID().toString())
|
||||
.claim("aud", EXPECTED_AUDIENCE)
|
||||
.header("JUST", "FOR TESTING")
|
||||
.build();
|
||||
final OAuth2TokenValidatorResult validationResult = audienceValidator.validate(token);
|
||||
assertThat(validationResult).isNotNull();
|
||||
assertThat(validationResult.hasErrors()).isFalse();
|
||||
assertThat(validationResult.getErrors()).isEmpty();
|
||||
}
|
||||
|
||||
private Jwt tokenWithIssuer(String issuer)
|
||||
{
|
||||
return Jwt.withTokenValue(UUID.randomUUID().toString())
|
||||
.issuer(issuer)
|
||||
.header("JUST", "FOR TESTING")
|
||||
.build();
|
||||
.issuer(issuer)
|
||||
.header("JUST", "FOR TESTING")
|
||||
.build();
|
||||
}
|
||||
|
||||
private Jwt tokenWithAudience(Collection<String> audience)
|
||||
{
|
||||
return Jwt.withTokenValue(UUID.randomUUID().toString())
|
||||
.audience(audience)
|
||||
.header("JUST", "FOR TESTING")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice;
|
||||
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -32,6 +33,8 @@ import static org.mockito.Mockito.when;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.nimbusds.openid.connect.sdk.claims.PersonClaims;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.alfresco.repo.management.subsystems.DefaultChildApplicationContextManager;
|
||||
@@ -57,6 +60,14 @@ public class IdentityServiceJITProvisioningHandlerTest extends BaseSpringTest
|
||||
private IdentityServiceFacade identityServiceFacade;
|
||||
private IdentityServiceJITProvisioningHandler jitProvisioningHandler;
|
||||
|
||||
private final boolean isAuth0Enabled = Optional.ofNullable(System.getProperty("auth0.enabled"))
|
||||
.map(Boolean::valueOf)
|
||||
.orElse(false);
|
||||
|
||||
private final String userPassword = Optional.ofNullable(System.getProperty("admin.password"))
|
||||
.filter(password -> isAuth0Enabled)
|
||||
.orElse("password");
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
@@ -85,7 +96,8 @@ public class IdentityServiceJITProvisioningHandlerTest extends BaseSpringTest
|
||||
assertFalse(personService.personExists(IDS_USERNAME));
|
||||
|
||||
IdentityServiceFacade.AccessTokenAuthorization accessTokenAuthorization =
|
||||
identityServiceFacade.authorize(IdentityServiceFacade.AuthorizationGrant.password(IDS_USERNAME, "password"));
|
||||
identityServiceFacade.authorize(
|
||||
IdentityServiceFacade.AuthorizationGrant.password(IDS_USERNAME, userPassword));
|
||||
|
||||
Optional<OIDCUserInfo> userInfoOptional = jitProvisioningHandler.extractUserInfoAndCreateUserIfNeeded(
|
||||
accessTokenAuthorization.getAccessToken().getTokenValue());
|
||||
@@ -94,13 +106,17 @@ public class IdentityServiceJITProvisioningHandlerTest extends BaseSpringTest
|
||||
|
||||
assertTrue(userInfoOptional.isPresent());
|
||||
assertEquals(IDS_USERNAME, userInfoOptional.get().username());
|
||||
assertEquals("John", userInfoOptional.get().firstName());
|
||||
assertEquals("Doe", userInfoOptional.get().lastName());
|
||||
assertEquals("johndoe@test.com", userInfoOptional.get().email());
|
||||
assertEquals("johndoe123@alfresco.com", userInfoOptional.get().email());
|
||||
assertEquals(IDS_USERNAME, nodeService.getProperty(person, ContentModel.PROP_USERNAME));
|
||||
assertEquals("John", nodeService.getProperty(person, ContentModel.PROP_FIRSTNAME));
|
||||
assertEquals("Doe", nodeService.getProperty(person, ContentModel.PROP_LASTNAME));
|
||||
assertEquals("johndoe@test.com", nodeService.getProperty(person, ContentModel.PROP_EMAIL));
|
||||
assertEquals("johndoe123@alfresco.com", nodeService.getProperty(person, ContentModel.PROP_EMAIL));
|
||||
|
||||
if (!isAuth0Enabled)
|
||||
{
|
||||
assertEquals("John", userInfoOptional.get().firstName());
|
||||
assertEquals("Doe", userInfoOptional.get().lastName());
|
||||
assertEquals("John", nodeService.getProperty(person, ContentModel.PROP_FIRSTNAME));
|
||||
assertEquals("Doe", nodeService.getProperty(person, ContentModel.PROP_LASTNAME));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,13 +124,15 @@ public class IdentityServiceJITProvisioningHandlerTest extends BaseSpringTest
|
||||
{
|
||||
assertFalse(personService.personExists(IDS_USERNAME));
|
||||
|
||||
String principalAttribute = isAuth0Enabled ? PersonClaims.NICKNAME_CLAIM_NAME : PersonClaims.PREFERRED_USERNAME_CLAIM_NAME;
|
||||
IdentityServiceFacade.AccessTokenAuthorization accessTokenAuthorization =
|
||||
identityServiceFacade.authorize(IdentityServiceFacade.AuthorizationGrant.password(IDS_USERNAME, "password"));
|
||||
identityServiceFacade.authorize(
|
||||
IdentityServiceFacade.AuthorizationGrant.password(IDS_USERNAME, userPassword));
|
||||
|
||||
String accessToken = accessTokenAuthorization.getAccessToken().getTokenValue();
|
||||
IdentityServiceFacade idsServiceFacadeMock = mock(IdentityServiceFacade.class);
|
||||
when(idsServiceFacadeMock.decodeToken(accessToken)).thenReturn(null);
|
||||
when(idsServiceFacadeMock.getUserInfo(accessToken)).thenReturn(identityServiceFacade.getUserInfo(accessToken));
|
||||
when(idsServiceFacadeMock.getUserInfo(accessToken, principalAttribute)).thenReturn(identityServiceFacade.getUserInfo(accessToken, principalAttribute));
|
||||
|
||||
// Replace the original facade with a mocked one to prevent user information from being extracted from the access token.
|
||||
Field declaredField = jitProvisioningHandler.getClass()
|
||||
@@ -131,15 +149,18 @@ public class IdentityServiceJITProvisioningHandlerTest extends BaseSpringTest
|
||||
|
||||
assertTrue(userInfoOptional.isPresent());
|
||||
assertEquals(IDS_USERNAME, userInfoOptional.get().username());
|
||||
assertEquals("John", userInfoOptional.get().firstName());
|
||||
assertEquals("Doe", userInfoOptional.get().lastName());
|
||||
assertEquals("johndoe@test.com", userInfoOptional.get().email());
|
||||
assertEquals(IDS_USERNAME, nodeService.getProperty(person, ContentModel.PROP_USERNAME));
|
||||
assertEquals("John", nodeService.getProperty(person, ContentModel.PROP_FIRSTNAME));
|
||||
assertEquals("Doe", nodeService.getProperty(person, ContentModel.PROP_LASTNAME));
|
||||
assertEquals("johndoe@test.com", nodeService.getProperty(person, ContentModel.PROP_EMAIL));
|
||||
assertEquals("johndoe123@alfresco.com", userInfoOptional.get().email());
|
||||
assertEquals("johndoe123@alfresco.com", nodeService.getProperty(person, ContentModel.PROP_EMAIL));
|
||||
verify(idsServiceFacadeMock).decodeToken(accessToken);
|
||||
verify(idsServiceFacadeMock).getUserInfo(accessToken);
|
||||
verify(idsServiceFacadeMock, atLeast(1)).getUserInfo(accessToken, principalAttribute);
|
||||
if (!isAuth0Enabled)
|
||||
{
|
||||
assertEquals("John", userInfoOptional.get().firstName());
|
||||
assertEquals("Doe", userInfoOptional.get().lastName());
|
||||
assertEquals("John", nodeService.getProperty(person, ContentModel.PROP_FIRSTNAME));
|
||||
assertEquals("Doe", nodeService.getProperty(person, ContentModel.PROP_LASTNAME));
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -60,6 +60,9 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
@Mock
|
||||
private TransactionService transactionService;
|
||||
|
||||
@Mock
|
||||
private IdentityServiceConfig identityServiceConfig;
|
||||
|
||||
@Mock
|
||||
private OIDCUserInfo userInfo;
|
||||
|
||||
@@ -76,7 +79,7 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
when(identityServiceFacade.decodeToken(JWT_TOKEN)).thenReturn(decodedAccessToken);
|
||||
when(personService.createMissingPeople()).thenReturn(true);
|
||||
jitProvisioningHandler = new IdentityServiceJITProvisioningHandler(identityServiceFacade,
|
||||
personService, transactionService);
|
||||
personService, transactionService, identityServiceConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,7 +94,23 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
assertTrue(result.isPresent());
|
||||
assertEquals("johny123", result.get().username());
|
||||
assertFalse(result.get().allFieldsNotEmpty());
|
||||
verify(identityServiceFacade, never()).getUserInfo(JWT_TOKEN);
|
||||
verify(identityServiceFacade, never()).getUserInfo(JWT_TOKEN, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractUserInfoForExistingUserWithProviderPrincipalAttribute()
|
||||
{
|
||||
when(identityServiceConfig.getPrincipalAttribute()).thenReturn("nickname");
|
||||
when(personService.personExists("johny123")).thenReturn(true);
|
||||
when(decodedAccessToken.getClaim("nickname")).thenReturn("johny123");
|
||||
|
||||
Optional<OIDCUserInfo> result = jitProvisioningHandler.extractUserInfoAndCreateUserIfNeeded(
|
||||
JWT_TOKEN);
|
||||
|
||||
assertTrue(result.isPresent());
|
||||
assertEquals("johny123", result.get().username());
|
||||
assertFalse(result.get().allFieldsNotEmpty());
|
||||
verify(identityServiceFacade, never()).getUserInfo(JWT_TOKEN, "nickname");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,7 +133,7 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
assertEquals("johny123@email.com", result.get().email());
|
||||
assertTrue(result.get().allFieldsNotEmpty());
|
||||
verify(personService).createPerson(any());
|
||||
verify(identityServiceFacade, never()).getUserInfo(JWT_TOKEN);
|
||||
verify(identityServiceFacade, never()).getUserInfo(JWT_TOKEN, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -128,7 +147,7 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
when(personService.personExists("johny123")).thenReturn(false);
|
||||
|
||||
when(decodedAccessToken.getClaim(PersonClaims.PREFERRED_USERNAME_CLAIM_NAME)).thenReturn("johny123");
|
||||
when(identityServiceFacade.getUserInfo(JWT_TOKEN)).thenReturn(Optional.of(userInfo));
|
||||
when(identityServiceFacade.getUserInfo(JWT_TOKEN, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME)).thenReturn(Optional.of(userInfo));
|
||||
|
||||
Optional<OIDCUserInfo> result = jitProvisioningHandler.extractUserInfoAndCreateUserIfNeeded(
|
||||
JWT_TOKEN);
|
||||
@@ -140,21 +159,21 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
assertEquals("johny123@email.com", result.get().email());
|
||||
assertTrue(result.get().allFieldsNotEmpty());
|
||||
verify(personService).createPerson(any());
|
||||
verify(identityServiceFacade).getUserInfo(JWT_TOKEN);
|
||||
verify(identityServiceFacade).getUserInfo(JWT_TOKEN, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnEmptyOptionalIfUsernameNotExtracted()
|
||||
{
|
||||
|
||||
when(identityServiceFacade.getUserInfo(JWT_TOKEN)).thenReturn(Optional.of(userInfo));
|
||||
when(identityServiceFacade.getUserInfo(JWT_TOKEN, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME)).thenReturn(Optional.of(userInfo));
|
||||
|
||||
Optional<OIDCUserInfo> result = jitProvisioningHandler.extractUserInfoAndCreateUserIfNeeded(
|
||||
JWT_TOKEN);
|
||||
|
||||
assertFalse(result.isPresent());
|
||||
verify(personService, never()).createPerson(any());
|
||||
verify(identityServiceFacade).getUserInfo(JWT_TOKEN);
|
||||
verify(identityServiceFacade).getUserInfo(JWT_TOKEN, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -165,7 +184,7 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
when(decodedAccessToken.getClaim(PersonClaims.PREFERRED_USERNAME_CLAIM_NAME)).thenReturn("");
|
||||
|
||||
when(userInfo.username()).thenReturn("johny123");
|
||||
when(identityServiceFacade.getUserInfo(JWT_TOKEN)).thenReturn(Optional.of(userInfo));
|
||||
when(identityServiceFacade.getUserInfo(JWT_TOKEN, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME)).thenReturn(Optional.of(userInfo));
|
||||
|
||||
Optional<OIDCUserInfo> result = jitProvisioningHandler.extractUserInfoAndCreateUserIfNeeded(
|
||||
JWT_TOKEN);
|
||||
@@ -177,7 +196,31 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
assertEquals("", result.get().email());
|
||||
assertFalse(result.get().allFieldsNotEmpty());
|
||||
verify(personService, never()).createPerson(any());
|
||||
verify(identityServiceFacade).getUserInfo(JWT_TOKEN);
|
||||
verify(identityServiceFacade).getUserInfo(JWT_TOKEN, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCallUserInfoEndpointToGetUsernameWithProvidedPrincipalAttribute()
|
||||
{
|
||||
when(identityServiceConfig.getPrincipalAttribute()).thenReturn("nickname");
|
||||
when(personService.personExists("johny123")).thenReturn(true);
|
||||
|
||||
when(decodedAccessToken.getClaim("nickname")).thenReturn("");
|
||||
|
||||
when(userInfo.username()).thenReturn("johny123");
|
||||
when(identityServiceFacade.getUserInfo(JWT_TOKEN, "nickname")).thenReturn(Optional.of(userInfo));
|
||||
|
||||
Optional<OIDCUserInfo> result = jitProvisioningHandler.extractUserInfoAndCreateUserIfNeeded(
|
||||
JWT_TOKEN);
|
||||
|
||||
assertTrue(result.isPresent());
|
||||
assertEquals("johny123", result.get().username());
|
||||
assertEquals("", result.get().firstName());
|
||||
assertEquals("", result.get().lastName());
|
||||
assertEquals("", result.get().email());
|
||||
assertFalse(result.get().allFieldsNotEmpty());
|
||||
verify(personService, never()).createPerson(any());
|
||||
verify(identityServiceFacade).getUserInfo(JWT_TOKEN, "nickname");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -189,8 +232,8 @@ public class IdentityServiceJITProvisioningHandlerUnitTest
|
||||
verify(personService, never()).createPerson(any());
|
||||
verify(identityServiceFacade, never()).decodeToken(null);
|
||||
verify(identityServiceFacade, never()).decodeToken("");
|
||||
verify(identityServiceFacade, never()).getUserInfo(null);
|
||||
verify(identityServiceFacade, never()).getUserInfo("");
|
||||
verify(identityServiceFacade, never()).getUserInfo(null, PersonClaims.PREFERRED_USERNAME_CLAIM_NAME);
|
||||
verify(identityServiceFacade, never()).getUserInfo("", PersonClaims.PREFERRED_USERNAME_CLAIM_NAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -94,13 +94,14 @@ public class IdentityServiceRemoteUserMapperTest extends TestCase
|
||||
final TransactionService transactionService = mock(TransactionService.class);
|
||||
final IdentityServiceFacade facade = mock(IdentityServiceFacade.class);
|
||||
final PersonService personService = mock(PersonService.class);
|
||||
final IdentityServiceConfig identityServiceConfig = mock(IdentityServiceConfig.class);
|
||||
when(transactionService.isReadOnly()).thenReturn(true);
|
||||
when(facade.decodeToken(anyString()))
|
||||
.thenAnswer(i -> new TestDecodedToken(tokenToUser.get(i.getArgument(0, String.class))));
|
||||
|
||||
when(personService.getUserIdentifier(anyString())).thenAnswer(i -> i.getArgument(0, String.class));
|
||||
|
||||
final IdentityServiceJITProvisioningHandler jitProvisioning = new IdentityServiceJITProvisioningHandler(facade, personService, transactionService);
|
||||
final IdentityServiceJITProvisioningHandler jitProvisioning = new IdentityServiceJITProvisioningHandler(facade, personService, transactionService, identityServiceConfig);
|
||||
|
||||
final IdentityServiceRemoteUserMapper mapper = new IdentityServiceRemoteUserMapper();
|
||||
mapper.setJitProvisioningHandler(jitProvisioning);
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -83,7 +83,7 @@ public class SpringBasedIdentityServiceFacadeUnitTest
|
||||
final SpringBasedIdentityServiceFacade facade = new SpringBasedIdentityServiceFacade(restOperations, testRegistration(), jwtDecoder);
|
||||
|
||||
|
||||
assertThat(facade.getUserInfo(TOKEN).isEmpty()).isTrue();
|
||||
assertThat(facade.getUserInfo(TOKEN, "preferred_username").isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
private ClientRegistration testRegistration()
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -36,10 +36,15 @@ import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import com.nimbusds.oauth2.sdk.Scope;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.alfresco.repo.security.authentication.external.RemoteUserMapper;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceConfig;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AccessToken;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AccessTokenAuthorization;
|
||||
@@ -68,6 +73,8 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
@Mock
|
||||
IdentityServiceFacade identityServiceFacade;
|
||||
@Mock
|
||||
IdentityServiceConfig identityServiceConfig;
|
||||
@Mock
|
||||
AdminConsoleAuthenticationCookiesService cookiesService;
|
||||
@Mock
|
||||
RemoteUserMapper remoteUserMapper;
|
||||
@@ -88,9 +95,12 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
initMocks(this);
|
||||
ClientRegistration clientRegistration = mock(ClientRegistration.class);
|
||||
ProviderDetails providerDetails = mock(ProviderDetails.class);
|
||||
Scope scope = Scope.parse(Arrays.asList("openid", "profile", "email", "offline_access"));
|
||||
|
||||
when(clientRegistration.getProviderDetails()).thenReturn(providerDetails);
|
||||
when(clientRegistration.getClientId()).thenReturn("alfresco");
|
||||
when(providerDetails.getAuthorizationUri()).thenReturn("http://localhost:8999/auth");
|
||||
when(providerDetails.getConfigurationMetadata()).thenReturn(Map.of("scopes_supported", scope));
|
||||
when(identityServiceFacade.getClientRegistration()).thenReturn(clientRegistration);
|
||||
when(request.getRequestURL()).thenReturn(adminConsoleURL);
|
||||
when(remoteUserMapper.getRemoteUser(request)).thenReturn(null);
|
||||
@@ -100,6 +110,7 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
authenticator.setIdentityServiceFacade(identityServiceFacade);
|
||||
authenticator.setCookiesService(cookiesService);
|
||||
authenticator.setRemoteUserMapper(remoteUserMapper);
|
||||
authenticator.setIdentityServiceConfig(identityServiceConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -142,11 +153,45 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
@Test
|
||||
public void shouldCallAuthChallenge() throws IOException
|
||||
{
|
||||
String authenticationRequest = "http://localhost:8999/auth?client_id=alfresco&redirect_uri=" + adminConsoleURL
|
||||
+ "&response_type=code&scope=openid";
|
||||
String redirectPath = "/alfresco/s/admin/admin-communitysummary";
|
||||
|
||||
when(identityServiceConfig.getAdminConsoleRedirectPath()).thenReturn("/alfresco/s/admin/admin-communitysummary");
|
||||
ArgumentCaptor<String> authenticationRequest = ArgumentCaptor.forClass(String.class);
|
||||
String expectedUri = "http://localhost:8999/auth?client_id=alfresco&redirect_uri=%s%s&response_type=code&scope="
|
||||
.formatted("http://localhost:8080", redirectPath);
|
||||
|
||||
authenticator.requestAuthentication(request, response);
|
||||
|
||||
verify(response).sendRedirect(authenticationRequest);
|
||||
verify(response).sendRedirect(authenticationRequest.capture());
|
||||
assertTrue(authenticationRequest.getValue().contains(expectedUri));
|
||||
assertTrue(authenticationRequest.getValue().contains("openid"));
|
||||
assertTrue(authenticationRequest.getValue().contains("profile"));
|
||||
assertTrue(authenticationRequest.getValue().contains("email"));
|
||||
assertTrue(authenticationRequest.getValue().contains("offline_access"));
|
||||
assertTrue(authenticationRequest.getValue().contains("state"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCallAuthChallengeWithAudience() throws IOException
|
||||
{
|
||||
String audience = "http://localhost:8082";
|
||||
String redirectPath = "/alfresco/s/admin/admin-communitysummary";
|
||||
when(identityServiceConfig.getAudience()).thenReturn(audience);
|
||||
when(identityServiceConfig.getAdminConsoleRedirectPath()).thenReturn(redirectPath);
|
||||
ArgumentCaptor<String> authenticationRequest = ArgumentCaptor.forClass(String.class);
|
||||
String expectedUri = "http://localhost:8999/auth?client_id=alfresco&redirect_uri=%s%s&response_type=code&scope="
|
||||
.formatted("http://localhost:8080", redirectPath);
|
||||
|
||||
authenticator.requestAuthentication(request, response);
|
||||
|
||||
verify(response).sendRedirect(authenticationRequest.capture());
|
||||
assertTrue(authenticationRequest.getValue().contains(expectedUri));
|
||||
assertTrue(authenticationRequest.getValue().contains("openid"));
|
||||
assertTrue(authenticationRequest.getValue().contains("profile"));
|
||||
assertTrue(authenticationRequest.getValue().contains("email"));
|
||||
assertTrue(authenticationRequest.getValue().contains("offline_access"));
|
||||
assertTrue(authenticationRequest.getValue().contains("audience=%s".formatted(audience)));
|
||||
assertTrue(authenticationRequest.getValue().contains("state"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -1889,7 +1889,7 @@
|
||||
"disableableCredentialTypes": [
|
||||
"password"
|
||||
],
|
||||
"email": "johndoe@test.com",
|
||||
"email": "johndoe123@alfresco.com",
|
||||
"emailVerified": false,
|
||||
"enabled": true,
|
||||
"firstName": "John",
|
||||
|
Reference in New Issue
Block a user