All Downloads are FREE. Search and download functionalities are using the official Maven repository.

no.nav.brukerdialog.security.oidc.OidcTokenValidator Maven / Gradle / Ivy

There is a newer version: 1.2020.02.21_14.01-cdaccec525a6
Show newest version
package no.nav.brukerdialog.security.oidc;

import no.nav.brukerdialog.security.jwks.JwtHeader;
import no.nav.brukerdialog.security.jwks.CacheMissAction;
import no.nav.brukerdialog.security.oidc.provider.OidcProvider;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.jwx.JsonWebStructure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.Key;
import java.util.List;

import static java.util.Optional.ofNullable;
import static no.nav.brukerdialog.security.jwks.CacheMissAction.REFRESH;

public class OidcTokenValidator {

    private static final Logger logger = LoggerFactory.getLogger(OidcTokenValidator.class);
    private static final int ALLOWED_CLOCK_SKEW_IN_SECONDS = 30;

    public OidcTokenValidatorResult validate(String token, OidcProvider oidcProvider) {
        return validate(token, oidcProvider, REFRESH);
    }

    public OidcTokenValidatorResult validate(
            String token,
            OidcProvider oidcProvider,
            CacheMissAction cacheMissAction
    ) {
        if (token == null) {
            return OidcTokenValidatorResult.invalid("Missing token (token was null)");
        }
        JwtHeader header;
        try {
            header = getHeader(token);
        } catch (InvalidJwtException e) {
            return OidcTokenValidatorResult.invalid("Invalid OIDC " + e.getMessage());
        }
        Key verificationKey = oidcProvider.getVerificationKey(header, cacheMissAction).orElse(null);
        if (verificationKey == null) {
            return OidcTokenValidatorResult.invalid(String.format("Jwt (%s) is not in jwks", header));
        }
        String issoExpectedTokenIssuer = oidcProvider.getExpectedIssuer();
        if (issoExpectedTokenIssuer == null) {
            return OidcTokenValidatorResult.invalid("Expected issuer must be configured.");
        }

        String expectedAud = oidcProvider.getExpectedAudience(token);

        JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                .setRequireExpirationTime()
                .setAllowedClockSkewInSeconds(ALLOWED_CLOCK_SKEW_IN_SECONDS)
                .setRequireSubject()
                .setExpectedIssuer(issoExpectedTokenIssuer)
                // Biblioteket støtter ikke at man disabler expected audience sjekken dersom den finnes en "aud"-claim i tokenet.
                // Henter dermed ut aud fra tokenet og setter det som expected hvis provideren vi ikke forventer et spesifikt audience.
                .setExpectedAudience(expectedAud != null, ofNullable(expectedAud).orElseGet(() -> OidcTokenUtils.getTokenAud(token)))
                .setVerificationKey(verificationKey)
                .build();

        try {
            JwtClaims claims = jwtConsumer.processToClaims(token);
            logger.debug("OIDC validation OK:" + claims.getSubject());
            return OidcTokenValidatorResult.valid(claims);
        } catch (InvalidJwtException e) {
            logger.info("Feil ved validering av token.", e);
            return OidcTokenValidatorResult.invalid(e.toString());
        } catch (MalformedClaimException e) {
            return OidcTokenValidatorResult.invalid("Malformed claim: " + e.toString());
        }
    }

    private JwtHeader getHeader(String jwt) throws InvalidJwtException {
        JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                .setSkipAllValidators()
                .setSkipAllDefaultValidators()
                .setRelaxVerificationKeyValidation()
                .setRelaxDecryptionKeyValidation()
                .setDisableRequireSignature()
                .setSkipSignatureVerification()
                .build();

        List jsonObjects = jwtConsumer.process(jwt).getJoseObjects();
        JsonWebStructure wstruct = jsonObjects.iterator().next();
        String kid = wstruct.getKeyIdHeaderValue();
        if (kid == null) {
            kid = "";
        }
        return new JwtHeader(kid, wstruct.getAlgorithmHeaderValue());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy