Search in sources :

Example 11 with ClientAuthorization

use of com.gw2auth.oauth2.server.service.client.authorization.ClientAuthorization in project oauth2-server by gw2auth.

the class OAuth2ServerTest method consentSubmitWithUnexpectedGW2APIException.

@WithGw2AuthLogin
public void consentSubmitWithUnexpectedGW2APIException(MockHttpSession session) throws Exception {
    final long accountId = AuthenticationHelper.getUser(session).orElseThrow().getAccountId();
    final ClientRegistrationCreation clientRegistrationCreation = createClientRegistration();
    final ClientRegistration clientRegistration = clientRegistrationCreation.clientRegistration();
    // perform authorization request (which should redirect to the consent page)
    MvcResult result = performAuthorizeWithClient(session, clientRegistration, List.of(Gw2ApiPermission.ACCOUNT.oauth2())).andReturn();
    // submit the consent
    final String tokenA = TestHelper.randomRootToken();
    final String tokenB = TestHelper.randomRootToken();
    final String tokenC = TestHelper.randomRootToken();
    result = performSubmitConsent(session, clientRegistration, URI.create(Objects.requireNonNull(result.getResponse().getRedirectedUrl())), tokenA, tokenB, tokenC).andReturn();
    // verify the consent has been saved
    final ClientConsentEntity clientConsentEntity = this.clientConsentRepository.findByAccountIdAndClientRegistrationId(accountId, clientRegistration.id()).orElse(null);
    assertNotNull(clientConsentEntity);
    assertEquals(Set.of(Gw2ApiPermission.ACCOUNT.oauth2()), clientConsentEntity.authorizedScopes());
    // verify the authorization has been saved
    final List<ClientAuthorizationEntity> authorizations = this.clientAuthorizationRepository.findAllByAccountIdAndClientRegistrationId(accountId, clientConsentEntity.clientRegistrationId());
    assertEquals(1, authorizations.size());
    final ClientAuthorizationEntity clientAuthorization = authorizations.get(0);
    assertEquals(Set.of(Gw2ApiPermission.ACCOUNT.oauth2()), clientAuthorization.authorizedScopes());
    List<ClientAuthorizationTokenEntity> clientAuthorizationTokenEntities = this.clientAuthorizationTokenRepository.findAllByAccountIdAndClientAuthorizationId(accountId, clientAuthorization.id());
    assertEquals(2, clientAuthorizationTokenEntities.size());
    // set testing clock to token customizer
    final Clock testingClock = Clock.fixed(Instant.now(), ZoneId.systemDefault());
    this.oAuth2TokenCustomizerService.setClock(testingClock);
    // prepare the gw2 api for the next requests
    final String dummySubtokenA = TestHelper.createSubtokenJWT(this.gw2AccountId1st, Set.of(Gw2ApiPermission.ACCOUNT), testingClock.instant(), Duration.ofMinutes(30L));
    this.gw2RestServer.reset();
    this.gw2RestServer.expect(times(2), requestTo(new StringStartsWith("/v2/createsubtoken"))).andExpect(method(HttpMethod.GET)).andExpect(MockRestRequestMatchers.header("Authorization", new StringStartsWith("Bearer "))).andExpect(queryParam("permissions", split(",", containingAll(Gw2ApiPermission.ACCOUNT.gw2())))).andExpect(queryParam("expire", asInstant(instantWithinTolerance(Instant.now().plus(Duration.ofMinutes(30L)), Duration.ofSeconds(5L))))).andRespond((request) -> {
        final String gw2ApiToken = request.getHeaders().getFirst("Authorization").replaceFirst("Bearer ", "");
        final String subtoken;
        if (gw2ApiToken.equals(tokenA)) {
            subtoken = dummySubtokenA;
        } else if (gw2ApiToken.equals(tokenB)) {
            throw new RuntimeException("unexpected exception");
        } else {
            subtoken = null;
        }
        if (subtoken == null || subtoken.isEmpty()) {
            return new MockClientHttpResponse(new byte[0], HttpStatus.UNAUTHORIZED);
        }
        final MockClientHttpResponse response = new MockClientHttpResponse(new JSONObject(Map.of("subtoken", subtoken)).toString().getBytes(StandardCharsets.UTF_8), HttpStatus.OK);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        return response;
    });
    // retrieve the initial access and refresh token
    final String codeParam = Utils.parseQuery(URI.create(Objects.requireNonNull(result.getResponse().getRedirectedUrl())).getRawQuery()).filter(QueryParam::hasValue).filter((queryParam) -> queryParam.name().equals(OAuth2ParameterNames.CODE)).map(QueryParam::value).findFirst().orElse(null);
    assertNotNull(codeParam);
    // retrieve an access token
    // dont use the user session here!
    result = this.mockMvc.perform(post("/oauth2/token").queryParam(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()).queryParam(OAuth2ParameterNames.CODE, codeParam).queryParam(OAuth2ParameterNames.CLIENT_ID, clientRegistrationCreation.clientRegistration().clientId().toString()).queryParam(OAuth2ParameterNames.CLIENT_SECRET, clientRegistrationCreation.clientSecret()).queryParam(OAuth2ParameterNames.REDIRECT_URI, TestHelper.first(clientRegistrationCreation.clientRegistration().redirectUris()).orElseThrow())).andExpectAll(expectValidTokenResponse()).andReturn();
    // verify the subtokens have been updated
    final Set<String> savedSubtokens = this.apiSubTokenRepository.findAllByAccountIdGw2AccountIdsAndGw2ApiPermissionsBitSet(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd), Gw2ApiPermission.toBitSet(Set.of(Gw2ApiPermission.ACCOUNT))).stream().map(ApiSubTokenEntity::gw2ApiSubtoken).collect(Collectors.toSet());
    assertEquals(1, savedSubtokens.size());
    assertTrue(savedSubtokens.contains(dummySubtokenA));
    // verify the validity status has been saved
    final List<ApiTokenEntity> apiTokenEntities = this.apiTokenRepository.findAllByAccountIdAndGw2AccountIds(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd));
    assertEquals(2, apiTokenEntities.size());
    for (ApiTokenEntity apiTokenEntity : apiTokenEntities) {
        if (apiTokenEntity.gw2AccountId().equals(this.gw2AccountId1st)) {
            assertTrue(apiTokenEntity.isValid());
            assertInstantEquals(testingClock.instant(), apiTokenEntity.lastValidCheckTime());
        } else {
            assertTrue(apiTokenEntity.isValid());
            assertTrue(testingClock.instant().isAfter(apiTokenEntity.lastValidCheckTime()));
        }
    }
    // verify the access token
    assertTokenResponse(result, () -> Map.of(this.gw2AccountId1st, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "First", "token", dummySubtokenA)), this.gw2AccountId2nd, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "Second", "error", "Failed to obtain new subtoken"))));
}
Also used : ApiTokenRepository(com.gw2auth.oauth2.server.repository.apitoken.ApiTokenRepository) BeforeEach(org.junit.jupiter.api.BeforeEach) MockMvcResultMatchers.jsonPath(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath) AccountService(com.gw2auth.oauth2.server.service.account.AccountService) Autowired(org.springframework.beans.factory.annotation.Autowired) JWTParser(com.nimbusds.jwt.JWTParser) QueryParam(com.gw2auth.oauth2.server.util.QueryParam) MockHttpServletRequestBuilder(org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder) ResultActions(org.springframework.test.web.servlet.ResultActions) ClientConsentEntity(com.gw2auth.oauth2.server.repository.client.consent.ClientConsentEntity) JSONObject(org.json.JSONObject) JWT(com.nimbusds.jwt.JWT) Duration(java.time.Duration) Utils(com.gw2auth.oauth2.server.util.Utils) JsonNode(com.fasterxml.jackson.databind.JsonNode) StringEndsWith(org.hamcrest.core.StringEndsWith) URI(java.net.URI) OAuth2TokenCustomizerService(com.gw2auth.oauth2.server.service.OAuth2TokenCustomizerService) StringStartsWith(org.hamcrest.core.StringStartsWith) MediaType(org.springframework.http.MediaType) Assertions.assertInstantEquals(com.gw2auth.oauth2.server.Assertions.assertInstantEquals) MockHttpSession(org.springframework.mock.web.MockHttpSession) MockMvcResultMatchers(org.springframework.test.web.servlet.result.MockMvcResultMatchers) ClientAuthorizationTokenRepository(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationTokenRepository) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) ZoneId(java.time.ZoneId) Test(org.junit.jupiter.api.Test) ClientConsentService(com.gw2auth.oauth2.server.service.client.consent.ClientConsentService) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) ClientRegistration(com.gw2auth.oauth2.server.service.client.registration.ClientRegistration) MockRestRequestMatchers(org.springframework.test.web.client.match.MockRestRequestMatchers) SecurityMockMvcRequestPostProcessors.csrf(org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf) ClientAuthorizationRepository(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationRepository) OAuth2ParameterNames(org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames) ApiSubTokenRepository(com.gw2auth.oauth2.server.repository.apisubtoken.ApiSubTokenRepository) java.util(java.util) com.gw2auth.oauth2.server(com.gw2auth.oauth2.server) ClientAuthorizationServiceImpl(com.gw2auth.oauth2.server.service.client.authorization.ClientAuthorizationServiceImpl) Gw2AccountVerificationRepository(com.gw2auth.oauth2.server.repository.verification.Gw2AccountVerificationRepository) ResultMatcher(org.springframework.test.web.servlet.ResultMatcher) AuthenticationHelper(com.gw2auth.oauth2.server.util.AuthenticationHelper) MockClientHttpResponse(org.springframework.mock.http.client.MockClientHttpResponse) ClientRegistrationService(com.gw2auth.oauth2.server.service.client.registration.ClientRegistrationService) Supplier(java.util.function.Supplier) AllOf(org.hamcrest.core.AllOf) MockRestServiceServer(org.springframework.test.web.client.MockRestServiceServer) MockMvc(org.springframework.test.web.servlet.MockMvc) ClientConsentRepository(com.gw2auth.oauth2.server.repository.client.consent.ClientConsentRepository) RegisterExtension(org.junit.jupiter.api.extension.RegisterExtension) MockMvcRequestBuilders.post(org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post) MvcResult(org.springframework.test.web.servlet.MvcResult) IsEqual(org.hamcrest.core.IsEqual) Qualifier(org.springframework.beans.factory.annotation.Qualifier) ExpectedCount.times(org.springframework.test.web.client.ExpectedCount.times) Gw2AccountVerificationEntity(com.gw2auth.oauth2.server.repository.verification.Gw2AccountVerificationEntity) ClientAuthorizationEntity(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationEntity) MockMvcResultMatchers.header(org.springframework.test.web.servlet.result.MockMvcResultMatchers.header) ClientAuthorizationTokenEntity(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationTokenEntity) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) HttpMethod(org.springframework.http.HttpMethod) Account(com.gw2auth.oauth2.server.service.account.Account) ApiTokenEntity(com.gw2auth.oauth2.server.repository.apitoken.ApiTokenEntity) HttpStatus(org.springframework.http.HttpStatus) ApiSubTokenEntity(com.gw2auth.oauth2.server.repository.apisubtoken.ApiSubTokenEntity) AutoConfigureMockMvc(org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc) OAuth2TokenType(org.springframework.security.oauth2.core.OAuth2TokenType) ClientRegistrationCreation(com.gw2auth.oauth2.server.service.client.registration.ClientRegistrationCreation) Gw2ApiPermission(com.gw2auth.oauth2.server.service.Gw2ApiPermission) Matchers(com.gw2auth.oauth2.server.Matchers) Assertions(org.junit.jupiter.api.Assertions) MockMvcRequestBuilders.get(org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get) Clock(java.time.Clock) AuthorizationGrantType(org.springframework.security.oauth2.core.AuthorizationGrantType) UriComponents(org.springframework.web.util.UriComponents) ApiTokenEntity(com.gw2auth.oauth2.server.repository.apitoken.ApiTokenEntity) StringStartsWith(org.hamcrest.core.StringStartsWith) MvcResult(org.springframework.test.web.servlet.MvcResult) Clock(java.time.Clock) ClientRegistrationCreation(com.gw2auth.oauth2.server.service.client.registration.ClientRegistrationCreation) ClientAuthorizationEntity(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationEntity) ClientRegistration(com.gw2auth.oauth2.server.service.client.registration.ClientRegistration) JSONObject(org.json.JSONObject) QueryParam(com.gw2auth.oauth2.server.util.QueryParam) ClientAuthorizationTokenEntity(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationTokenEntity) ClientConsentEntity(com.gw2auth.oauth2.server.repository.client.consent.ClientConsentEntity) MockClientHttpResponse(org.springframework.mock.http.client.MockClientHttpResponse)

