Search in sources :

Example 71 with OBErrorResponseException

use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.

the class HeadLessAuthorisationService method getConsentRequest.

private String getConsentRequest(AMGateway amGateway, String amAuthorizationEndpoint, AMAuthentication.TokenResponse authenticate) throws OBErrorResponseException, WrongResponseEntity {
    // Send the request to AM which will ask us to redirect to the RCS
    HttpHeaders amHeader = new HttpHeaders();
    amHeader.add("Cookie", cookieName + "=" + authenticate.getTokenId());
    ResponseEntity<String> responseEntity = null;
    try {
        responseEntity = amGateway.toAM(amAuthorizationEndpoint, HttpMethod.GET, amHeader, new ParameterizedTypeReference<String>() {
        }, null);
        log.debug("Response received by AM: {}", responseEntity);
    } catch (Exception e) {
        log.error("getConsentRequest() Caught exception from AM.", e);
        throw new OBErrorResponseException(OBRIErrorType.HEAD_LESS_AUTH_AS_ERROR_RECEIVED.getHttpStatus(), OBRIErrorResponseCategory.HEADLESS_AUTH, OBRIErrorType.HEAD_LESS_AUTH_AS_ERROR_RECEIVED.toOBError1(e.getMessage()));
    }
    if (responseEntity.getStatusCode() != HttpStatus.FOUND) {
        throw new WrongResponseEntity(responseEntity);
    }
    // Extract the RCS consent
    String location = responseEntity.getHeaders().getFirst(HttpHeaders.LOCATION);
    log.debug("The redirection to the consent page should be in the location '{}'", location);
    try {
        URL url = new URL(location);
        Map<String, String> queryParameters = ParseUriUtils.parseQueryOrFragment(url.getQuery());
        if (!queryParameters.containsKey("consent_request")) {
            throw new WrongResponseEntity(responseEntity);
        }
        log.debug("The consent_request '{}'", queryParameters.get("consent_request"));
        return queryParameters.get("consent_request");
    } catch (MalformedURLException e) {
        log.error("The location '{}' to the RCS, returned by AM, is not an URL", location, e);
        throw new OBErrorResponseException(OBRIErrorType.HEAD_LESS_AUTH_RCS_URI_INCORRECT.getHttpStatus(), OBRIErrorResponseCategory.HEADLESS_AUTH, OBRIErrorType.HEAD_LESS_AUTH_RCS_URI_INCORRECT.toOBError1(location));
    }
}
Also used : MalformedURLException(java.net.MalformedURLException) ParameterizedTypeReference(org.springframework.core.ParameterizedTypeReference) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) MalformedURLException(java.net.MalformedURLException) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) URL(java.net.URL)

Example 72 with OBErrorResponseException

use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.

the class AccessTokenApiControllerTest method failsWhenNoClientCredentials_getAccessToken.

@Test
public void failsWhenNoClientCredentials_getAccessToken() throws OBErrorResponseException {
    // Given
    MultiValueMap<String, String> params = getParamsMap(CLIENT_CREDENTIAL);
    PairClientIDAuthMethod pairClientIDAuthMethod = getClientIDAuthMethod(TokenEndpointAuthMethods.PRIVATE_KEY_JWT);
    given(matlsRequestVerificationService.verifyMATLSMatchesRequest(params, authorization, principal)).willReturn(pairClientIDAuthMethod);
    // When
    OBErrorResponseException e = catchThrowableOfType(() -> this.accessTokenApiController.getAccessToken(params, authorization, principal, request), OBErrorResponseException.class);
    // Then
    assertThat(e).isNotNull();
    assertThat(e.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED);
    assertThat(e.getCategory()).isEqualTo(OBRIErrorResponseCategory.ACCESS_TOKEN);
}
Also used : OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) PairClientIDAuthMethod(com.forgerock.openbanking.aspsp.as.service.PairClientIDAuthMethod) Test(org.junit.Test)

Example 73 with OBErrorResponseException

use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.

the class MatlsRequestVerificationService method getPairClientIdAuthMethodFromClientAssertion.

