Skip to content

Commit

Permalink
Litt mer innpakking av claims-aksess
Browse files Browse the repository at this point in the history
  • Loading branch information
jolarsen committed Mar 14, 2023
1 parent eb2e50a commit 615911c
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;

import org.jose4j.jwt.MalformedClaimException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import no.nav.vedtak.exception.TekniskException;
import no.nav.vedtak.log.mdc.MDCOperations;
import no.nav.vedtak.sikkerhet.abac.BeskyttetRessurs;
import no.nav.vedtak.sikkerhet.abac.ÅpenRessurs;
Expand Down Expand Up @@ -85,7 +85,7 @@ public static void validerSettKontekst(ResourceInfo resourceInfo, ContainerReque
.orElseThrow(() -> new TokenFeil("Mangler token"));
validerToken(tokenString);
}
} catch (MalformedClaimException | TokenFeil e) {
} catch (TekniskException | TokenFeil e) {
throw new WebApplicationException(e, Response.Status.FORBIDDEN);
} catch (WebApplicationException e) {
throw e;
Expand Down Expand Up @@ -134,10 +134,10 @@ private static Optional<TokenString> getCookie(ContainerRequestContext request,
.map(TokenString::new);
}

public static void validerToken(TokenString tokenString) throws MalformedClaimException {
public static void validerToken(TokenString tokenString) {
// Sett opp OpenIDToken
var claims = JwtUtil.getClaims(tokenString.token());
var configuration = ConfigProvider.getOpenIDConfiguration(claims.getIssuer())
var configuration = ConfigProvider.getOpenIDConfiguration(JwtUtil.getIssuer(claims))
.orElseThrow(() -> new TokenFeil("Token mangler issuer claim"));
var expiresAt = Optional.ofNullable(JwtUtil.getExpirationTime(claims)).orElseGet(() -> Instant.now().plusSeconds(300));
var token = new OpenIDToken(configuration.type(), OpenIDToken.OIDC_DEFAULT_TOKEN_TYPE, tokenString, null, expiresAt.toEpochMilli());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ public static String getIssuer(JwtClaims claims) {
}
}

public static String getSubject(JwtClaims claims) {
try {
return claims.getSubject();
} catch (MalformedClaimException e) {
throw ugyldigJwt(e);
}
}

public static List<String> getAudience(JwtClaims claims) {
try {
return claims.getAudience();
} catch (MalformedClaimException e) {
throw ugyldigJwt(e);
}
}

public static Instant getExpirationTime(JwtClaims claims) {
try {
long expirationTime = claims.getExpirationTime().getValue();
Expand All @@ -58,6 +74,14 @@ public static Instant getExpirationTime(JwtClaims claims) {
}
}

public static long getExpirationTimeRaw(JwtClaims claims) {
try {
return claims.getExpirationTime().getValue();
} catch (MalformedClaimException e) {
throw ugyldigJwt(e);
}
}

public static String getClientName(JwtClaims claims) {
try {
String azp = claims.getStringClaimValue("azp");
Expand All @@ -75,6 +99,22 @@ public static String getClientName(JwtClaims claims) {

}

public static String getStringClaim(JwtClaims claims, String key) {
try {
return claims.getStringClaimValue(key);
} catch (MalformedClaimException e) {
throw ugyldigJwt(e);
}
}

public static List<String> getStringListClaim(JwtClaims claims, String key) {
try {
return claims.getStringListClaimValue(key);
} catch (MalformedClaimException e) {
throw ugyldigJwt(e);
}
}

private static TekniskException ugyldigJwt(Exception e) {
return new TekniskException("F-026968", "Feil ved parsing av JWT", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.Set;

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;
Expand All @@ -22,17 +21,6 @@
import no.nav.vedtak.sikkerhet.oidc.jwks.JwksKeyHandlerImpl;
import no.nav.vedtak.sikkerhet.oidc.jwks.JwtHeader;
import no.nav.vedtak.sikkerhet.oidc.token.TokenString;
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 java.security.Key;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

public class OidcTokenValidator {

Expand Down Expand Up @@ -124,17 +112,17 @@ private OidcTokenValidatorResult validate(TokenString tokenHolder, int allowedCl
if (error != null) {
return OidcTokenValidatorResult.invalid(error);
}
String subject = claims.getSubject();
String subject = JwtUtil.getSubject(claims);
if (OpenIDProvider.AZUREAD.equals(provider)) {
return validateAzure(claims, subject);
} else if (OpenIDProvider.TOKENX.equals(provider)) {
return validateTokenX(claims, subject);
} else {
return OidcTokenValidatorResult.valid(subject, IdentType.utledIdentType(subject), claims.getExpirationTime().getValue());
return OidcTokenValidatorResult.valid(subject, IdentType.utledIdentType(subject), JwtUtil.getExpirationTimeRaw(claims));
}
} catch (InvalidJwtException e) {
return OidcTokenValidatorResult.invalid(e.toString());
} catch (MalformedClaimException e) {
} catch (Exception e) {
return OidcTokenValidatorResult.invalid("Malformed claim: " + e);
}
}
Expand All @@ -145,50 +133,50 @@ public OidcTokenValidatorResult validateWithoutExpirationTime(TokenString tokenH

// Validates some of the rules set in OpenID Connect Core 1.0 incorporatin errata set 1,
// which is not already validated by using JwtConsumer
private String validateClaims(JwtClaims claims) throws MalformedClaimException {
String azp = claims.getStringClaimValue("azp");
if (azp == null && claims.getAudience().size() != 1) {
private String validateClaims(JwtClaims claims) {
String azp = JwtUtil.getStringClaim(claims, "azp");
if (azp == null && JwtUtil.getAudience(claims).size() != 1) {
return "Either an azp-claim or a single value aud-claim is required";
}
return null;
}

private OidcTokenValidatorResult validateAzure(JwtClaims claims, String subject) throws MalformedClaimException {
private OidcTokenValidatorResult validateAzure(JwtClaims claims, String subject) {
if (isAzureClientCredentials(claims, subject)) {
var brukSubject = Optional.ofNullable(claims.getStringClaimValue(AzureProperty.AZP_NAME)).orElse(subject);
var brukSubject = Optional.ofNullable(JwtUtil.getStringClaim(claims, AzureProperty.AZP_NAME)).orElse(subject);
// Ta med bakoverkompatibelt navn ettersom azp_name er ganske langt (tabeller / opprettet_av)
if (brukSubject.lastIndexOf(':') >= 0) {
var appSrvName = "srv" + brukSubject.substring(brukSubject.lastIndexOf(':') + 1);
if (appSrvName.length() > 20) {
appSrvName = appSrvName.substring(0, 19);
}
return OidcTokenValidatorResult.valid(brukSubject, IdentType.Systemressurs, appSrvName, claims.getExpirationTime().getValue());
return OidcTokenValidatorResult.valid(brukSubject, IdentType.Systemressurs, appSrvName, JwtUtil.getExpirationTimeRaw(claims));
} else {
return OidcTokenValidatorResult.valid(brukSubject, IdentType.Systemressurs, claims.getExpirationTime().getValue());
return OidcTokenValidatorResult.valid(brukSubject, IdentType.Systemressurs, JwtUtil.getExpirationTimeRaw(claims));
}
} else {
var brukSubject = Optional.ofNullable(claims.getStringClaimValue(AzureProperty.NAV_IDENT)).orElse(subject);
var grupper = Optional.ofNullable(claims.getStringListClaimValue(AzureProperty.GRUPPER))
var brukSubject = Optional.ofNullable(JwtUtil.getStringClaim(claims, AzureProperty.NAV_IDENT)).orElse(subject);
var grupper = Optional.ofNullable(JwtUtil.getStringListClaim(claims, AzureProperty.GRUPPER))
.map(arr -> GroupsProvider.instance().getGroupsFrom(arr))
.orElse(Set.of());
return OidcTokenValidatorResult.valid(brukSubject, IdentType.InternBruker, grupper, claims.getExpirationTime().getValue());
return OidcTokenValidatorResult.valid(brukSubject, IdentType.InternBruker, grupper, JwtUtil.getExpirationTimeRaw(claims));
}
}

// Established practice: oid = sub -> CC-flow
private boolean isAzureClientCredentials(JwtClaims claims, String subject) throws MalformedClaimException {
return Objects.equals(subject, claims.getStringClaimValue("oid"));
private boolean isAzureClientCredentials(JwtClaims claims, String subject) {
return Objects.equals(subject, JwtUtil.getStringClaim(claims, "oid"));
}

private OidcTokenValidatorResult validateTokenX(JwtClaims claims, String subject) throws MalformedClaimException {
var level4 = Optional.ofNullable(claims.getStringClaimValue("acr"))
private OidcTokenValidatorResult validateTokenX(JwtClaims claims, String subject) {
var level4 = Optional.ofNullable(JwtUtil.getStringClaim(claims, "acr"))
.filter(AuthenticationLevel.AUTHENTICATION_LEVEL_ID_PORTEN::equals)
.isPresent();
if (!level4) {
return OidcTokenValidatorResult.invalid("TokenX token ikke på nivå 4");
}
var brukSubject = Optional.ofNullable(claims.getStringClaimValue("pid")).orElse(subject);
return OidcTokenValidatorResult.valid(brukSubject, IdentType.EksternBruker, claims.getExpirationTime().getValue());
var brukSubject = Optional.ofNullable(JwtUtil.getStringClaim(claims, "pid")).orElse(subject);
return OidcTokenValidatorResult.valid(brukSubject, IdentType.EksternBruker, JwtUtil.getExpirationTimeRaw(claims));
}

private JwtHeader getHeader(String jwt) throws InvalidJwtException {
Expand Down

0 comments on commit 615911c

Please sign in to comment.