Search in sources :

Example 1 with JWKSource

use of com.nimbusds.jose.jwk.source.JWKSource in project dhis2-core by dhis2.

the class JwtBearerTokenTest method setUpClass.

@BeforeAll
static void setUpClass() throws JOSEException {
    DhisWebApiWebSecurityConfig.setApiContextPath("");
    JWKSource<SecurityContext> jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(new JWKSet(ImmutableList.of(RSA_KEY)));
    jwsEncoder = new JwtUtils(jwkSource);
    jwtDecoder = NimbusJwtDecoder.withPublicKey(RSA_KEY.toRSAPublicKey()).build();
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) SecurityContext(com.nimbusds.jose.proc.SecurityContext) ConfigurationKey(org.hisp.dhis.external.conf.ConfigurationKey) NimbusJwtDecoder(org.springframework.security.oauth2.jwt.NimbusJwtDecoder) Contracts.assertNotNull(org.hibernate.validator.internal.util.Contracts.assertNotNull) JOSEException(com.nimbusds.jose.JOSEException) Autowired(org.springframework.beans.factory.annotation.Autowired) DhisOidcProviderRepository(org.hisp.dhis.security.oidc.DhisOidcProviderRepository) JWKSet(com.nimbusds.jose.jwk.JWKSet) JwtClaimsSet(org.hisp.dhis.webapi.security.utils.JwtClaimsSet) TestJwks(org.hisp.dhis.webapi.security.utils.TestJwks) TestJwtClaimsSets(org.hisp.dhis.webapi.security.utils.TestJwtClaimsSets) Dhis2JwtAuthenticationManagerResolver(org.hisp.dhis.security.jwt.Dhis2JwtAuthenticationManagerResolver) ImmutableList(com.google.common.collect.ImmutableList) BeforeAll(org.junit.jupiter.api.BeforeAll) JsonError(org.hisp.dhis.webapi.json.domain.JsonError) DhisWebApiWebSecurityConfig(org.hisp.dhis.webapi.security.config.DhisWebApiWebSecurityConfig) JoseHeaderNames(org.hisp.dhis.webapi.security.utils.JoseHeaderNames) User(org.hisp.dhis.user.User) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) JwtTokenHeader(org.hisp.dhis.webapi.WebClient.JwtTokenHeader) Jwt(org.springframework.security.oauth2.jwt.Jwt) JsonUser(org.hisp.dhis.webapi.json.domain.JsonUser) JWKSource(com.nimbusds.jose.jwk.source.JWKSource) Properties(java.util.Properties) TestJoseHeaders(org.hisp.dhis.webapi.security.utils.TestJoseHeaders) JoseHeader(org.hisp.dhis.webapi.security.utils.JoseHeader) DhisControllerWithJwtTokenAuthTest(org.hisp.dhis.webapi.DhisControllerWithJwtTokenAuthTest) GenericOidcProviderConfigParser(org.hisp.dhis.security.oidc.GenericOidcProviderConfigParser) Test(org.junit.jupiter.api.Test) HttpStatus(org.springframework.http.HttpStatus) RSAKey(com.nimbusds.jose.jwk.RSAKey) JwtUtils(org.hisp.dhis.webapi.security.utils.JwtUtils) DhisOidcClientRegistration(org.hisp.dhis.security.oidc.DhisOidcClientRegistration) GoogleProvider(org.hisp.dhis.security.oidc.provider.GoogleProvider) JWKSet(com.nimbusds.jose.jwk.JWKSet) SecurityContext(com.nimbusds.jose.proc.SecurityContext) JwtUtils(org.hisp.dhis.webapi.security.utils.JwtUtils) BeforeAll(org.junit.jupiter.api.BeforeAll)

Example 2 with JWKSource

use of com.nimbusds.jose.jwk.source.JWKSource in project dhis2-core by dhis2.

the class JwtUtils method jwkSource.

public JWKSource<SecurityContext> jwkSource() {
    RSAKey rsaKey = Jwks.generateRsa();
    JWKSet jwkSet = new JWKSet(rsaKey);
    return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}
Also used : SecurityContext(com.nimbusds.jose.proc.SecurityContext) JWKSelector(com.nimbusds.jose.jwk.JWKSelector) URL(java.net.URL) Date(java.util.Date) JOSEException(com.nimbusds.jose.JOSEException) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) JWKSet(com.nimbusds.jose.jwk.JWKSet) JWSSignerFactory(com.nimbusds.jose.produce.JWSSignerFactory) Map(java.util.Map) Base64URL(com.nimbusds.jose.util.Base64URL) Jwt(org.springframework.security.oauth2.jwt.Jwt) Base64(com.nimbusds.jose.util.Base64) Converter(org.springframework.core.convert.converter.Converter) JWKSource(com.nimbusds.jose.jwk.source.JWKSource) DefaultJWSSignerFactory(com.nimbusds.jose.crypto.factories.DefaultJWSSignerFactory) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) JWSAlgorithm(com.nimbusds.jose.JWSAlgorithm) UUID(java.util.UUID) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) JWSHeader(com.nimbusds.jose.JWSHeader) SignedJWT(com.nimbusds.jwt.SignedJWT) JWK(com.nimbusds.jose.jwk.JWK) KeySourceException(com.nimbusds.jose.KeySourceException) List(java.util.List) JWSSigner(com.nimbusds.jose.JWSSigner) RSAKey(com.nimbusds.jose.jwk.RSAKey) JSONObject(net.minidev.json.JSONObject) CollectionUtils(org.springframework.util.CollectionUtils) JOSEObjectType(com.nimbusds.jose.JOSEObjectType) JWKMatcher(com.nimbusds.jose.jwk.JWKMatcher) Assert(org.springframework.util.Assert) StringUtils(org.springframework.util.StringUtils) RSAKey(com.nimbusds.jose.jwk.RSAKey) JWKSet(com.nimbusds.jose.jwk.JWKSet)

