Search in sources :

Example 1 with Claims

use of com.forgerock.openbanking.model.claim.Claims in project openbanking-aspsp by OpenBankingToolkit.

the class JwsClaimsUtils method getClaims.

/**
 * getClaims extracts the claims from a JWT
 *
 * @param signedJWT the JWT from which the claims are to be returned
 * @return a {@code Claims} object containing the claims extracted from {@code signedJWT}
 * @throws ParseException
 */
public static Claims getClaims(SignedJWT signedJWT) throws ParseException {
    JWTClaimsSet claimSet = signedJWT.getJWTClaimsSet();
    Map<String, Object> jsonClaimSet = claimSet.getJSONObjectClaim(OIDCConstants.OIDCClaim.CLAIMS);
    Claims claims = Claims.parseClaims(new JSONObject(jsonClaimSet));
    return claims;
}
Also used : Claims(com.forgerock.openbanking.model.claim.Claims) JSONObject(com.nimbusds.jose.shaded.json.JSONObject) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) JSONObject(com.nimbusds.jose.shaded.json.JSONObject)

Example 2 with Claims

use of com.forgerock.openbanking.model.claim.Claims in project openbanking-aspsp by OpenBankingToolkit.

the class RCSDetailsGatewayApiController method details.

@Override
public ResponseEntity details(@RequestBody String consentRequestJwt, @CookieValue(value = "${am.cookie.name}") String ssoToken) throws OBErrorException {
    LOGGER.debug("Received a consent request with consent_request='{}'", consentRequestJwt);
    try {
        // Verify the RCS JWT
        LOGGER.debug("Validate consent request JWS");
        // TODO disabling this for now as the consent request JWT as a very short period of life
        // cryptoApiClient.validateJws(consentRequestJwt, amOpenBankingConfiguration.getIssuerID(), amOpenBankingConfiguration.jwksUri);
        LOGGER.debug("Parse consent request JWS");
        SignedJWT signedJWT = (SignedJWT) JWTParser.parse(consentRequestJwt);
        LOGGER.debug("Read payment ID from the claims");
        // Read the claims
        Claims claims = JwsClaimsUtils.getClaims(signedJWT);
        if (!claims.getIdTokenClaims().containsKey(OpenBankingConstants.IdTokenClaim.INTENT_ID)) {
            throw new OBErrorException(OBRIErrorType.RCS_CONSENT_REQUEST_INVALID, "No intent ID");
        }
        String intentId = claims.getIdTokenClaims().get(OpenBankingConstants.IdTokenClaim.INTENT_ID).getValue();
        String clientId = signedJWT.getJWTClaimsSet().getStringClaim(RCSConstants.Claims.CLIENT_ID);
        Map<String, String> profile = userProfileService.getProfile(ssoToken, amOpenBankingConfiguration.endpointUserProfile, amOpenBankingConfiguration.cookieName);
        String username = profile.get(amOpenBankingConfiguration.userProfileId);
        List<AccountWithBalance> accounts = getAccountOrGenerateData(username);
        LOGGER.debug("intent Id from the requested claims '{}'", intentId);
        return intentTypeService.consentDetails(intentId, consentRequestJwt, accounts, username, clientId);
    } catch (ParseException e) {
        LOGGER.error("Could not parse the JWT", e);
        throw new OBErrorException(OBRIErrorType.RCS_CONSENT_REQUEST_FORMAT);
    } catch (OBErrorException e) {
        return rcsErrorService.invalidConsentError(consentRequestJwt, e);
    }
}
Also used : Claims(com.forgerock.openbanking.model.claim.Claims) OBErrorException(com.forgerock.openbanking.exceptions.OBErrorException) SignedJWT(com.nimbusds.jwt.SignedJWT) ParseException(java.text.ParseException) AccountWithBalance(com.forgerock.openbanking.common.model.openbanking.persistence.account.AccountWithBalance)

Example 3 with Claims

use of com.forgerock.openbanking.model.claim.Claims in project openbanking-aspsp by OpenBankingToolkit.

the class AutodecisionsApiController method autoAccept.