Example 12 with ClientAuthorization

use of com.gw2auth.oauth2.server.service.client.authorization.ClientAuthorization in project oauth2-server by gw2auth.

the class OAuth2ServerTest method consentSubmitWithExpiredSubtokens.

@WithGw2AuthLogin
public void consentSubmitWithExpiredSubtokens(MockHttpSession session) throws Exception {
    final long accountId = AuthenticationHelper.getUser(session).orElseThrow().getAccountId();
    final ClientRegistrationCreation clientRegistrationCreation = createClientRegistration();
    final ClientRegistration clientRegistration = clientRegistrationCreation.clientRegistration();
    // perform authorization request (which should redirect to the consent page)
    MvcResult result = performAuthorizeWithClient(session, clientRegistration, List.of(Gw2ApiPermission.ACCOUNT.oauth2())).andReturn();
    // submit the consent
    final String tokenA = TestHelper.randomRootToken();
    final String tokenB = TestHelper.randomRootToken();
    final String tokenC = TestHelper.randomRootToken();
    result = performSubmitConsent(session, clientRegistration, URI.create(Objects.requireNonNull(result.getResponse().getRedirectedUrl())), tokenA, tokenB, tokenC).andReturn();
    // verify the consent has been saved
    final ClientConsentEntity clientConsentEntity = this.clientConsentRepository.findByAccountIdAndClientRegistrationId(accountId, clientRegistration.id()).orElse(null);
    assertNotNull(clientConsentEntity);
    assertEquals(Set.of(Gw2ApiPermission.ACCOUNT.oauth2()), clientConsentEntity.authorizedScopes());
    // verify the authorization has been saved
    final List<ClientAuthorizationEntity> authorizations = this.clientAuthorizationRepository.findAllByAccountIdAndClientRegistrationId(accountId, clientConsentEntity.clientRegistrationId());
    assertEquals(1, authorizations.size());
    final ClientAuthorizationEntity clientAuthorization = authorizations.get(0);
    assertEquals(Set.of(Gw2ApiPermission.ACCOUNT.oauth2()), clientAuthorization.authorizedScopes());
    List<ClientAuthorizationTokenEntity> clientAuthorizationTokenEntities = this.clientAuthorizationTokenRepository.findAllByAccountIdAndClientAuthorizationId(accountId, clientAuthorization.id());
    assertEquals(2, clientAuthorizationTokenEntities.size());
    // set testing clock to token customizer
    Clock testingClock = Clock.fixed(Instant.now(), ZoneId.systemDefault());
    this.oAuth2TokenCustomizerService.setClock(testingClock);
    // retrieve the initial access and refresh token
    final String[] dummySubtokenA = new String[] { TestHelper.createSubtokenJWT(this.gw2AccountId1st, Set.of(Gw2ApiPermission.ACCOUNT), testingClock.instant(), Duration.ofMinutes(30L)) };
    final String[] dummySubtokenB = new String[] { TestHelper.createSubtokenJWT(this.gw2AccountId2nd, Set.of(Gw2ApiPermission.ACCOUNT), testingClock.instant(), Duration.ofMinutes(30L)) };
    result = performRetrieveTokenByCodeAndExpectValid(clientRegistrationCreation, URI.create(Objects.requireNonNull(result.getResponse().getRedirectedUrl())), Map.of(tokenA, dummySubtokenA[0], tokenB, dummySubtokenB[0])).andReturn();
    // verify the subtokens have been updated
    clientAuthorizationTokenEntities = this.clientAuthorizationTokenRepository.findAllByAccountIdAndClientAuthorizationId(accountId, clientAuthorization.id());
    assertEquals(2, clientAuthorizationTokenEntities.size());
    Set<String> savedSubtokens = this.apiSubTokenRepository.findAllByAccountIdGw2AccountIdsAndGw2ApiPermissionsBitSet(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd), Gw2ApiPermission.toBitSet(Set.of(Gw2ApiPermission.ACCOUNT))).stream().map(ApiSubTokenEntity::gw2ApiSubtoken).collect(Collectors.toSet());
    assertEquals(2, savedSubtokens.size());
    assertTrue(savedSubtokens.contains(dummySubtokenA[0]));
    assertTrue(savedSubtokens.contains(dummySubtokenB[0]));
    // verify the validity status has been saved
    List<ApiTokenEntity> apiTokenEntities = this.apiTokenRepository.findAllByAccountIdAndGw2AccountIds(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd));
    assertEquals(2, apiTokenEntities.size());
    assertTrue(apiTokenEntities.get(0).isValid());
    assertInstantEquals(testingClock.instant(), apiTokenEntities.get(0).lastValidCheckTime());
    assertTrue(apiTokenEntities.get(1).isValid());
    assertInstantEquals(testingClock.instant(), apiTokenEntities.get(1).lastValidCheckTime());
    // verify the access token
    JsonNode tokenResponse = assertTokenResponse(result, () -> Map.of(this.gw2AccountId1st, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "First", "token", dummySubtokenA[0])), this.gw2AccountId2nd, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "Second", "token", dummySubtokenB[0]))));
    // prepare the gw2 reset api for new subtoken requests
    dummySubtokenA[0] = TestHelper.createSubtokenJWT(this.gw2AccountId1st, Set.of(Gw2ApiPermission.ACCOUNT), testingClock.instant(), Duration.ofMinutes(30L));
    dummySubtokenB[0] = TestHelper.createSubtokenJWT(this.gw2AccountId2nd, Set.of(Gw2ApiPermission.ACCOUNT), testingClock.instant(), Duration.ofMinutes(30L));
    prepareGw2RestServerForCreateSubToken(Map.of(tokenA, dummySubtokenA[0], tokenB, dummySubtokenB[0]));
    // retrieve a new access token using the refresh token
    testingClock = Clock.offset(testingClock, Duration.ofMinutes(31L));
    this.oAuth2TokenCustomizerService.setClock(testingClock);
    final String refreshToken = tokenResponse.get("refresh_token").textValue();
    result = performRetrieveTokensByRefreshTokenAndExpectValid(clientRegistrationCreation, refreshToken).andReturn();
    // verify the subtokens have been updated
    savedSubtokens = this.apiSubTokenRepository.findAllByAccountIdGw2AccountIdsAndGw2ApiPermissionsBitSet(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd), Gw2ApiPermission.toBitSet(Set.of(Gw2ApiPermission.ACCOUNT))).stream().map(ApiSubTokenEntity::gw2ApiSubtoken).collect(Collectors.toSet());
    assertEquals(2, savedSubtokens.size());
    assertTrue(savedSubtokens.contains(dummySubtokenA[0]));
    assertTrue(savedSubtokens.contains(dummySubtokenB[0]));
    // verify the validity status has been saved
    apiTokenEntities = this.apiTokenRepository.findAllByAccountIdAndGw2AccountIds(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd));
    assertEquals(2, apiTokenEntities.size());
    assertTrue(apiTokenEntities.get(0).isValid());
    assertInstantEquals(testingClock.instant(), apiTokenEntities.get(0).lastValidCheckTime());
    assertTrue(apiTokenEntities.get(1).isValid());
    assertInstantEquals(testingClock.instant(), apiTokenEntities.get(1).lastValidCheckTime());
    // verify the new response
    tokenResponse = assertTokenResponse(result, () -> Map.of(this.gw2AccountId1st, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "First", "token", dummySubtokenA[0])), this.gw2AccountId2nd, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "Second", "token", dummySubtokenB[0]))));
    assertNotEquals(refreshToken, tokenResponse.get("refresh_token").textValue());
}
Also used : ApiTokenEntity(com.gw2auth.oauth2.server.repository.apitoken.ApiTokenEntity) JsonNode(com.fasterxml.jackson.databind.JsonNode) MvcResult(org.springframework.test.web.servlet.MvcResult) Clock(java.time.Clock) ClientRegistrationCreation(com.gw2auth.oauth2.server.service.client.registration.ClientRegistrationCreation) ClientAuthorizationEntity(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationEntity) ClientRegistration(com.gw2auth.oauth2.server.service.client.registration.ClientRegistration) JSONObject(org.json.JSONObject) ApiSubTokenEntity(com.gw2auth.oauth2.server.repository.apisubtoken.ApiSubTokenEntity) ClientAuthorizationTokenEntity(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationTokenEntity) ClientConsentEntity(com.gw2auth.oauth2.server.repository.client.consent.ClientConsentEntity)