Example 3 with JWKSource

use of com.nimbusds.jose.jwk.source.JWKSource in project ddf by codice.

the class OidcTokenValidator method validateAccessTokenSignature.

/**
 * Validates an access token's signature
 *
 * @param accessToken - the token to validate
 * @param idToken - the corresponding ID token or null if one is not available. If an ID token is
 *     provided, the signature algorithm in the ID token is used. Otherwise the Algorithm provided
 *     in the header of the access token is used.
 * @param resourceRetriever - resource retriever
 * @param metadata - OIDC metadata
 */
private static void validateAccessTokenSignature(AccessToken accessToken, JWT idToken, ResourceRetriever resourceRetriever, OIDCProviderMetadata metadata) throws OidcValidationException {
    try {
        ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor();
        JWKSource keySource = new RemoteJWKSet(metadata.getJWKSetURI().toURL(), resourceRetriever);
        // Get signature algorithm, if ID token is given get algorithm from ID Token otherwise
        // get algorithm from access token header
        Algorithm expectedAlgorithm;
        if (idToken == null || idToken.getHeader().getAlgorithm() == Algorithm.NONE) {
            String accessTokenString = accessToken.getValue();
            Base64URL header = new Base64URL(accessTokenString.substring(0, accessTokenString.indexOf('.')));
            JSONObject jsonObject = JSONObjectUtils.parse(header.decodeToString());
            expectedAlgorithm = Header.parseAlgorithm(jsonObject);
        } else {
            expectedAlgorithm = idToken.getHeader().getAlgorithm();
        }
        if (expectedAlgorithm == Algorithm.NONE) {
            LOGGER.error("Error validating access token. Access token was not signed.");
            throw new OidcValidationException("Error validating access token. Access token was not signed.");
        }
        JWSAlgorithm expectedJWSAlgorithm = new JWSAlgorithm(expectedAlgorithm.getName(), expectedAlgorithm.getRequirement());
        JWSKeySelector keySelector = new JWSVerificationKeySelector(expectedJWSAlgorithm, keySource);
        jwtProcessor.setJWSKeySelector(keySelector);
        jwtProcessor.process(accessToken.getValue(), null);
    } catch (Exception e) {
        LOGGER.error(ACCESS_VALIDATION_ERR_MSG, e);
        throw new OidcValidationException(ACCESS_VALIDATION_ERR_MSG, e);
    }
}
Also used : JWSAlgorithm(com.nimbusds.jose.JWSAlgorithm) JWSAlgorithm(com.nimbusds.jose.JWSAlgorithm) Algorithm(com.nimbusds.jose.Algorithm) JWKSource(com.nimbusds.jose.jwk.source.JWKSource) RemoteJWKSet(com.nimbusds.jose.jwk.source.RemoteJWKSet) Base64URL(com.nimbusds.jose.util.Base64URL) JWSVerificationKeySelector(com.nimbusds.jose.proc.JWSVerificationKeySelector) ConfigurableJWTProcessor(com.nimbusds.jwt.proc.ConfigurableJWTProcessor) DefaultJWTProcessor(com.nimbusds.jwt.proc.DefaultJWTProcessor) JSONObject(net.minidev.json.JSONObject) JWSKeySelector(com.nimbusds.jose.proc.JWSKeySelector)

Example 4 with JWKSource

use of com.nimbusds.jose.jwk.source.JWKSource in project ddf by codice.

the class OidcTokenValidator method validateUserInfoIdToken.

/**
 * Validates id tokens received from the userinfo endpoint.
 *
 * <ul>
 *   <li>If the ID token is not signed, validation is ignored
 *   <li>If the ID token is signed
 *       <ul>
 *         <li>If the userinfo signing algorithms are listed in the metadata, we use that
 *             information along with the header attributes to validate the token
 *         <li>If the userinfo signing algorithms are NOT listed in the metadata, we just use the
 *             header attributes to validate the token
 *       </ul>
 *
 * @param idToken - id token to validate
 * @param resourceRetriever - resource retriever
 * @param metadata - OIDC metadata
 */