@Override
public ResponseEntity<RedirectionAction> autoAccept(@RequestBody String consentRequestJwt, @CookieValue(value = "${am.cookie.name}") String ssoToken) throws OBErrorException {
    try {
        log.debug("Parse consent request JWS");
        SignedJWT signedJWT = (SignedJWT) JWTParser.parse(consentRequestJwt);
        log.debug("Read payment ID from the claims");
        // Read the claims
        Claims claims = JwsClaimsUtils.getClaims(signedJWT);
        if (!claims.getIdTokenClaims().containsKey(OpenBankingConstants.IdTokenClaim.INTENT_ID)) {
            return rcsErrorService.error(OBRIErrorType.RCS_CONSENT_REQUEST_INVALID, "No intent ID");
        }
        String intentId = claims.getIdTokenClaims().get(OpenBankingConstants.IdTokenClaim.INTENT_ID).getValue();
        String clientId = signedJWT.getJWTClaimsSet().getStringClaim(RCSConstants.Claims.CLIENT_ID);
        String redirectUri = signedJWT.getJWTClaimsSet().getStringClaim(OIDCConstants.OIDCClaim.CONSENT_APPROVAL_REDIRECT_URI);
        String csrf = signedJWT.getJWTClaimsSet().getStringClaim(RCSConstants.Claims.CSRF);
        List<String> scopes = new ArrayList<>(signedJWT.getJWTClaimsSet().getJSONObjectClaim(RCSConstants.Claims.SCOPES).keySet());
        Map<String, String> profile = userProfileService.getProfile(ssoToken, amOpenBankingConfiguration.endpointUserProfile, amOpenBankingConfiguration.cookieName);
        String username = profile.get(amOpenBankingConfiguration.userProfileId);
        List<FRAccount> accounts = getAccountOrGenerateData(username);
        // Call the right decision delegate, cased on the intent type
        ConsentDecisionDelegate consentDecisionDelegate = intentTypeService.getConsentDecision(intentId);
        consentDecisionDelegate.autoaccept(accounts, username);
        log.debug("Redirect the resource owner to the original oauth2/openid request but this time, with the " + "consent response jwt '{}'.", consentRequestJwt);
        String consentJwt = rcsService.generateRCSConsentResponse(rcsConfiguration, amOpenBankingConfiguration, csrf, true, scopes, clientId);
        ResponseEntity responseEntity = rcsService.sendRCSResponseToAM(ssoToken, RedirectionAction.builder().redirectUri(redirectUri).consentJwt(consentJwt).requestMethod(HttpMethod.POST).build());
        log.debug("Response received from AM: {}", responseEntity);
        if (responseEntity.getStatusCode() != HttpStatus.FOUND) {
            log.error("When sending the consent response {} to AM, it failed to returned a 302", consentJwt, responseEntity);
            throw new OBErrorException(OBRIErrorType.RCS_CONSENT_RESPONSE_FAILURE);
        }
        // TODO: Determine if the id_token needs re-writing!
        String location = responseEntity.getHeaders().getFirst(HttpHeaders.LOCATION);
        log.debug("The redirection to the consent page should be in the location '{}'", location);
        return ResponseEntity.ok(RedirectionAction.builder().redirectUri(location).build());
    } catch (JOSEException e) {
        log.error("Could not generate consent context JWT", e);
        throw new OBErrorException(OBRIErrorType.RCS_CONSENT_RESPONSE_FAILURE);
    } catch (ParseException e) {
        log.error("Could not parse the JWT", e);
        throw new OBErrorException(OBRIErrorType.RCS_CONSENT_REQUEST_FORMAT);
    } catch (Exception e) {
        log.error("Unexpected error while authorising consent", e);
        throw new OBErrorException(OBRIErrorType.RCS_CONSENT_RESPONSE_FAILURE);
    }
}
Also used : Claims(com.forgerock.openbanking.model.claim.Claims) FRAccount(com.forgerock.openbanking.common.model.openbanking.persistence.account.FRAccount) ArrayList(java.util.ArrayList) OBErrorException(com.forgerock.openbanking.exceptions.OBErrorException) SignedJWT(com.nimbusds.jwt.SignedJWT) JOSEException(com.nimbusds.jose.JOSEException) ParseException(java.text.ParseException) OBErrorException(com.forgerock.openbanking.exceptions.OBErrorException) HttpClientErrorException(org.springframework.web.client.HttpClientErrorException) ResponseEntity(org.springframework.http.ResponseEntity) ConsentDecisionDelegate(com.forgerock.openbanking.aspsp.rs.rcs.api.rcs.decisions.ConsentDecisionDelegate) ParseException(java.text.ParseException) JOSEException(com.nimbusds.jose.JOSEException)

Example 4 with Claims

use of com.forgerock.openbanking.model.claim.Claims in project openbanking-aspsp by OpenBankingToolkit.

the class RCSConsentDecisionApiController method decision.

/**
 * @param consentDecisionSerialised
 * @param ssoToken
 * @return
 * @throws OBErrorException
 */
