Search in sources :

Example 66 with OBErrorResponseException

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;
}
Also used : HttpHeaders(org.springframework.http.HttpHeaders) RedirectionAction(com.forgerock.openbanking.common.model.rcs.RedirectionAction) OBErrorException(com.forgerock.openbanking.exceptions.OBErrorException) SignedJWT(com.nimbusds.jwt.SignedJWT) ResponseEntity(org.springframework.http.ResponseEntity) AMGateway(com.forgerock.openbanking.am.gateway.AMGateway) ParameterizedTypeReference(org.springframework.core.ParameterizedTypeReference) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) AccessTokenReWriteException(com.forgerock.openbanking.common.error.exception.AccessTokenReWriteException) ParseException(java.text.ParseException)

Example 67 with OBErrorResponseException

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();
}
Also used : UriComponents(org.springframework.web.util.UriComponents) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) OBErrorException(com.forgerock.openbanking.exceptions.OBErrorException)

Example 68 with OBErrorResponseException

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);
}
Also used : HttpHeaders(org.springframework.http.HttpHeaders) ResponseEntity(org.springframework.http.ResponseEntity) OIDCDiscoveryResponse(com.forgerock.openbanking.common.model.as.discovery.OIDCDiscoveryResponse) MockHttpServletRequest(org.springframework.mock.web.MockHttpServletRequest) ArrayList(java.util.ArrayList) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) Test(org.junit.Test)

Example 69 with OBErrorResponseException

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");
}
Also used : HttpHeaders(org.springframework.http.HttpHeaders) ResponseEntity(org.springframework.http.ResponseEntity) OIDCDiscoveryResponse(com.forgerock.openbanking.common.model.as.discovery.OIDCDiscoveryResponse) MockHttpServletRequest(org.springframework.mock.web.MockHttpServletRequest) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) Test(org.junit.Test)

Example 70 with OBErrorResponseException

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()));
    }
}
Also used : HttpHeaders(org.springframework.http.HttpHeaders) ResponseEntity(org.springframework.http.ResponseEntity) HttpStatus(org.springframework.http.HttpStatus) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) AccessTokenResponse(com.forgerock.openbanking.model.oidc.AccessTokenResponse)

Aggregations

OBErrorResponseException (com.forgerock.openbanking.exceptions.OBErrorResponseException)213 ResponseEntity (org.springframework.http.ResponseEntity)140 Controller (org.springframework.stereotype.Controller)129 DateTime (org.joda.time.DateTime)121 HttpHeaders (org.springframework.http.HttpHeaders)108 Collections (java.util.Collections)103 Principal (java.security.Principal)102 HttpServletRequest (javax.servlet.http.HttpServletRequest)102 RsStoreGateway (com.forgerock.openbanking.common.services.store.RsStoreGateway)101 RSEndpointWrapperService (com.forgerock.openbanking.aspsp.rs.wrappper.RSEndpointWrapperService)100 ApiParam (io.swagger.annotations.ApiParam)69 PathVariable (org.springframework.web.bind.annotation.PathVariable)69 RequestHeader (org.springframework.web.bind.annotation.RequestHeader)69 DateTimeFormat (org.springframework.format.annotation.DateTimeFormat)63 HTTP_DATE_FORMAT (com.forgerock.openbanking.constants.OpenBankingConstants.HTTP_DATE_FORMAT)59 ApiVersionUtils.getOBVersion (com.forgerock.openbanking.common.utils.ApiVersionUtils.getOBVersion)55 Logger (org.slf4j.Logger)50 LoggerFactory (org.slf4j.LoggerFactory)50 RequestBody (org.springframework.web.bind.annotation.RequestBody)49 Valid (javax.validation.Valid)48