From 2d876d31c543cf2c544f367a0b89e1b356586089 Mon Sep 17 00:00:00 2001
From: Felix <23635466+its-felix@users.noreply.github.com>
Date: Fri, 8 Nov 2024 23:12:18 +0100
Subject: [PATCH] feat: switch to accesstoken via query
---
pom.xml | 2 +-
.../server/service/gw2/Gw2ApiService.java | 1 +
.../server/service/gw2/Gw2ApiServiceImpl.java | 7 ++++
.../oauth2/server/RequestMatchers.java | 32 +++++++++++++++++++
.../server/oauth2/OAuth2ServerTest.java | 10 +++---
.../Gw2AccountApiTokenServiceImplTest.java | 9 +++---
.../VerificationControllerTest.java | 11 ++++---
7 files changed, 57 insertions(+), 15 deletions(-)
create mode 100644 src/test/java/com/gw2auth/oauth2/server/RequestMatchers.java
diff --git a/pom.xml b/pom.xml
index e1be4c92..e9184d65 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.gw2auth
oauth2-server
- 1.88.0
+ 1.89.0
jar
diff --git a/src/main/java/com/gw2auth/oauth2/server/service/gw2/Gw2ApiService.java b/src/main/java/com/gw2auth/oauth2/server/service/gw2/Gw2ApiService.java
index 62378087..fc921345 100644
--- a/src/main/java/com/gw2auth/oauth2/server/service/gw2/Gw2ApiService.java
+++ b/src/main/java/com/gw2auth/oauth2/server/service/gw2/Gw2ApiService.java
@@ -12,6 +12,7 @@ public interface Gw2ApiService {
String API_VERSION_PARAM = "v";
String API_VERSION = "2021-07-15T13:00:00.000Z";
+ String ACCESS_TOKEN_PARAM = "access_token";
Gw2TokenInfo getTokenInfo(String gw2ApiToken);
diff --git a/src/main/java/com/gw2auth/oauth2/server/service/gw2/Gw2ApiServiceImpl.java b/src/main/java/com/gw2auth/oauth2/server/service/gw2/Gw2ApiServiceImpl.java
index b79302e3..cc51d5e2 100644
--- a/src/main/java/com/gw2auth/oauth2/server/service/gw2/Gw2ApiServiceImpl.java
+++ b/src/main/java/com/gw2auth/oauth2/server/service/gw2/Gw2ApiServiceImpl.java
@@ -133,6 +133,10 @@ private T getFromAPI(String url, MultiValueMap query, String
query = new LinkedMultiValueMap<>(query);
query.set(API_VERSION_PARAM, API_VERSION);
+ if (token != null) {
+ query.set(ACCESS_TOKEN_PARAM, token);
+ }
+
final Long timeoutAt = Optional.ofNullable(TIMEOUT_AT_TL.get()).map(Deque::peekLast).orElse(null);
ResponseEntity response;
@@ -179,6 +183,7 @@ private T getFromAPI(String url, MultiValueMap query, String
}
private static HttpHeaders buildRequestHeaders(String token) {
+ /*
if (token == null) {
return HttpHeaders.EMPTY;
}
@@ -187,6 +192,8 @@ private static HttpHeaders buildRequestHeaders(String token) {
headers.add("Authorization", "Bearer " + token);
return headers;
+ */
+ return HttpHeaders.EMPTY;
}
private static boolean validateToken(String token) {
diff --git a/src/test/java/com/gw2auth/oauth2/server/RequestMatchers.java b/src/test/java/com/gw2auth/oauth2/server/RequestMatchers.java
new file mode 100644
index 00000000..17d7e4de
--- /dev/null
+++ b/src/test/java/com/gw2auth/oauth2/server/RequestMatchers.java
@@ -0,0 +1,32 @@
+package com.gw2auth.oauth2.server;
+
+import org.hamcrest.core.IsAnything;
+import org.hamcrest.core.IsEqual;
+import org.springframework.http.client.ClientHttpRequest;
+import org.springframework.test.web.client.RequestMatcher;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.util.Optional;
+
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.queryParam;
+
+public final class RequestMatchers {
+
+ public static RequestMatcher matchAuthorizedRequest() {
+ return queryParam("access_token", new IsAnything<>());
+ }
+
+ public static RequestMatcher matchAuthorizedRequest(String accessToken) {
+ return queryParam("access_token", new IsEqual<>(accessToken));
+ }
+
+ public static Optional extractAccessToken(ClientHttpRequest request) {
+ final String token = UriComponentsBuilder.fromUri(request.getURI())
+ .build()
+ .getQueryParams()
+ .getFirst("access_token");
+
+ return Optional.ofNullable(token);
+ }
+}
diff --git a/src/test/java/com/gw2auth/oauth2/server/oauth2/OAuth2ServerTest.java b/src/test/java/com/gw2auth/oauth2/server/oauth2/OAuth2ServerTest.java
index 7eb01ca1..18da959a 100644
--- a/src/test/java/com/gw2auth/oauth2/server/oauth2/OAuth2ServerTest.java
+++ b/src/test/java/com/gw2auth/oauth2/server/oauth2/OAuth2ServerTest.java
@@ -79,6 +79,8 @@
import static com.gw2auth.oauth2.server.Assertions.assertInstantEquals;
import static com.gw2auth.oauth2.server.Matchers.*;
+import static com.gw2auth.oauth2.server.RequestMatchers.extractAccessToken;
+import static com.gw2auth.oauth2.server.RequestMatchers.matchAuthorizedRequest;
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.client.ExpectedCount.times;
@@ -1299,11 +1301,11 @@ public void consentSubmitWithUnexpectedGW2APIException(SessionHandle sessionHand
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(matchAuthorizedRequest())
.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 gw2ApiToken = extractAccessToken(request).orElseThrow();
final String subtoken;
if (gw2ApiToken.equals(tokenA)) {
@@ -2469,11 +2471,11 @@ private void prepareGw2RestServerForCreateSubToken(Map subtokenB
if (!subtokenByGw2ApiToken.isEmpty()) {
this.gw2RestServer.expect(times(subtokenByGw2ApiToken.size()), requestTo(new StringStartsWith("/v2/createsubtoken")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", new StringStartsWith("Bearer ")))
+ .andExpect(matchAuthorizedRequest())
.andExpect(queryParam("permissions", split(",", containingAll(expectedGw2ApiPermissionStrs))))
.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 gw2ApiToken = extractAccessToken(request).orElseThrow();
final String subtoken = subtokenByGw2ApiToken.get(gw2ApiToken);
if (subtoken == null || subtoken.isEmpty()) {
diff --git a/src/test/java/com/gw2auth/oauth2/server/service/gw2account/apitoken/Gw2AccountApiTokenServiceImplTest.java b/src/test/java/com/gw2auth/oauth2/server/service/gw2account/apitoken/Gw2AccountApiTokenServiceImplTest.java
index 7458bd71..322d742a 100644
--- a/src/test/java/com/gw2auth/oauth2/server/service/gw2account/apitoken/Gw2AccountApiTokenServiceImplTest.java
+++ b/src/test/java/com/gw2auth/oauth2/server/service/gw2account/apitoken/Gw2AccountApiTokenServiceImplTest.java
@@ -6,7 +6,6 @@
import com.gw2auth.oauth2.server.repository.gw2account.apitoken.Gw2AccountApiTokenEntity;
import com.gw2auth.oauth2.server.repository.gw2account.apitoken.Gw2AccountApiTokenRepository;
import com.gw2auth.oauth2.server.service.Gw2ApiPermission;
-import org.hamcrest.core.IsEqual;
import org.hamcrest.core.StringStartsWith;
import org.json.JSONObject;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -20,7 +19,6 @@
import org.springframework.http.MediaType;
import org.springframework.mock.http.client.MockClientHttpResponse;
import org.springframework.test.web.client.MockRestServiceServer;
-import org.springframework.test.web.client.match.MockRestRequestMatchers;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
@@ -32,6 +30,7 @@
import java.util.UUID;
import static com.gw2auth.oauth2.server.Assertions.assertInstantEquals;
+import static com.gw2auth.oauth2.server.RequestMatchers.matchAuthorizedRequest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.test.web.client.ExpectedCount.times;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
@@ -95,7 +94,7 @@ public void checkTokenValidityWithUpdatedGw2AccountNames(SessionHandle sessionHa
// prepare the mock server for the upcoming account request
this.gw2RestServer.expect(times(1), requestTo(new StringStartsWith("/v2/account")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", new IsEqual<>("Bearer " + gw2ApiToken)))
+ .andExpect(matchAuthorizedRequest(gw2ApiToken))
.andRespond((request) -> {
final JSONObject responseJson = new JSONObject(Map.of(
"id", gw2AccountId.toString(),
@@ -153,7 +152,7 @@ public void checkTokenValidityWithFailingGw2ApiRequest(SessionHandle sessionHand
// prepare the mock server for the upcoming account request
this.gw2RestServer.expect(times(1), requestTo(new StringStartsWith("/v2/account")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", new IsEqual<>("Bearer " + gw2ApiToken)))
+ .andExpect(matchAuthorizedRequest(gw2ApiToken))
.andRespond((request) -> {
final MockClientHttpResponse response = new MockClientHttpResponse(
"{}".getBytes(StandardCharsets.UTF_8),
@@ -207,7 +206,7 @@ public void checkTokenValidityWithInvalidApiToken(SessionHandle sessionHandle) {
// prepare the mock server for the upcoming account request
this.gw2RestServer.expect(times(1), requestTo(new StringStartsWith("/v2/account")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", new IsEqual<>("Bearer " + gw2ApiToken)))
+ .andExpect(matchAuthorizedRequest(gw2ApiToken))
.andRespond((request) -> {
final MockClientHttpResponse response = new MockClientHttpResponse(
"{}".getBytes(StandardCharsets.UTF_8),
diff --git a/src/test/java/com/gw2auth/oauth2/server/web/verification/VerificationControllerTest.java b/src/test/java/com/gw2auth/oauth2/server/web/verification/VerificationControllerTest.java
index 4b97a75c..6238ef99 100644
--- a/src/test/java/com/gw2auth/oauth2/server/web/verification/VerificationControllerTest.java
+++ b/src/test/java/com/gw2auth/oauth2/server/web/verification/VerificationControllerTest.java
@@ -37,6 +37,7 @@
import java.util.stream.Collectors;
import static com.gw2auth.oauth2.server.Matchers.*;
+import static com.gw2auth.oauth2.server.RequestMatchers.matchAuthorizedRequest;
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.client.ExpectedCount.max;
@@ -769,7 +770,7 @@ public void startSubmitAndCancelChallenge(SessionHandle sessionHandle) throws Ex
private void prepareGw2RestServerForTransactionsRequest(String gw2ApiToken, int addDummyValues, int itemId, int quantity, long price, Instant created) {
this.gw2RestServer.expect(requestTo(new StringStartsWith("/v2/commerce/transactions/current/buys")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", "Bearer " + gw2ApiToken))
+ .andExpect(matchAuthorizedRequest(gw2ApiToken))
.andRespond((request) -> {
final org.json.JSONArray result = new org.json.JSONArray();
@@ -801,7 +802,7 @@ private void prepareGw2RestServerForTransactionsRequest(String gw2ApiToken, int
private void prepareGw2RestServerForTokenInfoRequest(String gw2ApiToken, String apiTokenName, Set gw2ApiPermissions) {
this.gw2RestServer.expect(requestTo(new StringStartsWith("/v2/tokeninfo")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", "Bearer " + gw2ApiToken))
+ .andExpect(matchAuthorizedRequest(gw2ApiToken))
.andRespond((request) -> {
final MockClientHttpResponse response = new MockClientHttpResponse(new JSONObject(Map.of(
"name", apiTokenName,
@@ -825,7 +826,7 @@ private void prepareGw2RestServerForCharactersRequest(String gw2ApiToken, int ad
this.gw2RestServer.expect(requestTo(new StringStartsWith("/v2/characters")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", "Bearer " + gw2ApiToken))
+ .andExpect(matchAuthorizedRequest(gw2ApiToken))
.andRespond((request) -> {
final MockClientHttpResponse response = new MockClientHttpResponse(new JSONArray(characters).toString().getBytes(StandardCharsets.UTF_8), HttpStatus.OK);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
@@ -837,7 +838,7 @@ private void prepareGw2RestServerForCharactersRequest(String gw2ApiToken, int ad
private void preparedGw2RestServerForCreateSubtoken(String gw2ApiToken, String gw2ApiSubtoken, Set requestPermissions, Instant expire) {
this.gw2RestServer.expect(requestTo(new StringStartsWith("/v2/createsubtoken")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", "Bearer " + gw2ApiToken))
+ .andExpect(matchAuthorizedRequest(gw2ApiToken))
.andExpect(queryParam("permissions", split(",", containingAll(requestPermissions.stream().map(Gw2ApiPermission::gw2).toArray(String[]::new)))))
.andExpect(queryParam("expire", asInstant(instant(expire))))
.andRespond((request) -> {
@@ -851,7 +852,7 @@ private void preparedGw2RestServerForCreateSubtoken(String gw2ApiToken, String g
private void preparedGw2RestServerForAccountRequest(UUID gw2AccountId, String gw2ApiToken) {
this.gw2RestServer.expect(max(2), requestTo(new StringStartsWith("/v2/account")))
.andExpect(method(HttpMethod.GET))
- .andExpect(MockRestRequestMatchers.header("Authorization", "Bearer " + gw2ApiToken))
+ .andExpect(matchAuthorizedRequest(gw2ApiToken))
.andRespond((request) -> {
final MockClientHttpResponse response = new MockClientHttpResponse(new JSONObject(Map.of(
"id", gw2AccountId,