You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by go...@apache.org on 2017/11/14 17:55:33 UTC
[cxf-fediz] 03/03: id_token exp should be computed at creation time
This is an automated email from the ASF dual-hosted git repository.
gonzalad pushed a commit to branch 1.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf-fediz.git
commit c0631b318a180fe86a3410f0445f5caf4189fd5c
Author: gonzalad <ad...@yahoo.fr>
AuthorDate: Tue Nov 14 18:39:41 2017 +0100
id_token exp should be computed at creation time
id_token expiry claim is now computed at id_token generation time.
It was previously computed from SAML token expiry.
Since SAML token is generated once per OIDC httpSession
and can be reused for generating multiple id_token, it introduced
some issues where the id_token is generated with an already expired claim.
We now compute the exp claim as :
* use timeToLive attribute of FedizSubjectCreator if it is strictly positive.
* use maxInactiveInterval from httpSession if it is strictly positive.
* otherwise use the default of 1 hour.
---
.../fediz/service/oidc/FedizSubjectCreator.java | 124 ++++++++++-----------
1 file changed, 56 insertions(+), 68 deletions(-)
diff --git a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/FedizSubjectCreator.java b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/FedizSubjectCreator.java
index e8ad831..dae3a10 100644
--- a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/FedizSubjectCreator.java
+++ b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/FedizSubjectCreator.java
@@ -26,6 +26,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
+import javax.servlet.http.HttpSession;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;
@@ -51,21 +52,23 @@ import org.opensaml.saml.saml2.core.Issuer;
public class FedizSubjectCreator implements SubjectCreator {
+
+ private static final long DEFAULT_TIME_TO_LIVE = 3600L;
private static final String ROLES_SCOPE = "roles";
private boolean stripPathFromIssuerUri;
private String issuer;
- private long defaultTimeToLive = 3600L;
private Map<String, String> supportedClaims = Collections.emptyMap();
+ private long timeToLive;
@Override
public OidcUserSubject createUserSubject(MessageContext mc,
- MultivaluedMap<String, String> params) throws OAuthServiceException {
+ MultivaluedMap<String, String> params) throws OAuthServiceException {
Principal principal = mc.getSecurityContext().getUserPrincipal();
if (!(principal instanceof FedizPrincipal)) {
throw new OAuthServiceException("Unsupported Principal");
}
- FedizPrincipal fedizPrincipal = (FedizPrincipal)principal;
+ FedizPrincipal fedizPrincipal = (FedizPrincipal) principal;
// In the future FedizPrincipal will likely have JWT claims already prepared,
// with IdToken being initialized here from those claims
@@ -74,13 +77,8 @@ public class FedizSubjectCreator implements SubjectCreator {
oidcSub.setId(fedizPrincipal.getName());
- IdToken idToken = convertToIdToken(mc,
- fedizPrincipal.getLoginToken(),
- oidcSub.getLogin(),
- oidcSub.getId(),
- fedizPrincipal.getClaims(),
- fedizPrincipal.getRoleClaims(),
- params);
+ IdToken idToken = convertToIdToken(mc, fedizPrincipal.getLoginToken(), oidcSub.getLogin(), oidcSub.getId(),
+ fedizPrincipal.getClaims(), fedizPrincipal.getRoleClaims(), params);
oidcSub.setIdToken(idToken);
oidcSub.setRoles(fedizPrincipal.getRoleClaims());
// UserInfo can be populated and set on OidcUserSubject too.
@@ -89,47 +87,26 @@ public class FedizSubjectCreator implements SubjectCreator {
return oidcSub;
}
- private IdToken convertToIdToken(MessageContext mc,
- Element samlToken,
- String subjectName,
- String subjectId,
- ClaimCollection claims,
- List<String> roles,
- MultivaluedMap<String, String> params) {
+ private IdToken convertToIdToken(MessageContext mc, Element samlToken, String subjectName, String subjectId,
+ ClaimCollection claims, List<String> roles,
+ MultivaluedMap<String, String> params) {
// The current SAML Assertion represents an authentication record.
// It has to be translated into IdToken (JWT) so that it can be returned
// to client applications participating in various OIDC flows.
IdToken idToken = new IdToken();
- //TODO: make the mapping between the subject name and IdToken claim configurable
+ // TODO: make the mapping between the subject name and IdToken claim configurable
idToken.setPreferredUserName(subjectName);
idToken.setSubject(subjectId);
Assertion saml2Assertion = getSaml2Assertion(samlToken);
- if (saml2Assertion != null) {
- // issueInstant
- DateTime issueInstant = saml2Assertion.getIssueInstant();
- if (issueInstant != null) {
- idToken.setIssuedAt(issueInstant.getMillis() / 1000);
- }
-
- // expiryTime
- if (saml2Assertion.getConditions() != null) {
- DateTime expires = saml2Assertion.getConditions().getNotOnOrAfter();
- if (expires != null) {
- idToken.setExpiryTime(expires.getMillis() / 1000);
- }
- }
-
- // authInstant
- if (!saml2Assertion.getAuthnStatements().isEmpty()) {
- DateTime authInstant =
- saml2Assertion.getAuthnStatements().get(0).getAuthnInstant();
- idToken.setAuthenticationTime(authInstant.getMillis() / 1000L);
- }
+ // authInstant
+ if (saml2Assertion != null && !saml2Assertion.getAuthnStatements().isEmpty()) {
+ DateTime authInstant = saml2Assertion.getAuthnStatements().get(0).getAuthnInstant();
+ idToken.setAuthenticationTime(authInstant.getMillis() / 1000L);
}
- // Check if default issuer, issuedAt and expiryTime values have to be set
+ // Check if default issuer, issuedAt values have to be set
if (issuer != null) {
String realIssuer = null;
if (issuer.startsWith("/")) {
@@ -156,23 +133,27 @@ public class FedizSubjectCreator implements SubjectCreator {
}
}
+ // Compute exp claim
long currentTimeInSecs = System.currentTimeMillis() / 1000;
- if (idToken.getIssuedAt() == null) {
- idToken.setIssuedAt(currentTimeInSecs);
- }
- if (idToken.getExpiryTime() == null) {
- idToken.setExpiryTime(currentTimeInSecs + defaultTimeToLive);
+ idToken.setIssuedAt(currentTimeInSecs);
+ HttpSession httpSession = mc.getHttpServletRequest().getSession(false);
+ if (timeToLive > 0) {
+ idToken.setExpiryTime(timeToLive);
+ } else if (httpSession != null && httpSession.getMaxInactiveInterval() > 0) {
+ idToken.setExpiryTime(currentTimeInSecs + httpSession.getMaxInactiveInterval());
+ } else {
+ idToken.setExpiryTime(currentTimeInSecs + DEFAULT_TIME_TO_LIVE);
}
List<String> requestedClaimsList = new ArrayList<String>();
- //Derive claims from scope
+ // Derive claims from scope
String requestedScope = params.getFirst(OAuthConstants.SCOPE);
if (requestedScope != null && !requestedScope.isEmpty()) {
String[] scopes = requestedScope.split(" ");
- //TODO: Note that if the consent screen enabled then it is feasible
+ // TODO: Note that if the consent screen enabled then it is feasible
// that the claims added in this code after mapping the scopes to claims
// may need to be removed if the user disapproves the related scope
-
+
// standard scope to claims mapping:
requestedClaimsList.addAll(OidcUtils.getScopeClaims(scopes));
// custom scopes to claims mapping
@@ -193,16 +174,16 @@ public class FedizSubjectCreator implements SubjectCreator {
continue;
}
if (ClaimTypes.FIRSTNAME.equals(c.getClaimType())) {
- idToken.setGivenName((String)c.getValue());
- firstName = (String)c.getValue();
+ idToken.setGivenName((String) c.getValue());
+ firstName = (String) c.getValue();
} else if (ClaimTypes.LASTNAME.equals(c.getClaimType())) {
- idToken.setFamilyName((String)c.getValue());
- lastName = (String)c.getValue();
+ idToken.setFamilyName((String) c.getValue());
+ lastName = (String) c.getValue();
} else if (ClaimTypes.EMAILADDRESS.equals(c.getClaimType())) {
- idToken.setEmail((String)c.getValue());
+ idToken.setEmail((String) c.getValue());
} else if (supportedClaims.containsKey(c.getClaimType().toString())
- && requestedClaimsList.contains(supportedClaims.get(c.getClaimType().toString()))) {
- idToken.setClaim(supportedClaims.get(c.getClaimType().toString()), (String)c.getValue());
+ && requestedClaimsList.contains(supportedClaims.get(c.getClaimType().toString()))) {
+ idToken.setClaim(supportedClaims.get(c.getClaimType().toString()), (String) c.getValue());
}
}
@@ -211,29 +192,28 @@ public class FedizSubjectCreator implements SubjectCreator {
}
}
- if (roles != null && !roles.isEmpty()
- && supportedClaims.containsKey(FedizConstants.DEFAULT_ROLE_URI.toString())) {
-
+ if (roles != null && !roles.isEmpty()
+ && supportedClaims.containsKey(FedizConstants.DEFAULT_ROLE_URI.toString())) {
+
String roleClaimName = supportedClaims.get(FedizConstants.DEFAULT_ROLE_URI.toString());
if (requestedClaimsList.contains(roleClaimName)) {
idToken.setClaim(roleClaimName, roles);
- }
+ }
}
return idToken;
}
-
private List<String> getCustomScopeClaims(String[] scopes) {
// For now the only custom scope (to claims) mapping Fediz supports is
// roles where the scope name is expected to be 'roles' and the role name must be configured
String roleClaimName = supportedClaims.get(FedizConstants.DEFAULT_ROLE_URI.toString());
if (roleClaimName != null && Arrays.asList(scopes).contains(ROLES_SCOPE)) {
- return Collections.singletonList(roleClaimName);
+ return Collections.singletonList(roleClaimName);
} else {
return Collections.emptyList();
}
-
+
}
private Assertion getSaml2Assertion(Element samlToken) {
@@ -247,16 +227,10 @@ public class FedizSubjectCreator implements SubjectCreator {
}
-
public void setIdTokenIssuer(String idTokenIssuer) {
this.issuer = idTokenIssuer;
}
-
- public void setIdTokenTimeToLive(long idTokenTimeToLive) {
- this.defaultTimeToLive = idTokenTimeToLive;
- }
-
/**
* Set a map of supported claims. The map is from a SAML ClaimType URI String to a claim value that is
* sent in the claims parameter. So for example:
@@ -272,4 +246,18 @@ public class FedizSubjectCreator implements SubjectCreator {
this.stripPathFromIssuerUri = stripPathFromIssuerUri;
}
+ /**
+ * Time to live in seconds (used for id_token exp claim).
+ *
+ * If this value is set and strictly positive, then the generated
+ * id_token will use this value for the exp claim.
+ *
+ * Otherwise, it will use maxInactiveInterval of httpSession, and
+ * if this later is not strictly positive, it will be 1 hour by default.
+ *
+ * @param timeToLive time to live in seconds of the id_token
+ */
+ public void setTimeToLive(long timeToLive) {
+ this.timeToLive = timeToLive;
+ }
}
--
To stop receiving notification emails like this one, please contact
"commits@cxf.apache.org" <co...@cxf.apache.org>.