From 5f109cea4ade34e4d45b16a1de5eb05b62491710 Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Thu, 17 Feb 2022 11:17:15 +0200 Subject: [PATCH] feat(jans-auth-server): added to par extra nbf and exp (for 60min) validation https://github.com/JanssenProject/jans/issues/824 --- .../as/persistence/model/ParAttributes.java | 11 +++++++ .../authorize/JwtAuthorizationRequest.java | 30 +++++++++++-------- .../jans/as/server/par/ws/rs/ParService.java | 21 +++++++++++-- .../as/server/par/ws/rs/ParValidator.java | 4 ++- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/jans-auth-server/persistence-model/src/main/java/io/jans/as/persistence/model/ParAttributes.java b/jans-auth-server/persistence-model/src/main/java/io/jans/as/persistence/model/ParAttributes.java index 5e4aeb7833e..9d20529f139 100644 --- a/jans-auth-server/persistence-model/src/main/java/io/jans/as/persistence/model/ParAttributes.java +++ b/jans-auth-server/persistence-model/src/main/java/io/jans/as/persistence/model/ParAttributes.java @@ -16,6 +16,8 @@ public class ParAttributes implements Serializable { @JsonProperty Integer maxAge; @JsonProperty + Integer nbf; + @JsonProperty private String scope; @JsonProperty private String responseType; @@ -142,6 +144,14 @@ public void setMaxAge(Integer maxAge) { this.maxAge = maxAge; } + public Integer getNbf() { + return nbf; + } + + public void setNbf(Integer nbf) { + this.nbf = nbf; + } + public String getUiLocales() { return uiLocales; } @@ -268,6 +278,7 @@ public String toString() { ", display='" + display + '\'' + ", prompt='" + prompt + '\'' + ", maxAge=" + maxAge + + ", nbf=" + nbf + ", uiLocales='" + uiLocales + '\'' + ", idTokenHint='" + idTokenHint + '\'' + ", loginHint='" + loginHint + '\'' + diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/model/authorize/JwtAuthorizationRequest.java b/jans-auth-server/server/src/main/java/io/jans/as/server/model/authorize/JwtAuthorizationRequest.java index e0ad49403d3..25d49e0f920 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/model/authorize/JwtAuthorizationRequest.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/model/authorize/JwtAuthorizationRequest.java @@ -58,8 +58,8 @@ */ public class JwtAuthorizationRequest { - private final static Logger log = LoggerFactory.getLogger(JwtAuthorizationRequest.class); - private final static int SIXTY_MINUTES_AS_SECONDS = 3600; + private static final Logger log = LoggerFactory.getLogger(JwtAuthorizationRequest.class); + private static final int SIXTY_MINUTES_AS_SECONDS = 3600; // Header private String type; @@ -544,17 +544,11 @@ private void validateFapi() throws InvalidJwtException { throw new InvalidJwtException("None algorithm is not allowed for FAPI"); } - if (nbf == null || nbf <= 0) { // https://github.com/JanssenProject/jans-auth-server/issues/164 fapi1-advanced-final-ensure-request-object-without-nbf-fails - log.error("nbf claim is not set, nbf: {}", nbf); - throw new InvalidJwtException("nbf claim is not set"); - } - final long nowSeconds = System.currentTimeMillis() / 1000; - final long nbfDiff = nowSeconds - nbf; - if (nbfDiff > SIXTY_MINUTES_AS_SECONDS) { // https://github.com/JanssenProject/jans-auth-server/issues/166 - log.error("nbf claim is more then 60 Minutes in the past, nbf: {}, nowSeconds: {}", nbf, nowSeconds); - throw new InvalidJwtException("nbf claim is more then 60 in the past"); - } + validateNbf(nbf); + validateExp(exp); + } + public static void validateExp(Integer exp) throws InvalidJwtException { if (exp == null) { log.error("The exp claim is not set"); throw new InvalidJwtException("exp claim is not set"); @@ -566,6 +560,18 @@ private void validateFapi() throws InvalidJwtException { log.error("exp claim is more then 60 minutes in the future, exp: {}, nowSecondsExp: {}", exp, nowSecondsExp); throw new InvalidJwtException("exp claim is more then 60 in the future"); } + } + public static void validateNbf(Integer nbf) throws InvalidJwtException { + if (nbf == null || nbf <= 0) { // https://github.com/JanssenProject/jans-auth-server/issues/164 fapi1-advanced-final-ensure-request-object-without-nbf-fails + log.error("nbf claim is not set, nbf: {}", nbf); + throw new InvalidJwtException("nbf claim is not set"); + } + final long nowSeconds = System.currentTimeMillis() / 1000; + final long nbfDiff = nowSeconds - nbf; + if (nbfDiff > SIXTY_MINUTES_AS_SECONDS) { // https://github.com/JanssenProject/jans-auth-server/issues/166 + log.error("nbf claim is more then 60 Minutes in the past, nbf: {}, nowSeconds: {}", nbf, nowSeconds); + throw new InvalidJwtException("nbf claim is more then 60 in the past"); + } } } diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParService.java b/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParService.java index 068bfa66b79..c8f089401cf 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParService.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParService.java @@ -3,8 +3,10 @@ import io.jans.as.model.authorize.AuthorizeErrorResponseType; import io.jans.as.model.config.StaticConfiguration; import io.jans.as.model.error.ErrorResponseFactory; +import io.jans.as.model.exception.InvalidJwtException; import io.jans.as.model.util.Util; import io.jans.as.persistence.model.Par; +import io.jans.as.server.model.authorize.JwtAuthorizationRequest; import io.jans.orm.PersistenceEntryManager; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -103,15 +105,30 @@ public Par getParAndValidateForAuthorizationRequest(String id, String state, Str .build()); } + validate(par, state); + return par; + } + + private void validate(Par par, String state) { Date now = new Date(); if (par.isExpired(now)) { - log.debug("PAR is expired, id: {}, exp: {}, now: {}", id, par.getExpirationDate(), now); + log.debug("PAR is expired, id: {}, exp: {}, now: {}", par.getId(), par.getExpirationDate(), now); throw new WebApplicationException(Response .status(Response.Status.BAD_REQUEST) .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST_URI, state, "PAR is expired")) .type(MediaType.APPLICATION_JSON_TYPE) .build()); } - return par; + + try { + JwtAuthorizationRequest.validateExp((int) (par.getExpirationDate().getTime() / 1000)); + JwtAuthorizationRequest.validateNbf(par.getAttributes().getNbf()); + } catch (InvalidJwtException e) { + throw new WebApplicationException(Response + .status(Response.Status.BAD_REQUEST) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST, state, "Failed to validate exp or nbf")) + .type(MediaType.APPLICATION_JSON_TYPE) + .build()); + } } } diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParValidator.java b/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParValidator.java index f321be7ccff..0c65b0f56f8 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParValidator.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParValidator.java @@ -91,7 +91,9 @@ public void validateRequestObject(RedirectUriResponse redirectUriResponse, Par p if (StringUtils.isNotBlank(jwtRequest.getClientId())) { par.getAttributes().setClientId(jwtRequest.getClientId()); } - + if (jwtRequest.getNbf() != null) { + par.getAttributes().setNbf(jwtRequest.getNbf()); + } if (!jwtRequest.getScopes().isEmpty()) { // JWT wins Set scopes = scopeChecker.checkScopesPolicy(client, Lists.newArrayList(jwtRequest.getScopes())); par.getAttributes().setScope(implode(scopes, " "));