001package com.nimbusds.openid.connect.provider.spi.par; 002 003 004import net.jcip.annotations.ThreadSafe; 005 006import com.nimbusds.oauth2.sdk.AuthorizationRequest; 007import com.nimbusds.oauth2.sdk.GeneralException; 008import com.nimbusds.openid.connect.provider.spi.Lifecycle; 009 010 011/** 012 * Service Provider Interface (SPI) for performing additional validation of 013 * Pushed Authorisation Requests (PAR). 014 * 015 * <p>The {@link #validatePushedAuthorizationRequest} method will be called 016 * after the Connect2id server has performed standard validation of the OAuth 017 * 2.0 authorisation / OpenID authentication request, such as checking the 018 * {@code client_id} and ensuring the client is authorised to use the OAuth 2.0 019 * grant. JWT-secured authorisation requests (JAR) will be unwrapped / resolved 020 * before that. The original raw request can be obtained from the 021 * {@link ValidatorContext#getRawRequest() context}. 022 * 023 * <p>The validated request can be returned modified. Modifications should be 024 * limited to optional parameters. Parameters such as {@code client_id}, 025 * {@code response_type}, {@code redirect_uri} and {@code state} must not be 026 * modified. 027 * 028 * <p>The {@link #validatePushedAuthorizationRequest} method can reject the 029 * request by throwing an {@link InvalidPushedAuthorizationRequestException} 030 * with an appropriate HTTP status code and error code. The exception message 031 * will be logged and not output to the client. 032 * 033 * <p>Example: 034 * 035 * <pre> 036 * throw new InvalidPARException("Scope not accepted scope", // will be logged 037 * OAuth2Error.INVALID_SCOPE 038 * .setHTTPStatusCode(400) 039 * .setDescription("Scope not accepted: some_scope")); 040 * </pre> 041 * 042 * The resulting HTTP response: 043 * 044 * <pre> 045 * HTTP/1.1 400 Bad Request 046 * Content-Type: application/json;charset=UTF-8 047 * Cache-Control: no-store 048 * Pragma: no-cache 049 * 050 * { 051 * "error" : "invalid_scope", 052 * "error_description" : "Scope not accepted: some_scope" 053 * } 054 * </pre> 055 * 056 * <p>Implementations must be thread-safe. 057 */ 058@ThreadSafe 059public interface PARValidator extends Lifecycle { 060 061 062 /** 063 * Validates the specified OAuth 2.0 authorisation / OpenID 064 * authentication request. 065 * 066 * <p>Deprecated, use {@link #validatePushedAuthorizationRequest} 067 * instead. 068 * 069 * @param authzRequest The request to perform additional validation on. 070 * Can be cast to 071 * {@link com.nimbusds.openid.connect.sdk.AuthenticationRequest} 072 * for an instance of an OpenID authentication 073 * request. Not {@code null}. 074 * @param validatorCtx The PAR validator context. Not {@code null}. 075 * 076 * @throws GeneralException If the request is rejected. Should include 077 * an appropriate HTTP status and error code. 078 */ 079 @Deprecated 080 default void validate(final AuthorizationRequest authzRequest, final ValidatorContext validatorCtx) 081 throws GeneralException { 082 083 try { 084 validatePushedAuthorizationRequest(authzRequest, validatorCtx); 085 } catch (InvalidPushedAuthorizationRequestException e) { 086 throw new GeneralException(e.getMessage(), e.getErrorObject()); 087 } 088 } 089 090 091 /** 092 * Validates the specified OAuth 2.0 authorisation / OpenID 093 * authentication request. 094 * 095 * @param authzRequest The request to perform additional validation on. 096 * Can be cast to 097 * {@link com.nimbusds.openid.connect.sdk.AuthenticationRequest} 098 * for an instance of an OpenID authentication 099 * request. Not {@code null}. 100 * @param validatorCtx The PAR validator context. Not {@code null}. 101 * 102 * @return The validated OAuth 2.0 authorisation / OpenID 103 * authentication request. It may be modified. Must not be 104 * {@code null}. 105 * 106 * @throws InvalidPushedAuthorizationRequestException If the request is 107 * rejected. 108 */ 109 default AuthorizationRequest validatePushedAuthorizationRequest(final AuthorizationRequest authzRequest, 110 final ValidatorContext validatorCtx) 111 throws InvalidPushedAuthorizationRequestException { 112 113 try { 114 validate(authzRequest, validatorCtx); 115 } catch (GeneralException e) { 116 throw new InvalidPushedAuthorizationRequestException(e.getMessage(), e.getErrorObject()); 117 } 118 return authzRequest; 119 } 120}