private PairClientIDAuthMethod getPairClientIdAuthMethodFromClientAssertion(String clientAssertion, MultiValueMap paramMap) throws OBErrorResponseException {
    PairClientIDAuthMethod pairClientIDAuthMethod = new PairClientIDAuthMethod();
    if (clientAssertion == null || clientAssertion.isEmpty() || clientAssertion.isBlank()) {
        throw new OBErrorResponseException(OBRIErrorType.ACCESS_TOKEN_INVALID.getHttpStatus(), OBRIErrorResponseCategory.ACCESS_TOKEN, OBRIErrorType.ACCESS_TOKEN_INVALID.toOBError1("No client_assertion in body"));
    }
    log.debug("Read client ID from client assertion found: {}", clientAssertion);
    try {
        SignedJWT jws = (SignedJWT) JWTParser.parse(clientAssertion);
        pairClientIDAuthMethod.clientId = jws.getJWTClaimsSet().getSubject();
        Object clientIDFromBody = paramMap.getFirst(CLIENT_ID);
        if (clientIDFromBody != null && !pairClientIDAuthMethod.clientId.equals(clientIDFromBody)) {
            log.error("Client ID from the request body {} is not matching the client assertion sub {}", clientIDFromBody, pairClientIDAuthMethod.clientId);
            throw new OBErrorResponseException(OBRIErrorType.ACCESS_TOKEN_CLIENT_ID_MISS_MATCH.getHttpStatus(), OBRIErrorResponseCategory.ACCESS_TOKEN, OBRIErrorType.ACCESS_TOKEN_CLIENT_ID_MISS_MATCH.toOBError1(clientIDFromBody, pairClientIDAuthMethod.clientId));
        }
        pairClientIDAuthMethod.authMethod = OIDCConstants.TokenEndpointAuthMethods.PRIVATE_KEY_JWT;
    } catch (ParseException e) {
        log.error("Parse client assertion error", e);
        throw new OBErrorResponseException(OBRIErrorType.ACCESS_TOKEN_CLIENT_ASSERTION_FORMAT_INVALID.getHttpStatus(), OBRIErrorResponseCategory.ACCESS_TOKEN, OBRIErrorType.ACCESS_TOKEN_CLIENT_ASSERTION_FORMAT_INVALID.toOBError1(clientAssertion));
    }
    return pairClientIDAuthMethod;
}
Also used : OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException) SignedJWT(com.nimbusds.jwt.SignedJWT) ParseException(java.text.ParseException)

Example 74 with OBErrorResponseException

use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.

the class MatlsRequestVerificationService method verifyMATLSMatchesRequest.

public PairClientIDAuthMethod verifyMATLSMatchesRequest(MultiValueMap paramMap, String authorization, Principal principal) throws OBErrorResponseException {
    UserDetails currentUser = (UserDetails) ((Authentication) principal).getPrincipal();
    PairClientIDAuthMethod pairClientIDAuthMethod;
    String clientAssertion = (String) paramMap.getFirst(OIDCConstants.OIDCClaim.CLIENT_ASSERTION);
    if (clientAssertion != null) {
        pairClientIDAuthMethod = getPairClientIdAuthMethodFromClientAssertion(clientAssertion, paramMap);
    } else if (authorization != null) {
        pairClientIDAuthMethod = getPairClientIdAuthMethodFromAuthorization(authorization, paramMap);
    } else if (paramMap.get("client_secret") != null) {
        pairClientIDAuthMethod = getPairClientIdAuthMethodWhenClientSecret(paramMap);
    } else {
        pairClientIDAuthMethod = getPairClientIdAuthMethodDefault(paramMap);
    }
    String authClientId = pairClientIDAuthMethod.clientId;
    Tpp tpp = getTppRegistered(authClientId);
    if (!matlsIdMatchesTppId(principal.getName(), tpp)) {
        log.info("The clientId found via the authentication method did not belong to the Tpp identified by the " + "MATLS certificate's principal (authorisationNumber). authorisationNumber '{}', clientId '{}'", principal.getName(), tpp.getAuthorisationNumber());
        throw new OBErrorResponseException(OBRIErrorType.ACCESS_TOKEN_CREDENTIAL_NOT_MATCHING_CLIENT_CERTS.getHttpStatus(), OBRIErrorResponseCategory.ACCESS_TOKEN, OBRIErrorType.ACCESS_TOKEN_CREDENTIAL_NOT_MATCHING_CLIENT_CERTS.toOBError1(tpp.getClientId(), pairClientIDAuthMethod.clientId, pairClientIDAuthMethod.authMethod.type));
    }
    // can throw UnsupportedOIDCAuthMethodsException
    OIDCRegistrationResponse registrationResponse = tpp.getRegistrationResponse();
    String tokenEndpointAuthMethod = registrationResponse.getTokenEndpointAuthMethod();
    OIDCConstants.TokenEndpointAuthMethods authMethodsFromTpp = OIDCConstants.TokenEndpointAuthMethods.fromType(tokenEndpointAuthMethod);
    if (!authMethodsFromTpp.equals(pairClientIDAuthMethod.authMethod)) {
        log.info("The authorisation method specified in the token differend from that in the Tpp registration " + "response");
        throw new OBErrorResponseException(OBRIErrorType.ACCESS_TOKEN_WRONG_AUTH_METHOD.getHttpStatus(), OBRIErrorResponseCategory.ACCESS_TOKEN, OBRIErrorType.ACCESS_TOKEN_WRONG_AUTH_METHOD.toOBError1(pairClientIDAuthMethod.authMethod.type, authMethodsFromTpp.type));
    }
    return pairClientIDAuthMethod;
}
Also used : UserDetails(org.springframework.security.core.userdetails.UserDetails) OIDCConstants(com.forgerock.openbanking.constants.OIDCConstants) Tpp(com.forgerock.openbanking.model.Tpp) OIDCRegistrationResponse(com.forgerock.openbanking.model.oidc.OIDCRegistrationResponse) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException)