@Override
public ResponseEntity decision(@RequestBody String consentDecisionSerialised, @CookieValue(value = "${am.cookie.name}") String ssoToken) throws OBErrorException {
    log.debug("decisionAccountSharing() consentDecisionSerialised is {}", consentDecisionSerialised);
    // Send a Consent response JWT to the initial request, which is define in the code
    if (consentDecisionSerialised == null || consentDecisionSerialised.isEmpty()) {
        log.debug("Consent decision is empty");
        return rcsErrorService.error(OBRIErrorType.RCS_CONSENT_DECISION_EMPTY);
    }
    ConsentDecision consentDecision;
    try {
        consentDecision = objectMapper.readValue(consentDecisionSerialised, ConsentDecision.class);
    } catch (IOException e) {
        log.error("Remote consent decisions invalid", e);
        throw new OBErrorException(OBRIErrorType.RCS_CONSENT_DECISIONS_FORMAT, e.getMessage());
    }
    String consentRequestJwt = consentDecision.getConsentJwt();
    if (consentRequestJwt == null || consentRequestJwt.isEmpty() || consentRequestJwt.isBlank()) {
        log.error("Remote consent decisions invalid - consentRequestJwt is null ");
        throw new OBErrorException(OBRIErrorType.RCS_CONSENT_DECISIONS_FORMAT, "consentRequestJwt was null or " + "empty");
    }
    try {
        try {
            log.debug("Received an accept consent request");
            // TODO check token but ignore if it's expired
            // cryptoApiClient.validateJws(consentDecision.getConsentJwt(),
            // amOpenBankingConfiguration.getIssuerID(),  amOpenBankingConfiguration.jwksUri);
            SignedJWT consentContextJwt = (SignedJWT) JWTParser.parse(consentRequestJwt);
            boolean decision = RCSConstants.Decision.ALLOW.equals(consentDecision.getDecision());
            log.debug("The decision is '{}'", decision);
            // here is a good time to actually save that the consent has been approved by our resource owner
            Claims claims = JwsClaimsUtils.getClaims(consentContextJwt);
            String intentId = claims.getIdTokenClaims().get(OpenBankingConstants.IdTokenClaim.INTENT_ID).getValue();
            String csrf = consentContextJwt.getJWTClaimsSet().getStringClaim(RCSConstants.Claims.CSRF);
            String clientId = consentContextJwt.getJWTClaimsSet().getStringClaim(RCSConstants.Claims.CLIENT_ID);
            List<String> scopes = new ArrayList<>(consentContextJwt.getJWTClaimsSet().getJSONObjectClaim(RCSConstants.Claims.SCOPES).keySet());
            String redirectUri = consentContextJwt.getJWTClaimsSet().getStringClaim(OIDCConstants.OIDCClaim.CONSENT_APPROVAL_REDIRECT_URI);
            ConsentDecisionDelegate consentDecisionDelegate = intentTypeService.getConsentDecision(intentId);
            if (consentDecisionDelegate == null) {
                log.error("No Consent Decision Delegate available from the intent type Service.");
                throw new OBErrorException(OBRIErrorType.RCS_CONSENT_REQUEST_INVALID, "Invalid intent ID? '" + intentId + "'");
            }
            // Verify consent is own by the right TPP
            String tppIdBehindConsent = consentDecisionDelegate.getTppIdBehindConsent();
            Optional<Tpp> isTpp = tppStoreService.findById(tppIdBehindConsent);
            if (isTpp.isEmpty()) {
                log.error("The TPP '{}' that created this intent id '{}' doesn't exist anymore.", tppIdBehindConsent, intentId);
                return rcsErrorService.error(OBRIErrorType.RCS_CONSENT_REQUEST_NOT_FOUND_TPP, tppIdBehindConsent, intentId, clientId);
            }
            if (!clientId.equals(isTpp.get().getClientId())) {
                log.error("The TPP '{}' created the account request '{}' but it's TPP '{}' that is trying to get" + " consent for it.", tppIdBehindConsent, intentId, clientId);
                throw new OBErrorException(OBRIErrorType.RCS_CONSENT_REQUEST_INVALID_CONSENT, tppIdBehindConsent, intentId, clientId);
            }
            // Verify consent decision is send by the same user
            Map<String, String> profile = userProfileService.getProfile(ssoToken, amOpenBankingConfiguration.endpointUserProfile, amOpenBankingConfiguration.cookieName);
            String username = profile.get(amOpenBankingConfiguration.userProfileId);
            String userIdBehindConsent = consentDecisionDelegate.getUserIDBehindConsent();
            if (!username.equals(userIdBehindConsent)) {
                log.error("The consent was associated with user '{}' but now, its user '{}' that " + "send the consent decision.", userIdBehindConsent, username);
                throw new OBErrorException(OBRIErrorType.RCS_CONSENT_DECISION_INVALID_USER, userIdBehindConsent, username);
            }
            // Call the right decision delegate, cased on the intent type
            consentDecisionDelegate.consentDecision(consentDecisionSerialised, decision);
            log.debug("Redirect the resource owner to the original oauth2/openid request but this time, with the " + "consent response jwt '{}'.", consentContextJwt.toString());
            String consentJwt = rcsService.generateRCSConsentResponse(rcsConfiguration, amOpenBankingConfiguration, csrf, decision, scopes, clientId);
            ResponseEntity responseEntity = rcsService.sendRCSResponseToAM(ssoToken, RedirectionAction.builder().redirectUri(redirectUri).consentJwt(consentJwt).requestMethod(HttpMethod.POST).build());
            log.debug("Response received from AM: {}", responseEntity);
            if (responseEntity.getStatusCode() != HttpStatus.FOUND) {
                log.error("When sending the consent response {} to AM, it failed to returned a 302. response '{}' ", consentJwt, responseEntity);
                throw new OBErrorException(OBRIErrorType.RCS_CONSENT_RESPONSE_FAILURE);
            } else if (locationContainsError(responseEntity.getHeaders().getLocation())) {
                log.error("When sending the consent response {} to AM, it failed. response '{}' ", consentJwt, responseEntity);
                return rcsErrorService.invalidConsentError(responseEntity.getHeaders().getLocation());
            }
            ResponseEntity rewrittenResponseEntity = null;
            try {
                rewrittenResponseEntity = jwtOverridingService.rewriteIdTokenFragmentInLocationHeader(responseEntity);
            } catch (AccessTokenReWriteException e) {
                log.info("decisionAccountSharing() Failed to re-write id_token", e);
                throw new OBErrorException(OBRIErrorType.RCS_CONSENT_RESPONSE_FAILURE);
            }
            String location = rewrittenResponseEntity.getHeaders().getFirst("Location");
            log.debug("The redirection to the consent page should be in the location '{}'", location);
            return ResponseEntity.ok(RedirectionAction.builder().redirectUri(location).build());
        } catch (JOSEException e) {
            log.error("Could not generate consent context JWT", e);
            throw new OBErrorException(OBRIErrorType.RCS_CONSENT_RESPONSE_FAILURE);
        } catch (ParseException e) {
            log.error("Could not parse the JWT", e);
            throw new OBErrorException(OBRIErrorType.RCS_CONSENT_REQUEST_FORMAT);
        } catch (IOException e) {
            log.error("Remote consent decisions invalid", e);
            throw new OBErrorException(OBRIErrorType.RCS_CONSENT_DECISIONS_FORMAT, e.getMessage());
        }
    } catch (OBErrorException e) {
        return rcsErrorService.invalidConsentError(consentRequestJwt, e);
    }
}
Also used : Claims(com.forgerock.openbanking.model.claim.Claims) ArrayList(java.util.ArrayList) OBErrorException(com.forgerock.openbanking.exceptions.OBErrorException) IOException(java.io.IOException) SignedJWT(com.nimbusds.jwt.SignedJWT) ResponseEntity(org.springframework.http.ResponseEntity) Tpp(com.forgerock.openbanking.model.Tpp) AccessTokenReWriteException(com.forgerock.openbanking.common.error.exception.AccessTokenReWriteException) ConsentDecision(com.forgerock.openbanking.common.model.rcs.consentdecision.ConsentDecision) ParseException(java.text.ParseException) JOSEException(com.nimbusds.jose.JOSEException)

