use of org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo in project carbon-apimgt by wso2.
the class JWTValidatorImpl method validateToken.
@Override
public JWTValidationInfo validateToken(SignedJWTInfo signedJWTInfo) throws APIManagementException {
JWTValidationInfo jwtValidationInfo = new JWTValidationInfo();
boolean state;
try {
state = validateSignature(signedJWTInfo.getSignedJWT());
if (state) {
JWTClaimsSet jwtClaimsSet = signedJWTInfo.getJwtClaimsSet();
state = isValidCertificateBoundAccessToken(signedJWTInfo);
if (state) {
state = validateTokenExpiry(jwtClaimsSet);
if (state) {
jwtValidationInfo.setConsumerKey(getConsumerKey(jwtClaimsSet));
jwtValidationInfo.setScopes(getScopes(jwtClaimsSet));
jwtValidationInfo.setAppToken(getIsAppToken(jwtClaimsSet));
JWTClaimsSet transformedJWTClaimSet = transformJWTClaims(jwtClaimsSet);
createJWTValidationInfoFromJWT(jwtValidationInfo, transformedJWTClaimSet);
jwtValidationInfo.setRawPayload(signedJWTInfo.getToken());
return jwtValidationInfo;
} else {
jwtValidationInfo.setValid(false);
jwtValidationInfo.setValidationCode(APIConstants.KeyValidationStatus.API_AUTH_INVALID_CREDENTIALS);
return jwtValidationInfo;
}
} else {
jwtValidationInfo.setValid(false);
jwtValidationInfo.setValidationCode(APIConstants.KeyValidationStatus.API_AUTH_INVALID_CREDENTIALS);
return jwtValidationInfo;
}
} else {
jwtValidationInfo.setValid(false);
jwtValidationInfo.setValidationCode(APIConstants.KeyValidationStatus.API_AUTH_INVALID_CREDENTIALS);
return jwtValidationInfo;
}
} catch (ParseException | JWTGeneratorException e) {
throw new APIManagementException("Error while parsing JWT", e);
}
}
use of org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo in project carbon-apimgt by wso2.
the class JWTValidatorImplTest method testValidateToken.
@Test
@PrepareForTest({ CertificateMgtUtils.class, JWTUtil.class, APIManagerConfiguration.class, ServiceReferenceHolder.class, APIManagerConfigurationService.class, APIUtil.class, X509CertUtils.class })
public void testValidateToken() {
TokenIssuerDto tokenIssuerDto = new TokenIssuerDto("https://localhost:9444/services");
Mockito.when(signedJWT.getHeader()).thenReturn(jwsHeader);
PowerMockito.mockStatic(JWTUtil.class);
byte[] encodedCertificateUnmatched = "aaaaaaaaaaaaaaaa".getBytes();
try {
PowerMockito.when(JWTUtil.verifyTokenSignature(signedJWT, KeyId)).thenReturn(true);
} catch (APIManagementException e) {
log.info("Exception while signature verification. " + e);
Assert.fail();
}
// Create a mock APIManagerConfiguration Object for retrieving properties from the deployment.toml
PowerMockito.mockStatic(ServiceReferenceHolder.class);
PowerMockito.mockStatic(APIManagerConfiguration.class);
PowerMockito.mockStatic(APIManagerConfigurationService.class);
PowerMockito.mockStatic(APIUtil.class);
PowerMockito.mockStatic(CertificateMgtUtils.class);
PowerMockito.mockStatic(X509CertUtils.class);
APIManagerConfiguration apiManagerConfiguration = PowerMockito.mock(APIManagerConfiguration.class);
ServiceReferenceHolder serviceReferenceHolder = PowerMockito.mock(ServiceReferenceHolder.class);
APIManagerConfigurationService apiManagerConfigurationService = PowerMockito.mock(APIManagerConfigurationService.class);
OAuthServerConfiguration oAuthServerConfiguration = Mockito.mock(OAuthServerConfiguration.class);
PowerMockito.when(ServiceReferenceHolder.getInstance()).thenReturn(serviceReferenceHolder);
Mockito.when(serviceReferenceHolder.getAPIManagerConfigurationService()).thenReturn(apiManagerConfigurationService);
Mockito.when(apiManagerConfigurationService.getAPIManagerConfiguration()).thenReturn(apiManagerConfiguration);
Mockito.when(oAuthServerConfiguration.getTimeStampSkewInSeconds()).thenReturn(300L);
Mockito.when(serviceReferenceHolder.getOauthServerConfiguration()).thenReturn(oAuthServerConfiguration);
JWTValidatorImpl jwtValidator = new JWTValidatorImpl();
JWKSConfigurationDTO jwksConfigurationDTO = new JWKSConfigurationDTO();
tokenIssuerDto.setJwksConfigurationDTO(jwksConfigurationDTO);
jwksConfigurationDTO.setEnabled(false);
jwtValidator.loadTokenIssuerConfiguration(tokenIssuerDto);
try {
JWTValidationInfo validatedInfo = jwtValidator.validateToken(signedJWTInfo);
assertTrue(validatedInfo.isValid(), "JWT certificate bound access token validation failed even when the" + " configuration is not enabled.");
} catch (APIManagementException e) {
Assert.fail();
}
// test when certificate is found in the trust store but cnf thumbprint is not matching with the certificate
MessageContext messageContext = Mockito.mock(Axis2MessageContext.class);
org.apache.axis2.context.MessageContext axis2MsgCntxt = Mockito.mock(org.apache.axis2.context.MessageContext.class);
X509Certificate x509Certificate = Mockito.mock(X509Certificate.class);
java.security.cert.X509Certificate x509CertificateJava = Mockito.mock(java.security.cert.X509Certificate.class);
PowerMockito.when(CertificateMgtUtils.convert(x509Certificate)).thenReturn(Optional.of(x509CertificateJava));
X509Certificate[] sslCertObject = new X509Certificate[] { x509Certificate };
Mockito.when(axis2MsgCntxt.getProperty(NhttpConstants.SSL_CLIENT_AUTH_CERT_X509)).thenReturn(sslCertObject);
Map<String, String> headers = new HashMap<>();
Mockito.when(axis2MsgCntxt.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS)).thenReturn(headers);
Mockito.when(((Axis2MessageContext) messageContext).getAxis2MessageContext()).thenReturn(axis2MsgCntxt);
X509Certificate x509CertificateUnMatched = Mockito.mock(X509Certificate.class);
java.security.cert.X509Certificate x509CertificateUnMatchedJava = Mockito.mock(java.security.cert.X509Certificate.class);
PowerMockito.when(CertificateMgtUtils.convert(x509CertificateUnMatched)).thenReturn(Optional.of(x509CertificateUnMatchedJava));
PowerMockito.when(X509CertUtils.computeSHA256Thumbprint(x509CertificateJava)).thenReturn(new Base64URL(CERT_HASH));
PowerMockito.when(X509CertUtils.computeSHA256Thumbprint(x509CertificateUnMatchedJava)).thenReturn(new Base64URL(encodedCertificateUnmatched.toString()));
signedJWTInfo.setX509ClientCertificate(x509CertificateUnMatched);
// Mock the properties read from the deployment.toml
Mockito.when(apiManagerConfiguration.getFirstProperty(APIConstants.ENABLE_CERTIFICATE_BOUND_ACCESS_TOKEN)).thenReturn("true");
try {
JWTValidationInfo validatedInfo = jwtValidator.validateToken(signedJWTInfo);
assertFalse(validatedInfo.isValid(), "JWT certificate bound access token validation successful even if the certificate thumbprint" + " is incorrect.");
} catch (APIManagementException e) {
Assert.fail();
}
// validate with correct certificate thumbprint
signedJWTInfo.setX509ClientCertificate(x509Certificate);
try {
JWTValidationInfo validatedInfo = jwtValidator.validateToken(signedJWTInfo);
assertTrue(validatedInfo.isValid(), "JWT certificate bound access token validation failed with the correct certificate thumbprint.");
} catch (APIManagementException e) {
Assert.fail();
}
// Test when certificate bound access token validation is enabled and cnf thumbprint validation is successful
// when client certificate is added in the trust store
signedJWTInfo.setX509ClientCertificate(null);
headers.put(BASE64_ENCODED_CLIENT_CERTIFICATE_HEADER, BASE64_ENCODED_CERT);
}
use of org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo in project carbon-apimgt by wso2.
the class OAuthJwtAuthenticatorImpl method authenticate.
/**
* @param message cxf message to be authenticated
* @return true if authentication was successful else false
*/
@Override
public boolean authenticate(Message message) throws APIManagementException {
RESTAPICacheConfiguration cacheConfiguration = APIUtil.getRESTAPICacheConfig();
isRESTApiTokenCacheEnabled = cacheConfiguration.isTokenCacheEnabled();
String accessToken = RestApiUtil.extractOAuthAccessTokenFromMessage(message, RestApiConstants.REGEX_BEARER_PATTERN, RestApiConstants.AUTH_HEADER_NAME);
if (StringUtils.countMatches(accessToken, APIConstants.DOT) != 2) {
log.error("Invalid JWT token. The expected token format is <header.payload.signature>");
return false;
}
try {
SignedJWTInfo signedJWTInfo = getSignedJwt(accessToken);
String jwtTokenIdentifier = getJWTTokenIdentifier(signedJWTInfo);
String maskedToken = message.get(RestApiConstants.MASKED_TOKEN).toString();
URL basePath = new URL(message.get(APIConstants.BASE_PATH).toString());
// Validate token
log.debug("Starting JWT token validation " + maskedToken);
JWTValidationInfo jwtValidationInfo = validateJWTToken(signedJWTInfo, jwtTokenIdentifier, accessToken, maskedToken, basePath);
if (jwtValidationInfo != null) {
if (jwtValidationInfo.isValid()) {
if (isRESTApiTokenCacheEnabled) {
getRESTAPITokenCache().put(jwtTokenIdentifier, jwtValidationInfo);
}
// Validating scopes
return handleScopeValidation(message, signedJWTInfo, accessToken);
} else {
log.error("Invalid JWT token :" + maskedToken);
return false;
}
} else {
log.error("Invalid JWT token :" + maskedToken);
return false;
}
} catch (ParseException e) {
log.error("Not a JWT token. Failed to decode the token. Reason: " + e.getMessage());
} catch (MalformedURLException e) {
log.error("Malformed URL found in request path.Reason: " + e.getMessage());
}
return false;
}
use of org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo in project carbon-apimgt by wso2.
the class OAuthJwtAuthenticatorImpl method validateJWTToken.
/**
* Validate the JWT token.
*
* @param jti jwtTokenIdentifier
* @param signedJWTInfo signed jwt info object
* @return JWTValidationInfo : token validated info
*/
@MethodStats
private JWTValidationInfo validateJWTToken(SignedJWTInfo signedJWTInfo, String jti, String accessToken, String maskedToken, URL basePath) throws APIManagementException {
JWTValidationInfo jwtValidationInfo;
String issuer = signedJWTInfo.getJwtClaimsSet().getIssuer();
if (StringUtils.isNotEmpty(issuer)) {
// validate Issuer
List<String> tokenAudiences = signedJWTInfo.getJwtClaimsSet().getAudience();
if (tokenIssuers != null && tokenIssuers.containsKey(issuer)) {
// validate audience
if (audiencesMap != null && audiencesMap.get(basePath.getPath()) != null && tokenAudiences.stream().anyMatch(audiencesMap.get(basePath.getPath())::contains)) {
if (isRESTApiTokenCacheEnabled) {
JWTValidationInfo tempJWTValidationInfo = (JWTValidationInfo) getRESTAPITokenCache().get(jti);
if (tempJWTValidationInfo != null) {
Boolean isExpired = checkTokenExpiration(new Date(tempJWTValidationInfo.getExpiryTime()));
if (isExpired) {
tempJWTValidationInfo.setValid(false);
getRESTAPITokenCache().remove(jti);
getRESTAPIInvalidTokenCache().put(jti, tempJWTValidationInfo);
log.error("JWT token validation failed. Reason: Expired Token. " + maskedToken);
return tempJWTValidationInfo;
}
// check accessToken
if (!tempJWTValidationInfo.getRawPayload().equals(accessToken)) {
tempJWTValidationInfo.setValid(false);
getRESTAPITokenCache().remove(jti);
getRESTAPIInvalidTokenCache().put(jti, tempJWTValidationInfo);
log.error("JWT token validation failed. Reason: Invalid Token. " + maskedToken);
return tempJWTValidationInfo;
}
return tempJWTValidationInfo;
} else if (getRESTAPIInvalidTokenCache().get(jti) != null) {
if (log.isDebugEnabled()) {
log.debug("Token retrieved from the invalid token cache. Token: " + maskedToken);
}
return (JWTValidationInfo) getRESTAPIInvalidTokenCache().get(jti);
}
}
// info not in cache. validate signature and exp
JWTValidator jwtValidator = APIMConfigUtil.getJWTValidatorMap().get(issuer);
jwtValidationInfo = jwtValidator.validateToken(signedJWTInfo);
if (jwtValidationInfo.isValid()) {
// valid token
if (isRESTApiTokenCacheEnabled) {
getRESTAPITokenCache().put(jti, jwtValidationInfo);
}
} else {
// put in invalid cache
if (isRESTApiTokenCacheEnabled) {
getRESTAPIInvalidTokenCache().put(jti, jwtValidationInfo);
}
// invalid credentials : 900901 error code
log.error("JWT token validation failed. Reason: Invalid Credentials. " + "Make sure you have provided the correct security credentials in the token :" + maskedToken);
}
} else {
if (audiencesMap == null) {
log.error("JWT token audience validation failed. Reason: No audiences registered " + "in the server");
} else if (audiencesMap.get(basePath.getPath()) == null) {
log.error("JWT token audience validation failed. Reason: No audiences registered " + "in the server for the base path (" + basePath.getPath() + ")");
} else {
log.error("JWT token audience validation failed. Reason: None of the aud present " + "in the JWT (" + tokenAudiences.toString() + ") matches the intended audience (" + audiencesMap.get(basePath.getPath()).toString() + ") for base path ( " + basePath.getPath() + " ).");
}
return null;
}
} else {
// invalid issuer. invalid token
log.error("JWT token issuer validation failed. Reason: Issuer present in the JWT (" + issuer + ") does not match with the token issuer (" + tokenIssuers.keySet().toString() + ")");
return null;
}
} else {
log.error("Issuer is not found in the token " + maskedToken);
return null;
}
return jwtValidationInfo;
}
use of org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo in project carbon-apimgt by wso2.
the class JWTValidator method getUserClaimsFromKeyManager.
private Map<String, String> getUserClaimsFromKeyManager(JWTInfoDto jwtInfoDto) {
if (jwtConfigurationDto.isEnableUserClaimRetrievalFromUserStore()) {
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
JWTValidationInfo jwtValidationInfo = jwtInfoDto.getJwtValidationInfo();
if (jwtValidationInfo != null) {
KeyManager keyManagerInstance = KeyManagerHolder.getKeyManagerInstance(tenantDomain, jwtValidationInfo.getKeyManager());
if (keyManagerInstance != null) {
Map<String, Object> properties = new HashMap<>();
if (jwtValidationInfo.getRawPayload() != null) {
properties.put(APIConstants.KeyManager.ACCESS_TOKEN, jwtValidationInfo.getRawPayload());
}
if (!StringUtils.isEmpty(jwtConfigurationDto.getConsumerDialectUri())) {
properties.put(APIConstants.KeyManager.CLAIM_DIALECT, jwtConfigurationDto.getConsumerDialectUri());
}
properties.put(APIConstants.KeyManager.BINDING_FEDERATED_USER_CLAIMS, jwtConfigurationDto.isBindFederatedUserClaims());
try {
return keyManagerInstance.getUserClaims(jwtInfoDto.getEndUser(), properties);
} catch (APIManagementException e) {
log.error("Error while retrieving User claims from Key Manager ", e);
}
}
}
}
return new HashMap<>();
}
Aggregations