mirror of
https://github.com/ysoftdevs/oauth-playground-server.git
synced 2026-04-01 14:53:16 +02:00
'state' is optional
This commit is contained in:
@@ -10,7 +10,6 @@ import com.ysoft.geecon.repo.SessionsRepo;
|
|||||||
import com.ysoft.geecon.repo.UsersRepo;
|
import com.ysoft.geecon.repo.UsersRepo;
|
||||||
import io.quarkus.qute.CheckedTemplate;
|
import io.quarkus.qute.CheckedTemplate;
|
||||||
import io.quarkus.qute.TemplateInstance;
|
import io.quarkus.qute.TemplateInstance;
|
||||||
import io.quarkus.runtime.util.StringUtil;
|
|
||||||
import io.quarkus.security.webauthn.WebAuthnLoginResponse;
|
import io.quarkus.security.webauthn.WebAuthnLoginResponse;
|
||||||
import io.quarkus.security.webauthn.WebAuthnRegisterResponse;
|
import io.quarkus.security.webauthn.WebAuthnRegisterResponse;
|
||||||
import io.quarkus.security.webauthn.WebAuthnSecurity;
|
import io.quarkus.security.webauthn.WebAuthnSecurity;
|
||||||
@@ -153,9 +152,11 @@ public class OAuthResource {
|
|||||||
var responseTypes = session.params().getResponseTypes();
|
var responseTypes = session.params().getResponseTypes();
|
||||||
|
|
||||||
UriBuilder uri = UriBuilder.fromUri(redirectUri)
|
UriBuilder uri = UriBuilder.fromUri(redirectUri)
|
||||||
.fragment("")
|
.fragment("");
|
||||||
.queryParam("state", session.params().getState());
|
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(session.params().getState())) {
|
||||||
|
uri.queryParam("state", session.params().getState());
|
||||||
|
}
|
||||||
if (responseTypes.contains(AuthParams.ResponseType.code)) {
|
if (responseTypes.contains(AuthParams.ResponseType.code)) {
|
||||||
uri.queryParam("code", sessionsRepo.generateAuthorizationCode(sessionId));
|
uri.queryParam("code", sessionsRepo.generateAuthorizationCode(sessionId));
|
||||||
}
|
}
|
||||||
@@ -263,9 +264,10 @@ public class OAuthResource {
|
|||||||
// must NOT redirect to invalid redirect URI
|
// must NOT redirect to invalid redirect URI
|
||||||
throw new OAuthUserVisibleException(ErrorResponse.Error.invalid_request, "Invalid redirect URI");
|
throw new OAuthUserVisibleException(ErrorResponse.Error.invalid_request, "Invalid redirect URI");
|
||||||
}
|
}
|
||||||
if (StringUtil.isNullOrEmpty(params.getState())) {
|
// state is optional
|
||||||
throw new OAuthRedirectException(params, ErrorResponse.Error.invalid_request, "Missing state");
|
// if (StringUtil.isNullOrEmpty(params.getState())) {
|
||||||
}
|
// throw new OAuthRedirectException(params, ErrorResponse.Error.invalid_request, "Missing state");
|
||||||
|
// }
|
||||||
if (!params.validateResponseType()) {
|
if (!params.validateResponseType()) {
|
||||||
throw new OAuthRedirectException(params, ErrorResponse.Error.unsupported_response_type,
|
throw new OAuthRedirectException(params, ErrorResponse.Error.unsupported_response_type,
|
||||||
"Unsupported response type");
|
"Unsupported response type");
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.ysoft.geecon.error;
|
|||||||
import com.ysoft.geecon.dto.AuthParams;
|
import com.ysoft.geecon.dto.AuthParams;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
import jakarta.ws.rs.core.UriBuilder;
|
import jakarta.ws.rs.core.UriBuilder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
public class OAuthRedirectException extends OAuthApiException {
|
public class OAuthRedirectException extends OAuthApiException {
|
||||||
private final AuthParams authParams;
|
private final AuthParams authParams;
|
||||||
@@ -19,9 +20,11 @@ public class OAuthRedirectException extends OAuthApiException {
|
|||||||
public Response getResponse() {
|
public Response getResponse() {
|
||||||
UriBuilder uri = UriBuilder.fromUri(authParams.getRedirectUri())
|
UriBuilder uri = UriBuilder.fromUri(authParams.getRedirectUri())
|
||||||
.fragment("")
|
.fragment("")
|
||||||
.queryParam("state", authParams.getState())
|
|
||||||
.queryParam("error", response.error())
|
.queryParam("error", response.error())
|
||||||
.queryParam("error_description", response.description());
|
.queryParam("error_description", response.description());
|
||||||
|
if (StringUtils.isNotBlank(authParams.getState())) {
|
||||||
|
uri.queryParam("state", authParams.getState());
|
||||||
|
}
|
||||||
return Response.seeOther(uri.build()).build();
|
return Response.seeOther(uri.build()).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,26 @@ public class AuthCodeGrantTest {
|
|||||||
assertThat(accessTokenResponse.accessToken(), is(notNullValue()));
|
assertThat(accessTokenResponse.accessToken(), is(notNullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authCodeGrant_stateIsOptional() throws IOException {
|
||||||
|
AuthorizationCodeFlow flow = new AuthorizationCodeFlow(authUrl, CLIENT)
|
||||||
|
.state(null)
|
||||||
|
.scope("scope1 scope2");
|
||||||
|
LoginScreen loginScreen = flow.start().expectLogin();
|
||||||
|
|
||||||
|
ConsentScreen consentScreen = loginScreen.submit("bob", "password").expectSuccess();
|
||||||
|
assertThat(consentScreen.getScopes(), is(List.of("scope1", "scope2")));
|
||||||
|
|
||||||
|
Document submit = consentScreen.submit();
|
||||||
|
flow.expectSuccessfulRedirect(submit.connection().response());
|
||||||
|
|
||||||
|
assertThat(flow.getCode(), is(notNullValue()));
|
||||||
|
assertThat(flow.getAccessToken(), is(nullValue()));
|
||||||
|
AccessTokenResponse accessTokenResponse = flow.exchangeCode().expectTokens();
|
||||||
|
|
||||||
|
assertThat(accessTokenResponse.accessToken(), is(notNullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void badCredentials() throws IOException {
|
public void badCredentials() throws IOException {
|
||||||
AuthorizationCodeFlow flow = new AuthorizationCodeFlow(authUrl, CLIENT)
|
AuthorizationCodeFlow flow = new AuthorizationCodeFlow(authUrl, CLIENT)
|
||||||
|
|||||||
@@ -37,7 +37,11 @@ public class AuthorizationCodeFlow {
|
|||||||
query = new HashMap<>();
|
query = new HashMap<>();
|
||||||
query.put("client_id", client.clientId());
|
query.put("client_id", client.clientId());
|
||||||
query.put("redirect_uri", client.redirectUris().get(0));
|
query.put("redirect_uri", client.redirectUris().get(0));
|
||||||
query.put("state", state);
|
}
|
||||||
|
|
||||||
|
public AuthorizationCodeFlow state(String state) {
|
||||||
|
this.state = state;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthorizationCodeFlow param(String key, String value) {
|
public AuthorizationCodeFlow param(String key, String value) {
|
||||||
@@ -46,6 +50,10 @@ public class AuthorizationCodeFlow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Result start() throws IOException {
|
public Result start() throws IOException {
|
||||||
|
if (state != null) {
|
||||||
|
query.put("state", state);
|
||||||
|
}
|
||||||
|
|
||||||
Document document = Jsoup.connect(authUrl)
|
Document document = Jsoup.connect(authUrl)
|
||||||
.followRedirects(false)
|
.followRedirects(false)
|
||||||
.data(query)
|
.data(query)
|
||||||
|
|||||||
Reference in New Issue
Block a user