Example 13 with ClientAuthorization

use of com.gw2auth.oauth2.server.service.client.authorization.ClientAuthorization in project oauth2-server by gw2auth.

the class OAuth2ServerTest method consentSubmitWithLessScopesThanRequested.

@WithGw2AuthLogin
public void consentSubmitWithLessScopesThanRequested(MockHttpSession session) throws Exception {
    final long accountId = AuthenticationHelper.getUser(session).orElseThrow().getAccountId();
    final ClientRegistrationCreation clientRegistrationCreation = createClientRegistration();
    final ClientRegistration clientRegistration = clientRegistrationCreation.clientRegistration();
    // perform authorization request (which should redirect to the consent page)
    MvcResult result = performAuthorizeWithClient(session, clientRegistration, List.of(Gw2ApiPermission.ACCOUNT.oauth2(), Gw2ApiPermission.TRADINGPOST.oauth2())).andReturn();
    // read request information from redirected uri
    final Map<String, String> params = Utils.parseQuery(URI.create(result.getResponse().getRedirectedUrl()).getRawQuery()).filter(QueryParam::hasValue).collect(Collectors.toMap(QueryParam::name, QueryParam::value));
    assertTrue(params.containsKey(OAuth2ParameterNames.CLIENT_ID));
    assertTrue(params.containsKey(OAuth2ParameterNames.STATE));
    assertTrue(params.containsKey(OAuth2ParameterNames.SCOPE));
    // insert a dummy api token
    this.testHelper.createApiToken(accountId, this.gw2AccountId1st, "TokenA", Set.of(Gw2ApiPermission.ACCOUNT, Gw2ApiPermission.TRADINGPOST), "First");
    // lookup the consent info (containing the submit uri and parameters that should be submitted)
    result = this.mockMvc.perform(get("/api/oauth2/consent").session(session).queryParam(OAuth2ParameterNames.CLIENT_ID, params.get(OAuth2ParameterNames.CLIENT_ID)).queryParam(OAuth2ParameterNames.STATE, params.get(OAuth2ParameterNames.STATE)).queryParam(OAuth2ParameterNames.SCOPE, params.get(OAuth2ParameterNames.SCOPE))).andReturn();
    // read the consent info and build the submit request
    final ObjectMapper mapper = new ObjectMapper();
    final JsonNode consentInfo = mapper.readTree(result.getResponse().getContentAsString());
    final String submitUri = consentInfo.get("submitFormUri").textValue();
    MockHttpServletRequestBuilder builder = post(submitUri).contentType(MediaType.APPLICATION_FORM_URLENCODED).session(session).with(csrf());
    for (Map.Entry<String, JsonNode> entry : (Iterable<? extends Map.Entry<String, JsonNode>>) () -> consentInfo.get("submitFormParameters").fields()) {
        final String name = entry.getKey();
        final JsonNode values = entry.getValue();
        for (int i = 0; i < values.size(); i++) {
            final String value = values.get(i).textValue();
            // exclude the tradingpost scope
            if (!name.equals(OAuth2ParameterNames.SCOPE) || !value.equals(Gw2ApiPermission.TRADINGPOST.oauth2())) {
                builder = builder.param(name, value);
            }
        }
    }
    final JsonNode apiTokensWithSufficientPermissions = consentInfo.get("apiTokensWithSufficientPermissions");
    assertEquals(1, apiTokensWithSufficientPermissions.size());
    assertEquals(0, consentInfo.get("apiTokensWithInsufficientPermissions").size());
    for (int i = 0; i < apiTokensWithSufficientPermissions.size(); i++) {
        builder = builder.param("token:" + apiTokensWithSufficientPermissions.get(i).get("gw2AccountId").textValue(), "");
    }
    // submit the consent
    this.mockMvc.perform(builder).andExpect(status().isBadRequest());
    // authorization should not be saved
    final ClientConsentEntity clientAuthorization = this.clientConsentRepository.findByAccountIdAndClientRegistrationId(accountId, clientRegistration.id()).orElse(null);
    // null is ok too
    if (clientAuthorization != null) {
        assertTrue(clientAuthorization.authorizedScopes().isEmpty());
    }
}
Also used : MockHttpServletRequestBuilder(org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder) JsonNode(com.fasterxml.jackson.databind.JsonNode) MvcResult(org.springframework.test.web.servlet.MvcResult) ClientRegistrationCreation(com.gw2auth.oauth2.server.service.client.registration.ClientRegistrationCreation) ClientRegistration(com.gw2auth.oauth2.server.service.client.registration.ClientRegistration) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) ClientConsentEntity(com.gw2auth.oauth2.server.repository.client.consent.ClientConsentEntity)

