use of com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken in project athenz by yahoo.
the class DefaultOAuthJwtAccessTokenParserTest method testParse.
@Test
@SuppressWarnings("rawtypes")
public void testParse() throws Exception {
// mock internal parser
DefaultOAuthJwtAccessTokenParser parser = new DefaultOAuthJwtAccessTokenParser(baseKeyStore, this.classLoader.getResource("jwt_jwks.json").toString());
JwtParser jwtParserMock = Mockito.mock(JwtParser.class);
Field f = parser.getClass().getDeclaredField("parser");
f.setAccessible(true);
f.set(parser, jwtParserMock);
// parse error
Mockito.when(jwtParserMock.parseClaimsJws(null)).thenThrow(new NullPointerException());
assertThrows(OAuthJwtAccessTokenException.class, () -> parser.parse(null));
// parse success
String jwtString = "dummy-jwt-string";
Jws<Claims> jws = new Jws<Claims>() {
public JwsHeader getHeader() {
return null;
}
public Claims getBody() {
return null;
}
@Override
public String getSignature() {
return "dummy-jwt-signature";
}
};
Mockito.when(jwtParserMock.parseClaimsJws(jwtString)).thenReturn(jws);
OAuthJwtAccessToken token = parser.parse(jwtString);
assertNotNull(token);
assertTrue(token instanceof DefaultOAuthJwtAccessToken);
assertEquals(token.getSignature(), "dummy-jwt-signature");
}
use of com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken in project athenz by yahoo.
the class OAuthCertBoundJwtAccessTokenAuthority method authenticate.
/**
* Process the authenticate request based on http request object.
* Skip if access token not exists or cannot be extracted.
* Fail if it is not mTLS.
* @param request http servlet request
* @param errMsg will contain error message if authenticate fails
* @return the Principal for the certificate, or null in case of failure.
*/
@Override
public Principal authenticate(HttpServletRequest request, StringBuilder errMsg) {
errMsg = errMsg == null ? new StringBuilder(512) : errMsg;
// extract credentials from request
String jwsString = OAuthAuthorityUtils.extractHeaderToken(request);
// skip when no credentials provided
if (jwsString == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("OAuthCertBoundJwtAccessTokenAuthority:authenticate: no credentials, skip...");
}
return null;
}
// parse certificate
CertificateIdentity certificateIdentity = null;
try {
certificateIdentity = this.certificateIdentityParser.parse(request);
} catch (CertificateIdentityException e) {
this.reportError("OAuthCertBoundJwtAccessTokenAuthority:authenticate: invalid certificate: " + e.getMessage(), errMsg);
return null;
}
X509Certificate clientCert = certificateIdentity.getX509Certificate();
String clientCertPrincipal = certificateIdentity.getPrincipalName();
// parse JWT
OAuthJwtAccessToken at = null;
try {
at = this.parser.parse(jwsString);
} catch (OAuthJwtAccessTokenException e) {
this.reportError("OAuthCertBoundJwtAccessTokenAuthority:authenticate: invalid JWT: " + e.getMessage(), errMsg);
return null;
}
// validate JWT
try {
this.validator.validate(at);
this.validator.validateClientId(at, clientCertPrincipal);
if (this.shouldVerifyCertThumbprint) {
String clientCertThumbprint = this.validator.getX509CertificateThumbprint(clientCert);
this.validator.validateCertificateBinding(at, clientCertThumbprint);
}
} catch (CertificateEncodingException | CryptoException | OAuthJwtAccessTokenException e) {
this.reportError("OAuthCertBoundJwtAccessTokenAuthority:authenticate: invalid JWT: " + e.getMessage(), errMsg);
return null;
}
// create principal
String[] ds = AthenzUtils.splitPrincipalName(at.getSubject());
if (ds == null) {
errMsg.append("OAuthCertBoundJwtAccessTokenAuthority:authenticate: sub is not a valid service identity: got=").append(at.getSubject());
return null;
}
String domain = ds[0];
String service = ds[1];
SimplePrincipal principal = (SimplePrincipal) SimplePrincipal.create(domain, service, jwsString, at.getIssuedAt(), this);
principal.setUnsignedCreds(at.toString());
principal.setX509Certificate(clientCert);
// principal.setRoles(at.getScopes());
principal.setApplicationId(clientCertPrincipal);
principal.setAuthorizedService(this.authorizedServices.getOrDefault(clientCertPrincipal, clientCertPrincipal));
if (LOG.isDebugEnabled()) {
LOG.debug("OAuthCertBoundJwtAccessTokenAuthority.authenticate: client certificate name={}", clientCertPrincipal);
LOG.debug("OAuthCertBoundJwtAccessTokenAuthority.authenticate: valid user={}", principal.toString());
LOG.debug("OAuthCertBoundJwtAccessTokenAuthority.authenticate: unsignedCredentials={}", principal.getUnsignedCredentials());
LOG.debug("OAuthCertBoundJwtAccessTokenAuthority.authenticate: credentials={}", principal.getCredentials());
}
return principal;
}
use of com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken in project athenz by yahoo.
the class DefaultOAuthJwtAccessTokenValidatorTest method testValidateClientId.
@Test
public void testValidateClientId() {
final DefaultOAuthJwtAccessTokenValidator validator = this.baseValidator;
final OAuthJwtAccessToken mock = Mockito.spy(baseJwt);
Mockito.doReturn(null).when(mock).getClientId();
// null JWT client ID, null CN, invalid
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, null);
}
}, "NO mapping of authorized client IDs for certificate principal (null)");
// null JWT client ID ONLY, no mapping
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "no_mapping_1");
}
}, "NO mapping of authorized client IDs for certificate principal (no_mapping_1)");
// null JWT client ID ONLY, mapped
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "client_cert_common_name");
}
}, "client_id is not authorized for certificate principal (client_cert_common_name): got=null");
Mockito.doReturn("jwt_client_id").when(mock).getClientId();
// null expected client ID ONLY, no mapping
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, null);
}
}, "NO mapping of authorized client IDs for certificate principal (null)");
// null expected client ID ONLY, mapped
authorizedClientIds.put(null, new HashSet<>(Arrays.asList("null_1, null_2")));
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, null);
}
}, "client_id is not authorized for certificate principal (null): got=jwt_client_id");
authorizedClientIds.remove(null);
// not match, no mapping
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "no_mapping_2");
}
}, "NO mapping of authorized client IDs for certificate principal (no_mapping_2)");
// not match, mapped
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "client_cert_common_name");
}
}, "client_id is not authorized for certificate principal (client_cert_common_name): got=jwt_client_id");
// match, no mapping
Mockito.doReturn("match.principal.1").when(mock).getClientId();
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "match.principal.1");
}
}, "NO mapping of authorized client IDs for certificate principal (match.principal.1)");
// match, mapped
Mockito.doReturn("client_id_1").when(mock).getClientId();
assertDoesNotThrow.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "client_cert_common_name");
}
});
// no mapping, case-insensitive, match, invalid
Mockito.doReturn("match.principal.PPP").when(mock).getClientId();
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "match.principal.ppp");
}
}, "NO mapping of authorized client IDs for certificate principal (match.principal.ppp)");
// mapped, case-sensitive, match
Mockito.doReturn("CLIENT_ID_2").when(mock).getClientId();
assertDoesNotThrow.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "client_cert_common_name");
}
});
// mapped, case-sensitive, not match
Mockito.doReturn("client_id_2").when(mock).getClientId();
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateClientId(mock, "client_cert_common_name");
}
}, "client_id is not authorized for certificate principal (client_cert_common_name): got=client_id_2");
}
use of com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken in project athenz by yahoo.
the class DefaultOAuthJwtAccessTokenValidatorTest method testValidateVerifyAudiences.
@Test
public void testValidateVerifyAudiences() {
final DefaultOAuthJwtAccessTokenValidator validator = this.baseValidator;
final OAuthJwtAccessToken mock = Mockito.spy(baseJwt);
Mockito.doReturn(this.trustedIssuer).when(mock).getIssuer();
Mockito.doReturn(new ArrayList<>(this.requiredScopes)).when(mock).getScopes();
Mockito.doReturn(1L).when(mock).getExpiration();
// null JWT issuer
Mockito.doReturn(null).when(mock).getAudiences();
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validate(mock);
}
}, "required aud not found: got=null");
// empty
Mockito.doReturn(new ArrayList<>()).when(mock).getAudiences();
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validate(mock);
}
}, "required aud not found: got=");
// not match
Mockito.doReturn(Arrays.asList("aud_1", "unknown_aud")).when(mock).getAudiences();
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validate(mock);
}
}, "required aud not found: got=aud_1, unknown_aud");
// match
Mockito.doReturn(Arrays.asList("aud_3", "aud_2", "aud_1")).when(mock).getAudiences();
assertDoesNotThrow.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validate(mock);
}
});
}
use of com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken in project athenz by yahoo.
the class DefaultOAuthJwtAccessTokenValidatorTest method testValidateCertificateBinding.
@Test
public void testValidateCertificateBinding() {
final DefaultOAuthJwtAccessTokenValidator validator = this.baseValidator;
final OAuthJwtAccessToken mock = Mockito.spy(baseJwt);
Mockito.doReturn(null).when(mock).getCertificateThumbprint();
// null JWT thumbprint, null expected certificate thumbprint
assertDoesNotThrow.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateCertificateBinding(mock, (String) null);
}
});
// null JWT thumbprint ONLY
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateCertificateBinding(mock, "certificate_thumbprint");
}
}, "client certificate thumbprint (certificate_thumbprint) not match: got=null");
Mockito.doReturn("certificate_thumbprint").when(mock).getCertificateThumbprint();
// null expected certificate thumbprint ONLY
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateCertificateBinding(mock, (String) null);
}
}, "client certificate thumbprint (null) not match: got=certificate_thumbprint");
// not match
assertThrowable.accept(new ThrowingRunnable() {
public void run() throws Throwable {
validator.validateCertificateBinding(mock, "not_match");
}
}, "client certificate thumbprint (not_match) not match: got=certificate_thumbprint");
// match
assertDoesNotThrow.accept(new ThrowingRunnable() {
public void run() throws Throwable {
// for coverage
validator.validateCertificateBinding(mock, new String("certificate_thumbprint"));
}
});
}
Aggregations