Aggregations

Claims (com.forgerock.openbanking.model.claim.Claims)4 OBErrorException (com.forgerock.openbanking.exceptions.OBErrorException)3 SignedJWT (com.nimbusds.jwt.SignedJWT)3 ParseException (java.text.ParseException)3 JOSEException (com.nimbusds.jose.JOSEException)2 ArrayList (java.util.ArrayList)2 ResponseEntity (org.springframework.http.ResponseEntity)2 ConsentDecisionDelegate (com.forgerock.openbanking.aspsp.rs.rcs.api.rcs.decisions.ConsentDecisionDelegate)1 AccessTokenReWriteException (com.forgerock.openbanking.common.error.exception.AccessTokenReWriteException)1 AccountWithBalance (com.forgerock.openbanking.common.model.openbanking.persistence.account.AccountWithBalance)1 FRAccount (com.forgerock.openbanking.common.model.openbanking.persistence.account.FRAccount)1 ConsentDecision (com.forgerock.openbanking.common.model.rcs.consentdecision.ConsentDecision)1 Tpp (com.forgerock.openbanking.model.Tpp)1 JSONObject (com.nimbusds.jose.shaded.json.JSONObject)1 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)1 IOException (java.io.IOException)1 HttpClientErrorException (org.springframework.web.client.HttpClientErrorException)1