Example 14 with ClientAuthorization

use of com.gw2auth.oauth2.server.service.client.authorization.ClientAuthorization in project oauth2-server by gw2auth.

the class OAuth2ServerTest method consentSubmitWithSubtokenRetrievalError.

@WithGw2AuthLogin
public void consentSubmitWithSubtokenRetrievalError(MockHttpSession session) throws Exception {
    final long accountId = AuthenticationHelper.getUser(session).orElseThrow().getAccountId();
    final ClientRegistrationCreation clientRegistrationCreation = createClientRegistration();
    final ClientRegistration clientRegistration = clientRegistrationCreation.clientRegistration();
    // perform authorization request (which should redirect to the consent page)
    MvcResult result = performAuthorizeWithClient(session, clientRegistration, List.of(Gw2ApiPermission.ACCOUNT.oauth2())).andReturn();
    // submit the consent
    final String tokenA = TestHelper.randomRootToken();
    final String tokenB = TestHelper.randomRootToken();
    final String tokenC = TestHelper.randomRootToken();
    result = performSubmitConsent(session, clientRegistration, URI.create(Objects.requireNonNull(result.getResponse().getRedirectedUrl())), tokenA, tokenB, tokenC).andReturn();
    // verify the consent has been saved
    final ClientConsentEntity clientConsentEntity = this.clientConsentRepository.findByAccountIdAndClientRegistrationId(accountId, clientRegistration.id()).orElse(null);
    assertNotNull(clientConsentEntity);
    assertEquals(Set.of(Gw2ApiPermission.ACCOUNT.oauth2()), clientConsentEntity.authorizedScopes());
    // verify the authorization has been saved
    final List<ClientAuthorizationEntity> authorizations = this.clientAuthorizationRepository.findAllByAccountIdAndClientRegistrationId(accountId, clientConsentEntity.clientRegistrationId());
    assertEquals(1, authorizations.size());
    final ClientAuthorizationEntity clientAuthorization = authorizations.get(0);
    assertEquals(Set.of(Gw2ApiPermission.ACCOUNT.oauth2()), clientAuthorization.authorizedScopes());
    List<ClientAuthorizationTokenEntity> clientAuthorizationTokenEntities = this.clientAuthorizationTokenRepository.findAllByAccountIdAndClientAuthorizationId(accountId, clientAuthorization.id());
    assertEquals(2, clientAuthorizationTokenEntities.size());
    // set testing clock to token customizer
    Clock testingClock = Clock.fixed(Instant.now(), ZoneId.systemDefault());
    this.oAuth2TokenCustomizerService.setClock(testingClock);
    // retrieve the initial access and refresh token
    final String[] dummySubtokenA = new String[] { TestHelper.createSubtokenJWT(this.gw2AccountId1st, Set.of(Gw2ApiPermission.ACCOUNT), testingClock.instant(), Duration.ofMinutes(30L)) };
    final String[] dummySubtokenB = new String[] { TestHelper.createSubtokenJWT(this.gw2AccountId2nd, Set.of(Gw2ApiPermission.ACCOUNT), testingClock.instant(), Duration.ofMinutes(30L)) };
    result = performRetrieveTokenByCodeAndExpectValid(clientRegistrationCreation, URI.create(Objects.requireNonNull(result.getResponse().getRedirectedUrl())), Map.of(tokenA, dummySubtokenA[0], tokenB, dummySubtokenB[0])).andReturn();
    // verify the subtokens been updated
    Set<String> savedSubtokens = this.apiSubTokenRepository.findAllByAccountIdGw2AccountIdsAndGw2ApiPermissionsBitSet(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd), Gw2ApiPermission.toBitSet(Set.of(Gw2ApiPermission.ACCOUNT))).stream().map(ApiSubTokenEntity::gw2ApiSubtoken).collect(Collectors.toSet());
    assertEquals(2, savedSubtokens.size());
    assertTrue(savedSubtokens.contains(dummySubtokenA[0]));
    assertTrue(savedSubtokens.contains(dummySubtokenB[0]));
    // verify the validity status has been saved
    List<ApiTokenEntity> apiTokenEntities = this.apiTokenRepository.findAllByAccountIdAndGw2AccountIds(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd));
    assertEquals(2, apiTokenEntities.size());
    assertTrue(apiTokenEntities.get(0).isValid());
    assertInstantEquals(testingClock.instant(), apiTokenEntities.get(0).lastValidCheckTime());
    assertTrue(apiTokenEntities.get(1).isValid());
    assertInstantEquals(testingClock.instant(), apiTokenEntities.get(1).lastValidCheckTime());
    // verify the access token
    JsonNode tokenResponse = assertTokenResponse(result, () -> Map.of(this.gw2AccountId1st, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "First", "token", dummySubtokenA[0])), this.gw2AccountId2nd, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "Second", "token", dummySubtokenB[0]))));
    // prepare the gw2 reset api for new subtoken requests (dont return a new subtoken for TokenB in this testcase)
    dummySubtokenA[0] = TestHelper.createSubtokenJWT(this.gw2AccountId1st, Set.of(Gw2ApiPermission.ACCOUNT), testingClock.instant(), Duration.ofMinutes(30L));
    prepareGw2RestServerForCreateSubToken(Map.of(tokenA, dummySubtokenA[0], tokenB, ""));
    // retrieve a new access token using the refresh token
    testingClock = Clock.offset(testingClock, Duration.ofMinutes(31L));
    this.oAuth2TokenCustomizerService.setClock(testingClock);
    final String refreshToken = tokenResponse.get("refresh_token").textValue();
    result = performRetrieveTokensByRefreshTokenAndExpectValid(clientRegistrationCreation, refreshToken).andReturn();
    // verify the subtokens have been updated, but only for one
    savedSubtokens = this.apiSubTokenRepository.findAllByAccountIdGw2AccountIdsAndGw2ApiPermissionsBitSet(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd), Gw2ApiPermission.toBitSet(Set.of(Gw2ApiPermission.ACCOUNT))).stream().map(ApiSubTokenEntity::gw2ApiSubtoken).collect(Collectors.toSet());
    assertEquals(2, savedSubtokens.size());
    assertTrue(savedSubtokens.contains(dummySubtokenA[0]));
    assertTrue(savedSubtokens.contains(dummySubtokenB[0]));
    // verify the validity status has been saved, but only for the first one
    apiTokenEntities = this.apiTokenRepository.findAllByAccountIdAndGw2AccountIds(accountId, Set.of(this.gw2AccountId1st, this.gw2AccountId2nd));
    assertEquals(2, apiTokenEntities.size());
    for (ApiTokenEntity apiTokenEntity : apiTokenEntities) {
        if (apiTokenEntity.gw2AccountId().equals(this.gw2AccountId1st)) {
            assertTrue(apiTokenEntity.isValid());
            assertInstantEquals(testingClock.instant(), apiTokenEntity.lastValidCheckTime());
        } else {
            assertTrue(apiTokenEntity.isValid());
            assertTrue(testingClock.instant().isAfter(apiTokenEntity.lastValidCheckTime()));
        }
    }
    tokenResponse = assertTokenResponse(result, () -> Map.of(this.gw2AccountId1st, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "First", "token", dummySubtokenA[0])), this.gw2AccountId2nd, new com.nimbusds.jose.shaded.json.JSONObject(Map.of("name", "Second", "error", "Failed to obtain new subtoken"))));
    assertNotEquals(refreshToken, tokenResponse.get("refresh_token").textValue());
}
Also used : ApiTokenEntity(com.gw2auth.oauth2.server.repository.apitoken.ApiTokenEntity) JsonNode(com.fasterxml.jackson.databind.JsonNode) MvcResult(org.springframework.test.web.servlet.MvcResult) Clock(java.time.Clock) ClientRegistrationCreation(com.gw2auth.oauth2.server.service.client.registration.ClientRegistrationCreation) ClientAuthorizationEntity(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationEntity) ClientRegistration(com.gw2auth.oauth2.server.service.client.registration.ClientRegistration) JSONObject(org.json.JSONObject) ApiSubTokenEntity(com.gw2auth.oauth2.server.repository.apisubtoken.ApiSubTokenEntity) ClientAuthorizationTokenEntity(com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationTokenEntity) ClientConsentEntity(com.gw2auth.oauth2.server.repository.client.consent.ClientConsentEntity)

