Skip to content
Draft
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
1 change: 1 addition & 0 deletions common/src/main/java/org/keycloak/common/Profile.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ public enum Feature {

OID4VC_VCI("Support for the OID4VCI protocol as part of OID4VC.", Type.EXPERIMENTAL),
OID4VC_VCI_PREAUTH_CODE("Support for credential offers with `pre-authorized_code` grant.", Type.EXPERIMENTAL, OID4VC_VCI),
OID4VC_HAIP("OpenID4VC High Assurance Interoperability Profile 1.0", Type.EXPERIMENTAL, OID4VC_VCI),

OPENTELEMETRY("OpenTelemetry support", Type.DEFAULT),
OPENTELEMETRY_LOGS("OpenTelemetry Logs support", Type.PREVIEW, OPENTELEMETRY),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public interface Details {
String ACTION = "action";
String CODE_ID = "code_id";
String REDIRECT_URI = "redirect_uri";
String REQUEST_URI = "request_uri";
String RESPONSE_TYPE = "response_type";
String RESPONSE_MODE = "response_mode";
String GRANT_TYPE = "grant_type";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import jakarta.ws.rs.core.MultivaluedHashMap;
Expand Down Expand Up @@ -59,6 +60,9 @@
import org.keycloak.protocol.LoginProtocol.Error;
import org.keycloak.protocol.RestartLoginCookie;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.protocol.oidc.endpoints.request.AuthorizationEndpointRequestParserProcessor;
import org.keycloak.protocol.oidc.endpoints.request.RequestUriType;
import org.keycloak.protocol.oidc.par.endpoints.request.AuthzEndpointParParser;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.ErrorPageException;
import org.keycloak.services.ServicesLogger;
Expand Down Expand Up @@ -1239,10 +1243,23 @@ protected Response authenticationComplete() {

String nextRequiredAction = nextRequiredAction();
if (nextRequiredAction != null) {
return AuthenticationManager.redirectToRequiredActions(session, realm, authenticationSession, uriInfo, nextRequiredAction);
Response response = AuthenticationManager.redirectToRequiredActions(session, realm, authenticationSession, uriInfo, nextRequiredAction);
return response;
} else {
event.detail(Details.CODE_ID, authenticationSession.getParentSession().getId()); // todo This should be set elsewhere. find out why tests fail. Don't know where this is supposed to be set
return AuthenticationManager.finishedRequiredActions(session, authenticationSession, userSession, connection, request, uriInfo, event);
Response response = AuthenticationManager.finishedRequiredActions(session, authenticationSession, userSession, connection, request, uriInfo, event);

// Authorization servers that enforce one-time use of request_uri values do so at the point of authorization,
// not at the point of visiting the authorization endpoint
String requestUri = authenticationSession.getAuthNote(Details.REQUEST_URI);
RequestUriType requestUriType = Optional.ofNullable(requestUri)
.map(AuthorizationEndpointRequestParserProcessor::getRequestUriType)
.orElse(null);
if (requestUriType == RequestUriType.PAR) {
AuthzEndpointParParser.removeRequestObject(session, requestUri);
}

return response;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.ClientData;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.oidc.endpoints.AuthorizationCheckException;
import org.keycloak.protocol.oidc.endpoints.AuthorizationEndpointChecker;
import org.keycloak.protocol.oidc.endpoints.request.AuthorizationEndpointRequest;
import org.keycloak.protocol.oidc.utils.LogoutUtil;
Expand All @@ -57,6 +58,7 @@
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.adapters.action.PushNotBeforeAction;
import org.keycloak.representations.idm.OAuth2ErrorRepresentation;
import org.keycloak.services.ErrorPageException;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.Urls;
import org.keycloak.services.clientpolicy.ClientPolicyException;
Expand Down Expand Up @@ -436,8 +438,8 @@ public Response sendError(ClientModel client, ClientData clientData, Error error
try {
checker.checkResponseType();
checker.checkRedirectUri();
} catch (AuthorizationEndpointChecker.AuthorizationCheckException ex) {
ex.throwAsErrorPageException(null);
} catch (AuthorizationCheckException ex) {
throw new ErrorPageException(session, ex.getError(), ex.getStatus(), ex.getErrorMessage(), ex.getParameters());
}

setupResponseTypeAndMode(clientData.getResponseType(), clientData.getResponseMode());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.keycloak.protocol.oidc.endpoints;

import java.text.MessageFormat;

import jakarta.ws.rs.core.Response;

// Exception propagated to the caller, which will allow caller to send proper error response based on the context (Browser OIDC Authorization Endpoint, PAR etc)
public class AuthorizationCheckException extends Exception {

private final Response.Status status;
private final String error;
private final String errorMessage;
private final Object[] parameters;

public AuthorizationCheckException(Response.Status status, String error, String errorDescription) {
this(error, status, errorDescription);
}

public AuthorizationCheckException(String error, Response.Status status, String errorMessage, Object... params) {
this.status = status;
this.error = error;
this.errorMessage = errorMessage;
this.parameters = params;
}

public Response.Status getStatus() {
return status;
}

public String getError() {
return error;
}

public String getErrorDescription() {
String errorDescription = errorMessage;
if (parameters.length > 0) {
errorDescription = MessageFormat.format(errorMessage, parameters);
}
return errorDescription;
}

public String getErrorMessage() {
return errorMessage;
}

public Object[] getParameters() {
return parameters;
}
}
Loading
Loading