Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ public String validateHolderAccessToken(OID4VCTestContext ctx, AccessTokenRespon
*/
public class AuthorizationEndpointRequest {

protected final LoginUrlBuilder loginForm;
private final LoginUrlBuilder loginForm;

public AuthorizationEndpointRequest() {
this.loginForm = oauth.loginForm();
Expand Down Expand Up @@ -555,11 +555,7 @@ public void openLoginForm() {
}

public AuthorizationEndpointResponse send(String username, String password) {
// [TODO #47649] OAuthClient cannot handle invalid authorization requests
// https://github.com/keycloak/keycloak/issues/47649
openLoginForm();
oauth.fillLoginForm(username, password);
return oauth.parseLoginResponse();
return loginForm.doLogin(username, password);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,12 @@

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.NoSuchElementException;

import static org.keycloak.OID4VCConstants.OPENID_CREDENTIAL;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;


/**
Expand Down Expand Up @@ -104,7 +101,7 @@ public void testCredentialFromPublicClient() throws Exception {
}

@Test
public void testAuthorizationRequestSuccess() throws Exception {
public void testAuthorizationRequestSuccess() {

var ctx = new OID4VCTestContext(pubClient, jwtTypeCredentialScope);

Expand All @@ -121,24 +118,18 @@ public void testAuthorizationRequestSuccess() throws Exception {
}

@Test
public void testAuthorizationRequestNoPkce() throws Exception {
public void testAuthorizationRequestNoPkce() {

var ctx = new OID4VCTestContext(pubClient, jwtTypeCredentialScope);

// Send AuthorizationRequest without required PKCE
//
NoSuchElementException ex = assertThrows(NoSuchElementException.class, () -> wallet
.authorizationRequest()
.scope(ctx.getScope())
.send(ctx.getHolder(), TEST_PASSWORD));

assertNotNull(ex.getMessage(), "No error message");
assertTrue(ex.getMessage().contains("Unable to locate element with ID: 'username'"), ex.getMessage());
oauth.loginForm().scope(ctx.getScope()).open();
AuthorizationEndpointResponse authResponse = oauth.parseLoginResponse();

// [TODO #47649] OAuthClient cannot handle invalid authorization requests
// https://github.com/keycloak/keycloak/issues/47649
// assertEquals("invalid_request", authResponse.getError());
// assertEquals("Missing parameter: code_challenge_method", authResponse.getErrorDescription());
assertNull(authResponse.getCode(), "Expected no auth code");
assertEquals("invalid_request", authResponse.getError());
assertEquals("Missing parameter: code_challenge_method", authResponse.getErrorDescription());
}

// Private ---------------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,13 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.NoSuchElementException;

import static org.keycloak.OID4VCConstants.OPENID_CREDENTIAL;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
Expand Down Expand Up @@ -562,11 +560,16 @@ public void testMismatchedCredentialConfigurationId() throws Exception {
CredentialIssuer issuer = wallet.getIssuerMetadata(ctx);

OID4VCAuthorizationDetail authDetail = createAuthorizationDetail(issuer, "unknown-credential-config-id");
NoSuchElementException ex = assertThrows(NoSuchElementException.class, () -> performAuthorizationCodeLoginWithAuthorizationDetails(authDetail));
wallet.authorizationRequest()
.scope(ctx.getScope())
.authorizationDetails(authDetail)
.openLoginForm();
AuthorizationEndpointResponse authResponse = oauth.parseLoginResponse();
assertEquals("invalid_request", authResponse.getError());

// [TODO #47649] OAuthClient cannot handle invalid authorization requests
assertNotNull(ex.getMessage(), "No error message");
assertTrue(ex.getMessage().contains("Unable to locate element with ID: 'username'"), ex.getMessage());
String errorDescription = authResponse.getErrorDescription();
assertNotNull(errorDescription, "No error message");
assertTrue(errorDescription.contains("Invalid authorization_details: Invalid credential configuration"), errorDescription);
}

/** Token exchange without redirect_uri must fail. */
Expand Down Expand Up @@ -686,14 +689,16 @@ public void testTokenExchangeWithoutClientId() throws Exception {
@Test
public void testTokenExchangeWithMalformedAuthorizationDetails() {

NoSuchElementException ex = assertThrows(NoSuchElementException.class, () -> oauth.loginForm()
oauth.loginForm()
.scope(ctx.getScope())
.param(OAuth2Constants.AUTHORIZATION_DETAILS, "invalid-json")
.doLogin(TEST_USER, TEST_PASSWORD));
.open();
AuthorizationEndpointResponse authResponse = oauth.parseLoginResponse();
assertEquals("invalid_request", authResponse.getError());

// [TODO #47649] OAuthClient cannot handle invalid authorization requests
assertNotNull(ex.getMessage(), "No error message");
assertTrue(ex.getMessage().contains("Unable to locate element with ID: 'username'"), ex.getMessage());
String errorDescription = authResponse.getErrorDescription();
assertNotNull(errorDescription, "No error description");
assertTrue(errorDescription.contains("Invalid authorization_details: invalid-json"), errorDescription);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.NoSuchElementException;

import static org.keycloak.OID4VCConstants.OPENID_CREDENTIAL;
import static org.keycloak.models.oid4vci.CredentialScopeModel.VC_IDENTIFIER;
Expand Down Expand Up @@ -109,14 +108,9 @@ public void testAuthorizationDetails_WithInvalidCredentialIdentifiers() {

ctx.putAttachment(ON_AUTH_REQUEST_ATTACHMENT_KEY, true);

// [TODO #47649] OAuthClient cannot handle invalid authorization requests
// https://github.com/keycloak/keycloak/issues/47649
assertThrows(NoSuchElementException.class, () ->
IllegalStateException ex = assertThrows(IllegalStateException.class, () ->
runAuthorizationDetailsTest(ctx, credIdentifier, () -> authDetail, null, null, null));

// IllegalStateException ex = assertThrows(IllegalStateException.class, () ->
// runAuthorizationDetailsTest(ctx, credIdentifier, () -> authDetail, null, null, null));
// assertTrue(ex.getMessage().contains("Found invalid credential_identifiers in authorization_details"), "Unexpected - " + ex.getMessage());
assertTrue(ex.getMessage().contains("Invalid authorization_details: credential_identifiers not allowed"), ex.getMessage());
}

@Test
Expand Down Expand Up @@ -197,9 +191,13 @@ private void runAuthorizationDetailsTest(
}

try {
AuthorizationEndpointResponse authResponse = authRequestSupplier.get()
.send(ctx.getHolder(), TEST_PASSWORD);

AuthorizationEndpointRequest authRequest = authRequestSupplier.get();
authRequest.openLoginForm();
String currUrl = oauth.getDriver().getCurrentUrl();
if (currUrl != null && !currUrl.contains("error=") && !currUrl.contains("error_description=")) {
oauth.fillLoginForm(ctx.getHolder(), TEST_PASSWORD);
}
AuthorizationEndpointResponse authResponse = oauth.parseLoginResponse();
if (authResponse.getError() != null)
throw new IllegalStateException(authResponse.getErrorDescription());

Expand Down Expand Up @@ -243,8 +241,10 @@ private void runAuthorizationDetailsTest(
verifyCredentialStructure(credentialObj);

} finally {
// Needed, because we don't go through wallet.authorizationRequest().send()
wallet.logout(ctx.getHolder());

// Restore the vc.credential_identifier attribute value
//
if (!wasCredentialIdentifier.equals(credIdentifier)) {
setCredentialScopeAttributes(ctx.getCredentialScope(), Map.of(VC_IDENTIFIER, wasCredentialIdentifier));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,20 @@
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse;
import org.keycloak.testsuite.util.oauth.OpenIDProviderConfigurationResponse;
import org.keycloak.testsuite.util.oauth.ParResponse;
import org.keycloak.testsuite.util.oauth.oid4vc.CredentialIssuerMetadataResponse;
import org.keycloak.testsuite.util.oauth.oid4vc.Oid4vcCredentialResponse;

import org.apache.http.HttpStatus;
import org.junit.Test;
import org.openqa.selenium.TimeoutException;

import static org.keycloak.OID4VCConstants.OPENID_CREDENTIAL;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
Expand Down Expand Up @@ -233,12 +232,12 @@ public void testAuthorizationCodeFlowWithPARAndAuthorizationDetailsFailure() thr
// Step 2: Perform authorization with PAR
oauth.client(clientId);
oauth.scope(getCredentialClientScope().getName());
TimeoutException ex = assertThrows(TimeoutException.class, () ->
oauth.loginForm().requestUri(requestUri).doLogin("john", "password"));
oauth.loginForm().requestUri(requestUri).open();
AuthorizationEndpointResponse authResponse = oauth.parseLoginResponse();

// [TODO #47649] OAuthClient cannot handle invalid authorization requests
assertNotNull("No error message", ex.getMessage());
assertTrue(ex.getMessage().contains("waiting for element Proxy element for: DefaultElementLocator 'By.id: username' to be present"), ex.getMessage());
// Should fail because authorization_details from PAR request cannot be processed
String errorDescription = authResponse.getErrorDescription();
assertTrue(errorDescription != null && errorDescription.contains("Invalid authorization_details"), "Error message should indicate authorization_details processing failure");
}

@Test
Expand Down
Loading