Aggregations

ClientRegistration (com.gw2auth.oauth2.server.service.client.registration.ClientRegistration)10 JsonNode (com.fasterxml.jackson.databind.JsonNode)9 ClientConsentEntity (com.gw2auth.oauth2.server.repository.client.consent.ClientConsentEntity)9 ClientRegistrationCreation (com.gw2auth.oauth2.server.service.client.registration.ClientRegistrationCreation)8 Clock (java.time.Clock)8 MvcResult (org.springframework.test.web.servlet.MvcResult)8 ClientAuthorizationEntity (com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationEntity)7 ClientAuthorizationTokenEntity (com.gw2auth.oauth2.server.repository.client.authorization.ClientAuthorizationTokenEntity)7 JSONObject (org.json.JSONObject)7 ApiTokenEntity (com.gw2auth.oauth2.server.repository.apitoken.ApiTokenEntity)6 ApiToken (com.gw2auth.oauth2.server.service.apitoken.ApiToken)5 ClientAuthorization (com.gw2auth.oauth2.server.service.client.authorization.ClientAuthorization)5 Collectors (java.util.stream.Collectors)5 Autowired (org.springframework.beans.factory.annotation.Autowired)5 ApiSubTokenEntity (com.gw2auth.oauth2.server.repository.apisubtoken.ApiSubTokenEntity)4 ApiTokenService (com.gw2auth.oauth2.server.service.apitoken.ApiTokenService)4 ClientAuthorizationService (com.gw2auth.oauth2.server.service.client.authorization.ClientAuthorizationService)4 Gw2AuthUser (com.gw2auth.oauth2.server.service.user.Gw2AuthUser)4 java.util (java.util)4 MediaType (org.springframework.http.MediaType)4