use of com.forgerock.openbanking.jwt.exceptions.InvalidTokenException in project openbanking-aspsp by OpenBankingToolkit.
the class TppRegistrationService method validateSsaAgainstIssuingDirectoryJwksUri.
public String validateSsaAgainstIssuingDirectoryJwksUri(String ssaSerialised, String issuer) throws DynamicClientRegistrationException {
log.debug("validateSsaAgainstIssuingDirectoryJwksUri(): issuer is {}", issuer);
if (ssaSerialised == null) {
return null;
}
if (issuer.equals(openBankingDirectoryConfiguration.issuerId)) {
try {
log.debug("validateSsaAgainstIssuingDirectoryJwksUri() Verify the SSA against OB directory");
cryptoApiClient.validateJws(ssaSerialised, openBankingDirectoryConfiguration.getIssuerID(), openBankingDirectoryConfiguration.jwksUri);
return openBankingDirectoryConfiguration.id;
} catch (InvalidTokenException | HttpClientErrorException | ParseException | IOException e) {
log.debug("validateSsaAgainstIssuingDirectoryJwksUri() Invalid SSA signature from OB directory", e);
}
} else if (issuer.equals(forgeRockDirectoryConfiguration.getIssuerID())) {
try {
log.debug("validateSsaAgainstIssuingDirectoryJwksUri() Verify the SSA against ForgeRock directory");
cryptoApiClient.validateJws(ssaSerialised, null, forgeRockDirectoryConfiguration.jwksUri);
return forgeRockDirectoryConfiguration.id;
} catch (InvalidTokenException | ParseException | IOException e) {
log.debug("validateSsaAgainstIssuingDirectoryJwksUri() Invalid SSA signature from ForgeRock directory", e);
}
} else {
String errorMessage = "Unrecognised ssa. Issuer is '" + issuer + "'. Please use an Open Banking issued " + "SSA.";
log.debug("validateSsaAgainstIssuingDirectoryJwksUri() {}", errorMessage);
throw new DynamicClientRegistrationException(errorMessage, DynamicClientRegistrationErrorType.UNAPPROVED_SOFTWARE_STATEMENT);
}
return null;
}
use of com.forgerock.openbanking.jwt.exceptions.InvalidTokenException in project openbanking-aspsp by OpenBankingToolkit.
the class DetachedJwsVerifier method verifyDetachedJws.
public void verifyDetachedJws(String detachedJws, OBVersion obVersion, HttpServletRequest request, String oauth2ClientId) throws OBErrorException {
if (StringUtils.isEmpty(detachedJws)) {
log.warn("Detached signature not provided");
throw new OBErrorException(OBRIErrorType.DETACHED_JWS_INVALID, detachedJws, "Not provided");
}
try {
MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest(request);
String body = multiReadRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
log.debug("Verify detached signature {} with payload {}", detachedJws, body);
// obVersion is only set from 3.1.3 onwards
if ((obVersion == null || obVersion.isBeforeVersion(v3_1_4)) && isBase64Encoded(detachedJws)) {
log.warn("Invalid detached signature {}, {}", detachedJws, "b64 claim header not set to false in version: " + obVersion);
throw new OBErrorException(OBRIErrorType.DETACHED_JWS_INVALID, detachedJws, "b64 claim header not set to false");
}
if (obVersion != null && obVersion.isAfterVersion(v3_1_3) && isB64ClaimHeaderPresent(detachedJws)) {
log.warn("Invalid detached signature {}, {}", detachedJws, "b64 claim header must not be present in version: " + obVersion);
throw new OBErrorException(OBRIErrorType.DETACHED_JWS_INVALID, detachedJws, "b64 claim header must not be present");
}
Tpp tpp = tppStoreService.findByClientId(oauth2ClientId).get();
DirectorySoftwareStatement softwareStatement = tpp.getDirectorySoftwareStatement();
String orgId = softwareStatement.getOrg_id();
String softwareId = softwareStatement.getSoftware_id();
String expectedIssuer = orgId + "/" + softwareId;
if (tpp.getRegistrationResponse().getJwks() != null) {
cryptoApiClient.validateDetachedJWSWithJWK(detachedJws, body, null, expectedIssuer, tpp.getRegistrationResponse().getJwks().getKeys().get(0));
} else {
cryptoApiClient.validateDetachedJWS(detachedJws, body, null, expectedIssuer, tpp.getRegistrationResponse().getJwks_uri());
}
} catch (InvalidTokenException e) {
log.warn("Invalid detached signature {}", detachedJws, e);
throw new OBErrorException(OBRIErrorType.DETACHED_JWS_INVALID, detachedJws, e.getMessage());
} catch (IOException e) {
log.error("Can't get the request body", e);
throw new OBErrorException(OBRIErrorType.DETACHED_JWS_UN_ACCESSIBLE);
} catch (ParseException e) {
log.error("Can't parse JWS", e);
throw new OBErrorException(OBRIErrorType.DETACHED_JWS_INVALID, detachedJws, e.getMessage());
}
}
use of com.forgerock.openbanking.jwt.exceptions.InvalidTokenException in project openbanking-aspsp by OpenBankingToolkit.
the class AuthorisationApiController method validateRequestParameter.
private SignedJWT validateRequestParameter(String responseType, String clientId, String state, String nonce, String scopes, String redirectUri, String requestParametersSerialised) throws OBErrorException {
SignedJWT requestParameters;
try {
try {
EncryptedJWT.parse(requestParametersSerialised);
log.debug("Request parameter {} is encrypted (JWE).", requestParametersSerialised);
requestParameters = cryptoApiClient.decryptJwe(requestParametersSerialised);
requestParametersSerialised = requestParameters.serialize();
log.debug("Request parameter {} decrypted (JWS).", requestParametersSerialised);
} catch (ParseException | JOSEException e) {
// If we got an exception, it means it's a JWS
log.debug("Request parameter {} is just signed (JWS).", requestParametersSerialised);
requestParameters = SignedJWT.parse(requestParametersSerialised);
}
verifyQueryParameterMatchesRequestParameterClaim(requestParameters, "client_id", clientId);
Optional<Tpp> byClientId = tppStoreService.findByClientId(clientId);
if (byClientId.isEmpty()) {
throw new OBErrorException(OBRIErrorType.REQUEST_PARAMETER_JWT_FORMAT_INVALID, "Unknown client id '" + clientId + "'");
}
Tpp tpp = byClientId.get();
log.debug("Validate the request parameter signature");
boolean validated = false;
OIDCRegistrationResponse registrationResponse = tpp.getRegistrationResponse();
if (registrationResponse != null) {
JWKSet jwkSet = registrationResponse.getJwks();
if (jwkSet != null) {
List<JWK> jwkSetKeys = jwkSet.getKeys();
if (jwkSetKeys != null && !jwkSetKeys.isEmpty()) {
JWK jwk = jwkSetKeys.get(0);
String jwksKeys = jwk.toString();
log.debug("validateRequestParameters() tpp has jwksKeys as part of registraiton. They will be" + " used to validate the request parameter.");
cryptoApiClient.validateJwsWithJWK(requestParametersSerialised, clientId, jwksKeys);
validated = true;
} else {
log.debug("validateRequestParameter() tpp has no jwkSetKeys; {}", tpp);
}
}
if (!validated) {
String jwks_uri = tpp.getRegistrationResponse().getJwks_uri();
if (jwks_uri == null || jwks_uri.isBlank()) {
log.error("validateRequestparameters() tpp does no have a jwksKeys, or a jwks_uri in it's " + "registration details; {}", tpp);
throw new InvalidTokenException("Tpp does no have a jwksKeys, or a jwks_uri in it's " + "registration details");
} else {
log.debug("validateRequestParameter() Validating request parameter using jwks_uri: " + "requestParametersSerialised: '{}', clientId; '{}', jwks_url: {}", requestParametersSerialised, clientId, jwks_uri);
cryptoApiClient.validateJws(requestParametersSerialised, clientId, jwks_uri);
validated = true;
}
}
} else {
log.error("validateRequestParameter() tpp has no registration response; {}", tpp);
throw new InvalidTokenException("Tpp is not registered");
}
List<String> MANDATORY_CLAIMS = Arrays.asList(OpenBankingConstants.RequestParameterClaim.AUD, OpenBankingConstants.RequestParameterClaim.SCOPE, OpenBankingConstants.RequestParameterClaim.ISS, OpenBankingConstants.RequestParameterClaim.CLAIMS, OpenBankingConstants.RequestParameterClaim.RESPONSE_TYPE, OpenBankingConstants.RequestParameterClaim.REDIRECT_URI, OpenBankingConstants.RequestParameterClaim.EXP, OpenBankingConstants.RequestParameterClaim.NONCE, OpenBankingConstants.RequestParameterClaim.CLIENT_ID);
for (String mandatoryClaim : MANDATORY_CLAIMS) {
if (requestParameters.getJWTClaimsSet().getClaim(mandatoryClaim) == null) {
throw new OBErrorException(OBRIErrorType.REQUEST_PARAMETER_CLAIM_MANDATORY, mandatoryClaim);
}
}
verifyQueryParameterMatchesRequestParameterClaim(requestParameters, "response_type", responseType);
verifyQueryParameterMatchesRequestParameterClaim(requestParameters, "state", state);
verifyQueryParameterMatchesRequestParameterClaim(requestParameters, "nonce", nonce);
verifyQueryParameterMatchesRequestParameterClaim(requestParameters, "redirect_uri", redirectUri);
verifyScopeQueryParameterMatchesRequestParameterClaim(requestParameters, scopes);
verifyRequestparameterClaims(requestParameters);
} catch (ParseException | IOException e) {
log.error("Invalid Request parameter {}. Reason: {}", requestParametersSerialised, e.getMessage(), e);
throw new OBErrorException(OBRIErrorType.REQUEST_PARAMETER_JWT_FORMAT_INVALID, e.getMessage());
} catch (InvalidTokenException e) {
log.error("Invalid Request parameter {}. Reason: {}", requestParametersSerialised, e.getMessage(), e);
throw new OBErrorException(OBRIErrorType.REQUEST_PARAMETER_JWT_INVALID, e.getMessage());
}
return requestParameters;
}
use of com.forgerock.openbanking.jwt.exceptions.InvalidTokenException in project openbanking-aspsp by OpenBankingToolkit.
the class RSEndpointWrapper method verifyAccessToken.
public void verifyAccessToken(List<String> expectedScopes, List<OIDCConstants.GrantType> expectedGrantTypes) throws OBErrorException {
try {
// Verify access token
log.info("Verify the access token {}", authorization);
accessToken = rsEndpointWrapperService.verifyAccessToken(authorization);
String grantTypeSerialised = accessToken.getJWTClaimsSet().getStringClaim(OBConstants.OIDCClaim.GRANT_TYPE);
if (grantTypeSerialised == null) {
log.error("We managed to get an access token that doesn't have a grant type claim defined: {}", authorization);
throw new OBErrorException(SERVER_ERROR, "Access token grant type is undefined");
}
OIDCConstants.GrantType grantType = OIDCConstants.GrantType.fromType(grantTypeSerialised);
if (!OIDCConstants.GrantType.REFRESH_TOKEN.equals(grantType) && !expectedGrantTypes.contains(grantType)) {
log.debug("The access token grant type {} doesn't match one of the expected grant types {}", grantType, expectedGrantTypes);
throw new OBErrorException(OBRIErrorType.ACCESS_TOKEN_INVALID_GRANT_TYPE, grantType, expectedGrantTypes);
}
List<String> scopes = (List<String>) accessToken.getJWTClaimsSet().getClaim(OBConstants.OIDCClaim.SCOPE);
if (!scopes.containsAll(expectedScopes)) {
log.warn("The access token {} doesn't contain the scope {}", authorization, expectedScopes);
throw new OBErrorException(OBRIErrorType.ACCESS_TOKEN_INVALID_SCOPE, expectedScopes);
}
} catch (ParseException e) {
log.warn("Couldn't parse the the access token {}. It's probably not stateless and therefore, not " + "an access token generated by our ASPSP-AS", authorization);
throw new OBErrorException(OBRIErrorType.ACCESS_TOKEN_INVALID_FORMAT);
} catch (InvalidTokenException e) {
log.warn("Invalid access token {}", authorization);
throw new OBErrorException(OBRIErrorType.ACCESS_TOKEN_INVALID, e.getMessage());
} catch (IOException e) {
log.error("IO exception", e);
throw new OBErrorException(SERVER_ERROR, e.getMessage());
}
}
use of com.forgerock.openbanking.jwt.exceptions.InvalidTokenException in project openbanking-aspsp by OpenBankingToolkit.
the class AggregatedPollingApiEndpointWrapper method verifyAccessToken.
@Override
public void verifyAccessToken(List<String> expectedScopes, List<OIDCConstants.GrantType> expectedGrantTypes) throws OBErrorException {
try {
// Verify access token
log.info("Verify the access token {}", authorization);
accessToken = rsEndpointWrapperService.amResourceServerService.verifyAccessToken(authorization);
List<String> scopes = (List<String>) accessToken.getJWTClaimsSet().getClaim(OBConstants.OIDCClaim.SCOPE);
String grantTypeSerialised = accessToken.getJWTClaimsSet().getStringClaim(OBConstants.OIDCClaim.GRANT_TYPE);
if (grantTypeSerialised == null) {
log.error("We managed to get an access token that doesn't have a grant type claim defined: {}", authorization);
throw new OBErrorException(SERVER_ERROR, "Access token grant type is undefined");
}
OIDCConstants.GrantType grantType = OIDCConstants.GrantType.fromType(grantTypeSerialised);
if (!OIDCConstants.GrantType.REFRESH_TOKEN.equals(grantType) && !expectedGrantTypes.contains(grantType)) {
log.debug("The access token grant type {} doesn't match one of the expected grant types {}", grantType, expectedGrantTypes);
throw new OBErrorException(OBRIErrorType.ACCESS_TOKEN_INVALID_GRANT_TYPE, grantType, expectedGrantTypes);
}
if (scopes.stream().noneMatch(expectedScopes::contains)) {
log.warn("The access token {} contains scopes: {} but needs at least one of the expected scopes: {}", authorization, scopes, expectedScopes);
throw new OBErrorException(OBRIErrorType.ACCESS_TOKEN_INVALID_SCOPE, expectedScopes);
}
} catch (ParseException e) {
log.warn("Couldn't parse the the access token {}. It's probably not stateless and therefore, not " + "an access token generated by our ASPSP-AS", authorization);
throw new OBErrorException(OBRIErrorType.ACCESS_TOKEN_INVALID_FORMAT);
} catch (InvalidTokenException e) {
log.warn("Invalid access token {}", authorization);
throw new OBErrorException(OBRIErrorType.ACCESS_TOKEN_INVALID, e.getMessage());
} catch (IOException e) {
log.error("IO exception", e);
throw new OBErrorException(SERVER_ERROR, e.getMessage());
}
}
Aggregations