use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.
the class AuthorisationApiController method getAuthorisation.
/**
* getAuthorisation - Implementation of the /authorize OIDC Connect endpoint.
* @param responseType required = true
* @param clientId required = true
* @param state required = false
* @param nonce required = false
* @param scopes required = false
* @param redirectUri required = false,
* @param requestParametersSerialised required = true)
* @param isHeadlessEnabled required = false, defaultValue = "false"
* @param username required = false, defaultValue = ""
* @param password required = false, defaultValue = ""
* @param ssoToken (required = false)
* @param body required = false
* @return A <code>ResponseEntity</code> containing the result of authorization request
* @throws OBErrorResponseException or OBErrorException when errors occur that prevent authorization
*/
@Override
public ResponseEntity getAuthorisation(String responseType, String clientId, String state, String nonce, String scopes, String redirectUri, String requestParametersSerialised, boolean isHeadlessEnabled, String username, String password, String ssoToken, MultiValueMap body, HttpServletRequest request) throws OBErrorResponseException, OBErrorException {
// Initialisation the response entity, it will be overwritten with am response.
ResponseEntity responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
try {
// FAPI compliant ('code id_token'): https://github.com/ForgeCloud/ob-deploy/issues/674
if (!discoveryConfig.getSupportedResponseTypes().contains(responseType)) {
log.error("The response types requested '" + responseType + "' don't match with the response types " + "supported '" + discoveryConfig.getSupportedResponseTypes() + "' by as-api");
throw new OBErrorResponseException(OBRIErrorType.REQUEST_RESPONSE_TYPE_MISMATCH.getHttpStatus(), OBRIErrorResponseCategory.REQUEST_INVALID, OBRIErrorType.REQUEST_RESPONSE_TYPE_MISMATCH.toOBError1(responseType, discoveryConfig.getSupportedResponseTypes().toString()));
}
SignedJWT requestParameterJwt = validateRequestParameter(responseType, clientId, state, nonce, scopes, redirectUri, requestParametersSerialised);
requestParametersSerialised = requestParameterJwt.serialize();
try {
state = getState(state, requestParameterJwt);
} catch (ParseException e) {
throw new OBErrorResponseException(OBRIErrorType.REQUEST_PARAMETER_JWT_INVALID.getHttpStatus(), OBRIErrorResponseCategory.REQUEST_INVALID, OBRIErrorType.REQUEST_PARAMETER_JWT_INVALID.toOBError1(e.getMessage()));
}
AMGateway amGateway = amGatewayService.getAmGateway(requestParametersSerialised);
if (isHeadlessAlwaysEnabled || isHeadlessEnabled) {
log.debug("getAuthorisation() performing headless authorisation");
responseEntity = headLessAuthorisationService.getAuthorisation(amGateway, responseType, clientId, state, nonce, scopes, redirectUri, requestParametersSerialised, username, password);
} else {
log.debug("getAuthorisation() delegating authorisation to AM");
HashMap<String, String> queryParameters = new HashMap<>();
queryParameters.put("request", requestParametersSerialised);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Cookie", cookieName + "=" + ssoToken);
responseEntity = amGateway.toAM(request, httpHeaders, queryParameters, new ParameterizedTypeReference<String>() {
}, body);
}
log.debug("getAuthorisation() responseEntity {}", responseEntity);
// re-write it to appear as a fragment
if (hasQueryParamIdToken(responseEntity)) {
responseEntity = convertQueryToFragment(responseEntity.getHeaders().getLocation(), responseEntity.getHeaders(), state);
return responseEntity;
}
// Rewriting the response as we need to re-sign the id token. We can assume the id_token will exist as a fragment
if (hasFragmentIdToken(responseEntity)) {
try {
responseEntity = this.jwtOverridingService.rewriteIdTokenFragmentInLocationHeader(responseEntity);
tokenUsageService.incrementTokenUsage(TokenUsage.ID_TOKEN);
} catch (AccessTokenReWriteException e) {
String supportUID = UUID.randomUUID().toString();
log.info("getAuthorisation() Failed to re-write the id_token", e);
throw new OBErrorResponseException(OBRIErrorType.AUTHORIZE_INVALID_ID_TOKEN.getHttpStatus(), OBRIErrorResponseCategory.ACCESS_TOKEN, OBRIErrorType.AUTHORIZE_INVALID_ID_TOKEN.toOBError1(supportUID));
}
} else {
log.debug("responseEntity {} is null or is not a redirection", responseEntity);
}
} catch (OBErrorResponseException | OBErrorException obException) {
log.error("Authorisation error '{}', building the redirect action", obException.getMessage());
if (redirectUri != null && state != null) {
RedirectionAction redirectionAction = buildRedirectionAction(obException, redirectUri, state);
return ResponseEntity.status(HttpStatus.FOUND).header("Location", redirectionAction.getRedirectUri()).build();
}
}
return responseEntity;
}
use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.
the class AuthorisationApiController method buildRedirectionAction.
private RedirectionAction buildRedirectionAction(Exception obException, String redirectUri, String state) {
UriComponents uriComponents = UriComponentsBuilder.newInstance().build();
if (obException instanceof OBErrorException) {
OBErrorException obErrorException = (OBErrorException) obException;
uriComponents = UriComponentsBuilder.fromHttpUrl(redirectUri).fragment("error=invalid_request_object&state=" + state + "&error_description=" + String.format(obErrorException.getObriErrorType().getMessage(), obErrorException.getArgs())).encode().build();
} else if (obException instanceof OBErrorResponseException) {
OBErrorResponseException obErrorResponseException = (OBErrorResponseException) obException;
uriComponents = UriComponentsBuilder.fromHttpUrl(redirectUri).fragment("error=invalid_request_object&state=" + state + "&error_description=" + obErrorResponseException.getErrors().get(0).getMessage()).encode().build();
}
return RedirectionAction.builder().redirectUri(uriComponents.toUriString()).requestMethod(HttpMethod.GET).build();
}
use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.
the class DiscoveryApiControllerTest method testResponseTypesSupported_dont_match.
@Test
public void testResponseTypesSupported_dont_match() {
// Given
List<String> responseTypes = List.of("code", "id_token", "code id_token");
given(config.getSupportedResponseTypes()).willReturn(responseTypes);
discoveryApiController = new DiscoveryApiController(amGateway, config, "localhost", "", "", "");
MockHttpServletRequest req = new MockHttpServletRequest();
OIDCDiscoveryResponse oidcDiscoveryResponse = JMockData.mock(OIDCDiscoveryResponse.class);
List<String> amResponseTypes = new ArrayList<>();
amResponseTypes.addAll(responseTypes.subList(0, 1));
amResponseTypes.add("device_code");
amResponseTypes.add("device_code code id_token");
oidcDiscoveryResponse.setResponseTypesSupported(amResponseTypes);
ResponseEntity<OIDCDiscoveryResponse> response = new ResponseEntity<>(oidcDiscoveryResponse, HttpStatus.OK);
given(amGateway.toAM(req, new HttpHeaders(), new ParameterizedTypeReference<OIDCDiscoveryResponse>() {
})).willReturn(response);
// When
OBErrorResponseException e = catchThrowableOfType(() -> discoveryApiController.getDiscovery(req), OBErrorResponseException.class);
// Then
assertThat(e.getErrors().get(0).getMessage()).isEqualTo("The response types supported by the authorisation server '" + amResponseTypes + "' don't match with the response types supported '" + responseTypes + "' by as-api");
assertThat(e.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST);
}
use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.
the class DiscoveryApiControllerTest method testResponseTypeSupported_dont_match.
@Test
public void testResponseTypeSupported_dont_match() {
// Given
List<String> responseTypes = List.of("code id_token");
given(config.getSupportedResponseTypes()).willReturn(responseTypes);
discoveryApiController = new DiscoveryApiController(amGateway, config, "localhost", "", "", "");
MockHttpServletRequest req = new MockHttpServletRequest();
OIDCDiscoveryResponse oidcDiscoveryResponse = JMockData.mock(OIDCDiscoveryResponse.class);
List<String> amResponseTypes = List.of("device_code", "device_code code id_token");
oidcDiscoveryResponse.setResponseTypesSupported(amResponseTypes);
ResponseEntity<OIDCDiscoveryResponse> response = new ResponseEntity<>(oidcDiscoveryResponse, HttpStatus.OK);
given(amGateway.toAM(req, new HttpHeaders(), new ParameterizedTypeReference<OIDCDiscoveryResponse>() {
})).willReturn(response);
// When
OBErrorResponseException e = catchThrowableOfType(() -> discoveryApiController.getDiscovery(req), OBErrorResponseException.class);
// Then
assertThat(e.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST);
assertThat(e.getErrors().get(0).getMessage()).isEqualTo("The response types supported by the authorisation server '" + amResponseTypes + "' don't match with the response types supported '" + responseTypes + "' by as-api");
}
use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.
the class HeadLessAccessTokenService method exchangeAuthorizationCodeForAccessToken.
private ResponseEntity<AccessTokenResponse> exchangeAuthorizationCodeForAccessToken(AMGateway amGateway, PairClientIDAuthMethod tokenEndpointAuthMethods, MultiValueMap paramMap, HttpServletRequest request, String code) throws OBErrorResponseException {
StringBuilder requestBody = new StringBuilder();
requestBody.append("grant_type=authorization_code");
Map<String, String> parameters = paramMap.toSingleValueMap();
switch(tokenEndpointAuthMethods.authMethod) {
case CLIENT_SECRET_BASIC:
// Would be in the request header already
break;
case TLS_CLIENT_AUTH:
requestBody.append("&client_id=").append(encode(parameters.get("client_id")));
break;
case CLIENT_SECRET_POST:
requestBody.append("&client_id=").append(encode(parameters.get("client_id")));
requestBody.append("&client_secret=").append(encode(parameters.get("client_secret")));
break;
case CLIENT_SECRET_JWT:
throw new RuntimeException("Not Implemented");
case PRIVATE_KEY_JWT:
requestBody.append("&client_assertion_type=").append(encode(parameters.get("client_assertion_type")));
requestBody.append("&client_assertion=").append(encode(parameters.get("client_assertion")));
break;
}
requestBody.append("&redirect_uri=").append(encode(parameters.get("redirect_uri")));
requestBody.append("&code=").append(encode(code));
HttpHeaders httpHeaders = new HttpHeaders();
// httpHeaders.add("Content-Type", "application/x-www-form-urlencoded");
ResponseEntity responseFromAM = amGateway.toAM(request, httpHeaders, new ParameterizedTypeReference<AccessTokenResponse>() {
}, requestBody.toString());
HttpStatus statusCode = responseFromAM.getStatusCode();
if (!statusCode.is2xxSuccessful() && !statusCode.is3xxRedirection()) {
log.warn("getAccessToken() unsuccessful call to headlessAuthTokenService. StatusCode: {}, body: {}", statusCode, responseFromAM.getBody());
throw new OBErrorResponseException(OBRIErrorType.ACCESS_TOKEN_INVALID.getHttpStatus(), OBRIErrorResponseCategory.ACCESS_TOKEN, OBRIErrorType.ACCESS_TOKEN_INVALID.toOBError1(responseFromAM.getBody()));
}
Object responseBody = responseFromAM.getBody();
if (responseBody instanceof AccessTokenResponse) {
ResponseEntity<AccessTokenResponse> responseEntity = new ResponseEntity<>((AccessTokenResponse) responseFromAM.getBody(), responseFromAM.getStatusCode());
return responseEntity;
} else {
throw new OBErrorResponseException(OBRIErrorType.ACCESS_TOKEN_INVALID.getHttpStatus(), OBRIErrorResponseCategory.ACCESS_TOKEN, OBRIErrorType.ACCESS_TOKEN_INVALID.toOBError1(responseFromAM.getBody()));
}
}
Aggregations