Example 75 with OBErrorResponseException

use of com.forgerock.openbanking.exceptions.OBErrorResponseException in project openbanking-aspsp by OpenBankingToolkit.

the class DiscoveryApiController method getDiscovery.

@Override
public ResponseEntity getDiscovery(HttpServletRequest request) throws OBErrorResponseException {
    String normalEndpoint = "https://as.aspsp." + dnsHostRoot;
    String matlsProtectedEndpoint = withPort("https://matls.as.aspsp." + dnsHostRoot);
    HttpHeaders additionalHttpHeaders = new HttpHeaders();
    ParameterizedTypeReference<OIDCDiscoveryResponse> ptr = new ParameterizedTypeReference<OIDCDiscoveryResponse>() {
    };
    ResponseEntity<OIDCDiscoveryResponse> responseEntity = amGateway.toAM(request, additionalHttpHeaders, ptr);
    OIDCDiscoveryResponse discoveryResponse = Objects.requireNonNull(responseEntity.getBody());
    log.debug("Discovery response received from AM: {}", discoveryResponse);
    discoveryResponse.setVersion(readWriteApiVersion);
    discoveryResponse.setReadWriteApiVersion(readWriteApiVersion);
    discoveryResponse.setClientRegistrationApiVersion(clientRegistrationApiVersion);
    // Override the well-known
    discoveryResponse.setIssuer(switchToNonMatls(discoveryResponse.getIssuer()));
    discoveryResponse.setIntrospectionEndpoint(switchToSCGWPort(switchToMatls(discoveryResponse.getIntrospectionEndpoint())));
    discoveryResponse.setUserinfoEndpoint(switchToSCGWPort(switchToMatls(discoveryResponse.getUserinfoEndpoint())));
    discoveryResponse.setTokenEndpoint(switchToSCGWPort(switchToMatls(discoveryResponse.getTokenEndpoint())));
    if (discoveryConfig.getObieJwkUri() != null && !"".equals(discoveryConfig.getObieJwkUri())) {
        discoveryResponse.setJwksUri(discoveryConfig.getObieJwkUri());
    } else {
        discoveryResponse.setJwksUri(withPort(normalEndpoint) + "/api/jwk/jwk_uri");
    }
    discoveryResponse.setAuthorizationEndpoint(withPort(normalEndpoint) + "/oauth2/authorize");
    log.debug("Supported Token Endpoint Auth Methods from AM: {} will be restricted to as-api configured values: {}", discoveryResponse.getTokenEndpointAuthMethodsSupported(), discoveryConfig.getSupportedAuthMethod());
    discoveryResponse.setTokenEndpointAuthMethodsSupported(discoveryConfig.getSupportedAuthMethod());
    log.debug("Grant Types from AM: {} will be restricted to as-api configured values: {}", discoveryResponse.getGrantTypesSupported(), discoveryConfig.getSupportedGrantTypes());
    discoveryResponse.setGrantTypesSupported(discoveryConfig.getSupportedGrantTypes());
    // FAPI compliant ('code id_token'): https://github.com/ForgeCloud/ob-deploy/issues/674
    if (discoveryResponse.getResponseTypesSupported().containsAll(discoveryConfig.getSupportedResponseTypes())) {
        log.debug("Response Types from AM: {} will be restricted to as-api configured values: {}", discoveryResponse.getResponseTypesSupported(), discoveryConfig.getSupportedResponseTypes());
        discoveryResponse.setResponseTypesSupported(discoveryConfig.getSupportedResponseTypes());
    } else {
        log.error("The response types supported by the authorisation server '" + discoveryResponse.getResponseTypesSupported() + "' don't match with the response types supported '" + discoveryConfig.getSupportedResponseTypes() + "' by as-api");
        throw new OBErrorResponseException(OBRIErrorType.DISCOVERY_RESPONSE_TYPE_MISMATCH.getHttpStatus(), OBRIErrorResponseCategory.REQUEST_INVALID, OBRIErrorType.DISCOVERY_RESPONSE_TYPE_MISMATCH.toOBError1(discoveryResponse.getResponseTypesSupported().toString(), discoveryConfig.getSupportedResponseTypes().toString()));
    }
    log.debug("Set requestUriParameterSupported={} from as-api config", discoveryConfig.isRequestUriParameterSupported());
    discoveryResponse.setRequestUriParameterSupported(discoveryConfig.isRequestUriParameterSupported());
    if (discoveryConfig.isDynamicRegistrationEnable()) {
        discoveryResponse.setRegistrationEndpoint(matlsProtectedEndpoint + "/open-banking/register/");
    } else {
        log.debug("Dynamic Registration disabled. Registration endpoint will not appear in the well-known endpoint response.");
        discoveryResponse.setRegistrationEndpoint(null);
    }
    if (discoveryConfig.isUserInfoEnable()) {
        discoveryResponse.setUserinfoEndpoint(switchToSCGWPort(switchToMatls(discoveryResponse.getUserinfoEndpoint())));
    } else {
        log.debug("User Info endpoint disabled. It will not appear in the well-known endpoint response.");
        discoveryResponse.setUserinfoEndpoint(null);
        discoveryResponse.setUserinfoEncryptionAlgValuesSupported(null);
        discoveryResponse.setUserinfoEncryptionEncValuesSupported(null);
        discoveryResponse.setUserinfoSigningAlgValuesSupported(null);
    }
    if (discoveryConfig.isIntrospectionEnable()) {
        discoveryResponse.setIntrospectionEndpoint(switchToSCGWPort(switchToMatls(discoveryResponse.getIntrospectionEndpoint())));
    } else {
        log.debug("Introspection endpoint disabled. It will not appear in the well-known endpoint response.");
        discoveryResponse.setIntrospectionEndpoint(null);
    }
    // Don't show empty fields in response
    if (CollectionUtils.isEmpty(discoveryResponse.getIdTokenSigningAlgValuesSupported())) {
        discoveryResponse.setIdTokenSigningAlgValuesSupported(null);
    }
    if (!discoveryConfig.isIdTokenEncryptionAlgValuesEnabled() || CollectionUtils.isEmpty(discoveryResponse.getIdTokenEncryptionAlgValuesSupported())) {
        discoveryResponse.setIdTokenEncryptionAlgValuesSupported(null);
    }
    if (!discoveryConfig.isIdTokenEncryptionEncValuesEnabled() || CollectionUtils.isEmpty(discoveryResponse.getIdTokenEncryptionEncValuesSupported())) {
        discoveryResponse.setIdTokenEncryptionEncValuesSupported(null);
    }
    if (CollectionUtils.isEmpty(discoveryResponse.getRequestObjectSigningAlgValuesSupported())) {
        discoveryResponse.setRequestObjectSigningAlgValuesSupported(null);
    }
    if (!discoveryConfig.isRequestObjectEncryptionAlgValuesEnabled() || CollectionUtils.isEmpty(discoveryResponse.getRequestObjectEncryptionAlgValuesSupported())) {
        discoveryResponse.setRequestObjectEncryptionAlgValuesSupported(null);
    }
    if (!discoveryConfig.isRequestObjectEncryptionEncValuesEnabled() || CollectionUtils.isEmpty(discoveryResponse.getRequestObjectEncryptionEncValuesSupported())) {
        discoveryResponse.setRequestObjectEncryptionEncValuesSupported(null);
    }
    if (CollectionUtils.isEmpty(discoveryResponse.getTokenEndpointAuthSigningAlgValuesSupported())) {
        discoveryResponse.setTokenEndpointAuthSigningAlgValuesSupported(null);
    }
    // If 'Request Uri Parameter' not active then don't show 'Require Request Uri Registration' value as it is not relevant to our API
    if (!discoveryResponse.getRequestUriParameterSupported()) {
        discoveryResponse.setRequireRequestUriRegistration(null);
    }
    log.debug("Discovery response after manipulation: {}", discoveryResponse);
    return ResponseEntity.ok(discoveryResponse);
}
Also used : HttpHeaders(org.springframework.http.HttpHeaders) OIDCDiscoveryResponse(com.forgerock.openbanking.common.model.as.discovery.OIDCDiscoveryResponse) ParameterizedTypeReference(org.springframework.core.ParameterizedTypeReference) OBErrorResponseException(com.forgerock.openbanking.exceptions.OBErrorResponseException)

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