Search in sources :

Example 1 with OAuthJwtAccessToken

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");
}
Also used : JwtParser(io.jsonwebtoken.JwtParser) Field(java.lang.reflect.Field) Claims(io.jsonwebtoken.Claims) DefaultOAuthJwtAccessToken(com.yahoo.athenz.auth.oauth.token.DefaultOAuthJwtAccessToken) OAuthJwtAccessToken(com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken) DefaultOAuthJwtAccessToken(com.yahoo.athenz.auth.oauth.token.DefaultOAuthJwtAccessToken) Jws(io.jsonwebtoken.Jws) Test(org.testng.annotations.Test)

Example 2 with OAuthJwtAccessToken

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;
}
Also used : OAuthJwtAccessToken(com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken) CertificateIdentity(com.yahoo.athenz.auth.impl.CertificateIdentity) OAuthJwtAccessTokenException(com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessTokenException) CertificateEncodingException(java.security.cert.CertificateEncodingException) CryptoException(com.yahoo.athenz.auth.util.CryptoException) CertificateIdentityException(com.yahoo.athenz.auth.impl.CertificateIdentityException) X509Certificate(java.security.cert.X509Certificate) SimplePrincipal(com.yahoo.athenz.auth.impl.SimplePrincipal)

Example 3 with OAuthJwtAccessToken

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");
}
Also used : OAuthJwtAccessToken(com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken) ThrowingRunnable(org.testng.Assert.ThrowingRunnable) Test(org.testng.annotations.Test)

Example 4 with OAuthJwtAccessToken

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);
        }
    });
}
Also used : OAuthJwtAccessToken(com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken) ThrowingRunnable(org.testng.Assert.ThrowingRunnable) Test(org.testng.annotations.Test)

Example 5 with OAuthJwtAccessToken

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"));
        }
    });
}
Also used : OAuthJwtAccessToken(com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken) ThrowingRunnable(org.testng.Assert.ThrowingRunnable) Test(org.testng.annotations.Test)

Aggregations

OAuthJwtAccessToken (com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessToken)11 Test (org.testng.annotations.Test)9 ThrowingRunnable (org.testng.Assert.ThrowingRunnable)6 DefaultOAuthJwtAccessToken (com.yahoo.athenz.auth.oauth.token.DefaultOAuthJwtAccessToken)2 OAuthJwtAccessTokenException (com.yahoo.athenz.auth.oauth.token.OAuthJwtAccessTokenException)2 CryptoException (com.yahoo.athenz.auth.util.CryptoException)2 Claims (io.jsonwebtoken.Claims)2 CertificateEncodingException (java.security.cert.CertificateEncodingException)2 X509Certificate (java.security.cert.X509Certificate)2 CertificateIdentity (com.yahoo.athenz.auth.impl.CertificateIdentity)1 CertificateIdentityException (com.yahoo.athenz.auth.impl.CertificateIdentityException)1 SimplePrincipal (com.yahoo.athenz.auth.impl.SimplePrincipal)1 Jws (io.jsonwebtoken.Jws)1 JwtParser (io.jsonwebtoken.JwtParser)1 Field (java.lang.reflect.Field)1