mirror of
https://github.com/ysoftdevs/oauth-playground-server.git
synced 2026-01-17 09:07:12 +01:00
refactor tests, introduce TokenEndpointCall
This commit is contained in:
@@ -123,7 +123,8 @@ public class OAuthResource {
|
||||
return switch (params.getGrantType()) {
|
||||
case "authorization_code" -> redeemAuthorizationCode(params);
|
||||
case "urn:ietf:params:oauth:grant-type:device_code" -> redeemDeviceCode(params);
|
||||
default -> throw new OAuthApiException(ErrorResponse.Error.invalid_request, "Unsupported grant type");
|
||||
default ->
|
||||
throw new OAuthApiException(ErrorResponse.Error.unsupported_grant_type, "Unsupported grant type");
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
public record ErrorResponse(@JsonProperty("error") Error error,
|
||||
@JsonProperty("error_description") String description) {
|
||||
public enum Error {
|
||||
invalid_request, unauthorized_client, unsupported_response_type,
|
||||
invalid_request, unauthorized_client, unsupported_response_type, unsupported_grant_type,
|
||||
access_denied, invalid_scope, server_error, temporarily_unavailable, authorization_pending
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ysoft.geecon;
|
||||
|
||||
import com.ysoft.geecon.dto.AccessTokenResponse;
|
||||
import com.ysoft.geecon.dto.OAuthClient;
|
||||
import com.ysoft.geecon.dto.User;
|
||||
import com.ysoft.geecon.error.ErrorResponse;
|
||||
@@ -53,9 +54,9 @@ public class AuthCodeGrantTest {
|
||||
|
||||
assertThat(flow.getCode(), is(notNullValue()));
|
||||
assertThat(flow.getAccessToken(), is(nullValue()));
|
||||
flow.exchangeCode();
|
||||
AccessTokenResponse accessTokenResponse = flow.exchangeCode().expectTokens();
|
||||
|
||||
assertThat(flow.getAccessToken(), is(notNullValue()));
|
||||
assertThat(accessTokenResponse.accessToken(), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -94,9 +95,9 @@ public class AuthCodeGrantTest {
|
||||
|
||||
assertThat(flow.getCode(), is(notNullValue()));
|
||||
assertThat(flow.getAccessToken(), is(nullValue()));
|
||||
flow.exchangeCode();
|
||||
AccessTokenResponse accessTokenResponse = flow.exchangeCode().expectTokens();
|
||||
|
||||
assertThat(flow.getAccessToken(), is(notNullValue()));
|
||||
assertThat(accessTokenResponse.accessToken(), is(notNullValue()));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ysoft.geecon;
|
||||
|
||||
import com.ysoft.geecon.dto.AccessTokenResponse;
|
||||
import com.ysoft.geecon.dto.DeviceResponse;
|
||||
import com.ysoft.geecon.dto.OAuthClient;
|
||||
import com.ysoft.geecon.dto.User;
|
||||
@@ -21,6 +22,7 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@@ -57,7 +59,8 @@ public class DeviceAuthGrantTest {
|
||||
ConsentScreen consentScreen = loginScreen.submitCorrect("bob", "password");
|
||||
consentScreen.submit();
|
||||
|
||||
flow.exchangeDeviceCode();
|
||||
AccessTokenResponse accessTokenResponse = flow.exchangeDeviceCode().expectTokens();
|
||||
assertThat(accessTokenResponse.accessToken(), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -69,10 +72,10 @@ public class DeviceAuthGrantTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceAuthGrant_authorizationPending() throws IOException {
|
||||
public void deviceAuthGrant_authorizationPending() {
|
||||
DeviceAuthorizationGrantFlow flow = new DeviceAuthorizationGrantFlow(deviceUri, CLIENT);
|
||||
flow.start();
|
||||
ErrorResponse errorResponse = flow.exchangeDeviceCodeError();
|
||||
ErrorResponse errorResponse = flow.exchangeDeviceCode().expectError(400);
|
||||
assertThat(errorResponse.error(), is(ErrorResponse.Error.authorization_pending));
|
||||
}
|
||||
}
|
||||
33
src/test/java/com/ysoft/geecon/TokenEndpointTest.java
Normal file
33
src/test/java/com/ysoft/geecon/TokenEndpointTest.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.ysoft.geecon;
|
||||
|
||||
import com.ysoft.geecon.dto.OAuthClient;
|
||||
import com.ysoft.geecon.error.ErrorResponse;
|
||||
import com.ysoft.geecon.helpers.TokenEndpointCall;
|
||||
import com.ysoft.geecon.repo.ClientsRepo;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.inject.Inject;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@QuarkusTest
|
||||
public class TokenEndpointTest {
|
||||
public static final OAuthClient CLIENT = new OAuthClient("deviceclient", "", null, null);
|
||||
@Inject
|
||||
ClientsRepo clientsRepo;
|
||||
|
||||
@BeforeEach
|
||||
void beforeAll() {
|
||||
clientsRepo.register(CLIENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidGrant() {
|
||||
ErrorResponse errorResponse = new TokenEndpointCall(CLIENT).grantType("invalid").expectError(400);
|
||||
assertThat(errorResponse.error(), is(ErrorResponse.Error.unsupported_grant_type));
|
||||
assertThat(errorResponse.description(), is(notNullValue()));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.ysoft.geecon.helpers;
|
||||
|
||||
import com.ysoft.geecon.dto.AccessTokenResponse;
|
||||
import com.ysoft.geecon.dto.OAuthClient;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
@@ -16,8 +15,6 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static io.restassured.http.ContentType.JSON;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@@ -104,31 +101,8 @@ public class AuthorizationCodeFlow {
|
||||
return query;
|
||||
}
|
||||
|
||||
public AccessTokenResponse exchangeCode() {
|
||||
Map<String, String> tokenForm = new HashMap<>();
|
||||
tokenForm.put("grant_type", "authorization_code");
|
||||
tokenForm.put("client_id", client.clientId());
|
||||
tokenForm.put("redirect_uri", client.redirectUri());
|
||||
tokenForm.put("code", code);
|
||||
if (codeVerifier != null) {
|
||||
tokenForm.put("code_verifier", codeVerifier);
|
||||
}
|
||||
|
||||
AccessTokenResponse accessTokenResponse = given()
|
||||
.formParams(tokenForm)
|
||||
.when()
|
||||
.post("/auth/token")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.contentType(JSON)
|
||||
.body("token_type", is("Bearer"))
|
||||
.body("expires_in", is(notNullValue()))
|
||||
.body("access_token", is(notNullValue()))
|
||||
.body("refresh_token", is(notNullValue()))
|
||||
.extract().body().as(AccessTokenResponse.class);
|
||||
accessToken = accessTokenResponse.accessToken();
|
||||
idToken = accessTokenResponse.idToken();
|
||||
return accessTokenResponse;
|
||||
public TokenEndpointCall exchangeCode() {
|
||||
return new TokenEndpointCall(client).authorizationCode(code, codeVerifier);
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.ysoft.geecon.helpers;
|
||||
|
||||
import com.ysoft.geecon.dto.AccessTokenResponse;
|
||||
import com.ysoft.geecon.dto.DeviceResponse;
|
||||
import com.ysoft.geecon.dto.OAuthClient;
|
||||
import com.ysoft.geecon.error.ErrorResponse;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static io.restassured.http.ContentType.JSON;
|
||||
@@ -37,35 +35,7 @@ public class DeviceAuthorizationGrantFlow {
|
||||
return deviceResponse;
|
||||
}
|
||||
|
||||
public AccessTokenResponse exchangeDeviceCode() {
|
||||
return given()
|
||||
.formParam("grant_type", "urn:ietf:params:oauth:grant-type:device_code")
|
||||
.formParam("client_id", client.clientId())
|
||||
.formParam("device_code", deviceResponse.deviceCode())
|
||||
.when()
|
||||
.post("/auth/token")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.contentType(JSON)
|
||||
.body("token_type", is(notNullValue()))
|
||||
.body("expires_in", is(notNullValue()))
|
||||
.body("access_token", is(notNullValue()))
|
||||
.body("refresh_token", is(notNullValue()))
|
||||
.extract().as(AccessTokenResponse.class);
|
||||
}
|
||||
|
||||
public ErrorResponse exchangeDeviceCodeError() {
|
||||
return given()
|
||||
.formParam("grant_type", "urn:ietf:params:oauth:grant-type:device_code")
|
||||
.formParam("client_id", client.clientId())
|
||||
.formParam("device_code", deviceResponse.deviceCode())
|
||||
.when()
|
||||
.post("/auth/token")
|
||||
.then()
|
||||
.statusCode(400)
|
||||
.contentType(JSON)
|
||||
.body("error", is(notNullValue()))
|
||||
.body("error_description", is(notNullValue()))
|
||||
.extract().as(ErrorResponse.class);
|
||||
public TokenEndpointCall exchangeDeviceCode() {
|
||||
return new TokenEndpointCall(client).deviceCode(deviceResponse.deviceCode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ysoft.geecon.helpers;
|
||||
|
||||
import com.ysoft.geecon.dto.AccessTokenResponse;
|
||||
import com.ysoft.geecon.dto.OAuthClient;
|
||||
import com.ysoft.geecon.error.ErrorResponse;
|
||||
import io.restassured.response.ValidatableResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static io.restassured.http.ContentType.JSON;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
|
||||
public class TokenEndpointCall {
|
||||
private final OAuthClient client;
|
||||
private final Map<String, String> tokenForm;
|
||||
|
||||
public TokenEndpointCall(OAuthClient client) {
|
||||
this.client = client;
|
||||
|
||||
tokenForm = new HashMap<>();
|
||||
tokenForm.put("client_id", client.clientId());
|
||||
}
|
||||
|
||||
public TokenEndpointCall authorizationCode(String code, String codeVerifier) {
|
||||
tokenForm.put("grant_type", "authorization_code");
|
||||
tokenForm.put("redirect_uri", client.redirectUri());
|
||||
tokenForm.put("code", code);
|
||||
if (codeVerifier != null) {
|
||||
tokenForm.put("code_verifier", codeVerifier);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TokenEndpointCall deviceCode(String deviceCode) {
|
||||
tokenForm.put("grant_type", "urn:ietf:params:oauth:grant-type:device_code");
|
||||
tokenForm.put("device_code", deviceCode);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TokenEndpointCall grantType(String grantType) {
|
||||
tokenForm.put("grant_type", grantType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccessTokenResponse expectTokens() {
|
||||
return expect()
|
||||
.statusCode(200)
|
||||
.body("token_type", is("Bearer"))
|
||||
.body("expires_in", is(notNullValue()))
|
||||
.body("access_token", is(notNullValue()))
|
||||
.body("refresh_token", is(notNullValue()))
|
||||
.extract().body().as(AccessTokenResponse.class);
|
||||
}
|
||||
|
||||
public ErrorResponse expectError(int status) {
|
||||
return expect()
|
||||
.statusCode(status)
|
||||
.body("error", is(notNullValue()))
|
||||
.body("error_description", is(notNullValue()))
|
||||
.extract().body().as(ErrorResponse.class);
|
||||
}
|
||||
|
||||
private ValidatableResponse expect() {
|
||||
return given()
|
||||
.formParams(tokenForm)
|
||||
.when()
|
||||
.post("/auth/token")
|
||||
.then()
|
||||
.contentType(JSON);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user