From 89d55e3d339663e95245c6c69f9c8674ccaeb4e3 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 24 May 2014 22:12:41 -0400 Subject: [PATCH] added support for default max auth age and require auth time, made prompt filter only work on authorization endpoint --- .../openid/connect/filter/PromptFilter.java | 56 +++++++++++++++---- .../service/impl/DefaultOIDCTokenService.java | 10 +++- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/PromptFilter.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/PromptFilter.java index f7c554bab..6b62a3943 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/PromptFilter.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/PromptFilter.java @@ -33,12 +33,16 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.mitre.oauth2.model.ClientDetailsEntity; +import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.openid.connect.web.AuthenticationTimeStamper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.stereotype.Component; @@ -62,6 +66,9 @@ public class PromptFilter extends GenericFilterBean { @Autowired private OAuth2RequestFactory authRequestFactory; + @Autowired + private ClientDetailsEntityService clientService; + /** * */ @@ -70,9 +77,25 @@ public class PromptFilter extends GenericFilterBean { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; + + // skip everything that's not an authorize URL + if (!request.getRequestURI().startsWith("/authorize")) { + chain.doFilter(req, res); + } + // we have to create our own auth request in order to get at all the parmeters appropriately AuthorizationRequest authRequest = authRequestFactory.createAuthorizationRequest(createRequestMap(request.getParameterMap())); + ClientDetailsEntity client = null; + + try { + client = clientService.loadClientByClientId(authRequest.getClientId()); + } catch (InvalidClientException e) { + // no need to worry about this here, it would be caught elsewhere + } catch (IllegalArgumentException e) { + // no need to worry about this here, it would be caught elsewhere + } + if (authRequest.getExtensions().get("prompt") != null) { // we have a "prompt" parameter String prompt = (String)authRequest.getExtensions().get("prompt"); @@ -125,21 +148,30 @@ public class PromptFilter extends GenericFilterBean { chain.doFilter(req, res); } - } else if (authRequest.getExtensions().get("max_age") != null) { + } else if (authRequest.getExtensions().get("max_age") != null || + (client != null && client.getDefaultMaxAge() != null)) { + + // default to the client's stored value, check the string parameter + Integer max = (client != null ? client.getDefaultMaxAge() : null); String maxAge = (String) authRequest.getExtensions().get("max_age"); - HttpSession session = request.getSession(); - Date authTime = (Date) session.getAttribute(AuthenticationTimeStamper.AUTH_TIMESTAMP); - - Date now = new Date(); - if (authTime != null) { - Integer max = Integer.parseInt(maxAge); - long seconds = (now.getTime() - authTime.getTime()) / 1000; - if (seconds > max) { - // session is too old, log the user out and continue - SecurityContextHolder.getContext().setAuthentication(null); + if (maxAge != null) { + max = Integer.parseInt(maxAge); + } + + if (max != null) { + + HttpSession session = request.getSession(); + Date authTime = (Date) session.getAttribute(AuthenticationTimeStamper.AUTH_TIMESTAMP); + + Date now = new Date(); + if (authTime != null) { + long seconds = (now.getTime() - authTime.getTime()) / 1000; + if (seconds > max) { + // session is too old, log the user out and continue + SecurityContextHolder.getContext().setAuthentication(null); + } } } - chain.doFilter(req, res); } else { // no prompt parameter, not our business diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java index 24a40eca1..dd8d152d1 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java @@ -95,9 +95,15 @@ public class DefaultOIDCTokenService implements OIDCTokenService { OAuth2AccessTokenEntity idTokenEntity = new OAuth2AccessTokenEntity(); JWTClaimsSet idClaims = new JWTClaimsSet(); - if (request.getExtensions().containsKey(AuthenticationTimeStamper.AUTH_TIMESTAMP)) { + // if the auth time claim was explicitly requested OR if the client always wants the auth time, put it in + if (request.getExtensions().containsKey("max_age") + || (request.getExtensions().containsKey("idtoken")) // TODO: parse the ID Token claims (#473) -- for now assume it could be in there + || (client.getRequireAuthTime() != null && client.getRequireAuthTime())) { + Date authTime = (Date) request.getExtensions().get(AuthenticationTimeStamper.AUTH_TIMESTAMP); - idClaims.setClaim("auth_time", authTime.getTime() / 1000); + if (authTime != null) { + idClaims.setClaim("auth_time", authTime.getTime() / 1000); + } } idClaims.setIssueTime(issueTime);