public static void validateUserInfoIdToken(JWT idToken, ResourceRetriever resourceRetriever, OIDCProviderMetadata metadata) throws OidcValidationException {
    if (metadata == null) {
        LOGGER.debug("Oidc metadata is null. Unable to validate userinfo id token.");
        return;
    }
    if (resourceRetriever == null) {
        resourceRetriever = new DefaultResourceRetriever();
    }
    try {
        if (!(idToken instanceof SignedJWT)) {
            LOGGER.info("ID token received from the userinfo endpoint was not signed.");
            return;
        }
        JWKSource jwkSource = new RemoteJWKSet(metadata.getJWKSetURI().toURL(), resourceRetriever);
        SignedJWT signedJWT = ((SignedJWT) idToken);
        JWSAlgorithm jwsAlgorithm = signedJWT.getHeader().getAlgorithm();
        List<JWSAlgorithm> userInfoSigAlgList = metadata.getUserInfoJWSAlgs();
        if (userInfoSigAlgList.isEmpty()) {
            LOGGER.warn("A JWS algorithm was not listed in the OpenID Connect provider metadata. " + "Using JWS algorithm specified in the header.");
        } else {
            if (!userInfoSigAlgList.contains(jwsAlgorithm)) {
                LOGGER.error("The signature algorithm of the id token do not match the expected ones.");
                throw new OidcValidationException("The signature algorithm of the id token do not match the expected ones.");
            }
        }
        JWSKeySelector jwsKeySelector = new JWSVerificationKeySelector(jwsAlgorithm, jwkSource);
        JWSVerifierFactory jwsVerifierFactory = new DefaultJWSVerifierFactory();
        List<? extends Key> keyCandidates = jwsKeySelector.selectJWSKeys(signedJWT.getHeader(), null);
        if (keyCandidates == null || keyCandidates.isEmpty()) {
            throw new OidcValidationException("Error Validating userinfo ID token. No matching key(s) found");
        }
        ListIterator<? extends Key> it = keyCandidates.listIterator();
        while (it.hasNext()) {
            JWSVerifier verifier = jwsVerifierFactory.createJWSVerifier(signedJWT.getHeader(), it.next());
            if (verifier == null) {
                continue;
            }
            final boolean validSignature = signedJWT.verify(verifier);
            if (validSignature) {
                return;
            }
            if (!it.hasNext()) {
                throw new OidcValidationException("Error Validating userinfo ID token. Invalid signature");
            }
        }
        throw new OidcValidationException("Error Validating userinfo ID token. No matching verifier(s) found");
    } catch (Exception e) {
        LOGGER.error(ID_VALIDATION_ERR_MSG, e);
        throw new OidcValidationException(ID_VALIDATION_ERR_MSG, e);
    }
}
Also used : DefaultJWSVerifierFactory(com.nimbusds.jose.crypto.factories.DefaultJWSVerifierFactory) JWSVerifier(com.nimbusds.jose.JWSVerifier) JWSVerifierFactory(com.nimbusds.jose.proc.JWSVerifierFactory) DefaultJWSVerifierFactory(com.nimbusds.jose.crypto.factories.DefaultJWSVerifierFactory) SignedJWT(com.nimbusds.jwt.SignedJWT) JWSAlgorithm(com.nimbusds.jose.JWSAlgorithm) JWKSource(com.nimbusds.jose.jwk.source.JWKSource) RemoteJWKSet(com.nimbusds.jose.jwk.source.RemoteJWKSet) JWSVerificationKeySelector(com.nimbusds.jose.proc.JWSVerificationKeySelector) JWSKeySelector(com.nimbusds.jose.proc.JWSKeySelector) DefaultResourceRetriever(com.nimbusds.jose.util.DefaultResourceRetriever)

Aggregations

JWKSource (com.nimbusds.jose.jwk.source.JWKSource)4 JWSAlgorithm (com.nimbusds.jose.JWSAlgorithm)3 JOSEException (com.nimbusds.jose.JOSEException)2 JWKSet (com.nimbusds.jose.jwk.JWKSet)2 RSAKey (com.nimbusds.jose.jwk.RSAKey)2 RemoteJWKSet (com.nimbusds.jose.jwk.source.RemoteJWKSet)2 JWSKeySelector (com.nimbusds.jose.proc.JWSKeySelector)2 JWSVerificationKeySelector (com.nimbusds.jose.proc.JWSVerificationKeySelector)2 SecurityContext (com.nimbusds.jose.proc.SecurityContext)2 Base64URL (com.nimbusds.jose.util.Base64URL)2 SignedJWT (com.nimbusds.jwt.SignedJWT)2 JSONObject (net.minidev.json.JSONObject)2 Jwt (org.springframework.security.oauth2.jwt.Jwt)2 ImmutableList (com.google.common.collect.ImmutableList)1 Algorithm (com.nimbusds.jose.Algorithm)1 JOSEObjectType (com.nimbusds.jose.JOSEObjectType)1 JWSHeader (com.nimbusds.jose.JWSHeader)1 JWSSigner (com.nimbusds.jose.JWSSigner)1 JWSVerifier (com.nimbusds.jose.JWSVerifier)1 KeySourceException (com.nimbusds.jose.KeySourceException)1