Skip to content

Commit

Permalink
make id token max timeout configurable (AthenZ#722)
Browse files Browse the repository at this point in the history
  • Loading branch information
havetisyan authored Jul 11, 2019
1 parent 27f3cf4 commit bf40b8a
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 12 deletions.
5 changes: 5 additions & 0 deletions servers/zts/conf/zts.properties
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ athenz.zts.cert_signer_factory_class=com.yahoo.athenz.zts.cert.impl.SelfCertSign
# does not specify any timeout parameters
#athenz.zts.role_token_default_timeout=7200

# Specifies the maximum expiry timeout that a client can ask for when
# requesting a oauth2 id token. If the client asks for a longer timeout, the
# server will automatically replace the value with this one
#athenz.zts.id_token_max_timeout=43200

# Specifies the expiry timeout for signed policy documents that
# ZTS Server signs and returns to ZPU clients
#athenz.zts.signed_policy_timeout=604800
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public final class ZTSConsts {
public static final String ZTS_PROP_LEAST_PRIVILEGE_PRINCIPLE = "athenz.zts.least_privilege_principle";
public static final String ZTS_PROP_ROLE_TOKEN_MAX_TIMEOUT = "athenz.zts.role_token_max_timeout";
public static final String ZTS_PROP_ROLE_TOKEN_DEFAULT_TIMEOUT = "athenz.zts.role_token_default_timeout";
public static final String ZTS_PROP_ID_TOKEN_MAX_TIMEOUT = "athenz.zts.id_token_max_timeout";
public static final String ZTS_PROP_SIGNED_POLICY_TIMEOUT = "athenz.zts.signed_policy_timeout";
public static final String ZTS_PROP_AUTHORIZED_PROXY_USERS = "athenz.zts.authorized_proxy_users";
public static final String ZTS_PROP_SECURE_REQUESTS_ONLY = "athenz.zts.secure_requests_only";
Expand Down
29 changes: 22 additions & 7 deletions servers/zts/src/main/java/com/yahoo/athenz/zts/ZTSImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public class ZTSImpl implements KeyStore, ZTSHandler {
protected SignatureAlgorithm privateKeyAlg = null;
protected int roleTokenDefaultTimeout;
protected int roleTokenMaxTimeout;
protected int idTokenMaxTimeout;
protected long x509CertRefreshResetTime;
protected long signedPolicyTimeout;
protected static String serverHostName = null;
Expand Down Expand Up @@ -354,7 +355,13 @@ void loadConfigurationSettings() {
timeout = TimeUnit.SECONDS.convert(30, TimeUnit.DAYS);
roleTokenMaxTimeout = Integer.parseInt(
System.getProperty(ZTSConsts.ZTS_PROP_ROLE_TOKEN_MAX_TIMEOUT, Long.toString(timeout)));


// default id token timeout - 12 hours

timeout = TimeUnit.SECONDS.convert(12, TimeUnit.HOURS);
idTokenMaxTimeout = Integer.parseInt(
System.getProperty(ZTSConsts.ZTS_PROP_ID_TOKEN_MAX_TIMEOUT, Long.toString(timeout)));

// signedPolicyTimeout is in milliseconds but the config setting should be in seconds
// to be consistent with other configuration properties

Expand Down Expand Up @@ -1013,7 +1020,11 @@ String convertEmptyStringToNull(String value) {
return value;
}
}


long determineIdTokenTimeout(long tokenTimeout) {
return (tokenTimeout > idTokenMaxTimeout) ? idTokenMaxTimeout : tokenTimeout;
}

long determineTokenTimeout(Integer minExpiryTime, Integer maxExpiryTime) {

// we're going to default our return value to the default token
Expand Down Expand Up @@ -1585,17 +1596,21 @@ public AccessTokenResponse postAccessTokenRequest(ResourceContext ctx, String re
String idJwts = null;
if (tokenRequest.isOpenidScope()) {

// id tokens are only valid for 1 hour

IdToken idToken = new IdToken();
idToken.setVersion(1);
idToken.setAudience(tokenRequest.getDomainName() + "." + tokenRequest.getServiceName());
idToken.setIssueTime(iat);
idToken.setExpiryTime(iat + 3600);
idToken.setAuthTime(iat);
idToken.setSubject(principalName);
idToken.setIssuer(ztsOAuthIssuer);

// id tokens are only valid for up to 12 hours max
// (value configured as a system property).
// we'll use the user specified timeout unless it's
// over the configured max

idToken.setIssueTime(iat);
idToken.setAuthTime(iat);
idToken.setExpiryTime(iat + determineIdTokenTimeout(tokenTimeout));

idJwts = idToken.getSignedToken(privateKey, privateKeyId, privateKeyAlg);
}

Expand Down
62 changes: 57 additions & 5 deletions servers/zts/src/test/java/com/yahoo/athenz/zts/ZTSImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package com.yahoo.athenz.zts;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
Expand All @@ -35,8 +34,6 @@
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.Response;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.yahoo.athenz.common.server.log.AuditLogMsgBuilder;
import com.yahoo.athenz.zms.*;
import com.yahoo.athenz.zms.Assertion;
Expand Down Expand Up @@ -2135,7 +2132,13 @@ public void testEmitMonmetricError() {
isEmitMonmetricError = ZTSUtils.emitMonmetricError(errorCode, " " + caller + " ", null, metric);
assertTrue(isEmitMonmetricError);
}


@Test
public void testDetermineIdTokenTimoeout() {
assertEquals(zts.determineIdTokenTimeout(3600), 3600);
assertEquals(zts.determineIdTokenTimeout(360000), zts.idTokenMaxTimeout);
}

@Test
public void testDetermineTokenTimeoutBothNull() {
assertEquals(zts.determineTokenTimeout(null, null), roleTokenDefaultTimeout);
Expand Down Expand Up @@ -8770,7 +8773,43 @@ public void testPostAccessTokenRequestOpenIdScope() {
ResourceContext context = createResourceContext(principal);

AccessTokenResponse resp = zts.postAccessTokenRequest(context,
"grant_type=client_credentials&scope=coretech:domain openid coretech:service.api");
"grant_type=client_credentials&scope=coretech:domain openid coretech:service.api&expires_in=240");
assertNotNull(resp);
assertEquals("coretech:role.writers openid", resp.getScope());

String accessToken = resp.getAccess_token();
assertNotNull(accessToken);

String idToken = resp.getId_token();
assertNotNull(idToken);

Jws<Claims> claims;
try {
claims = Jwts.parser().setSigningKey(Crypto.extractPublicKey(privateKey))
.parseClaimsJws(idToken);
} catch (SignatureException e) {
throw new ResourceException(ResourceException.UNAUTHORIZED);
}
assertNotNull(claims);

assertEquals(240 * 1000, claims.getBody().getExpiration().getTime() - claims.getBody().getIssuedAt().getTime());
}

@Test
public void testPostAccessTokenRequestOpenIdScopeMaxTimeout() {

SignedDomain signedDomain = createSignedDomain("coretech", "weather", "storage", true);
store.processDomain(signedDomain, false);

Principal principal = SimplePrincipal.create("user_domain", "user",
"v=U1;d=user_domain;n=user;s=signature", 0, null);
ResourceContext context = createResourceContext(principal);

// default max timeout is 12 hours so we'll pick a value
// bigger than that

AccessTokenResponse resp = zts.postAccessTokenRequest(context,
"grant_type=client_credentials&scope=coretech:domain openid coretech:service.api&expires_in=57600");
assertNotNull(resp);
assertEquals("coretech:role.writers openid", resp.getScope());

Expand All @@ -8779,6 +8818,19 @@ public void testPostAccessTokenRequestOpenIdScope() {

String idToken = resp.getId_token();
assertNotNull(idToken);

Jws<Claims> claims;
try {
claims = Jwts.parser().setSigningKey(Crypto.extractPublicKey(privateKey))
.parseClaimsJws(idToken);
} catch (SignatureException e) {
throw new ResourceException(ResourceException.UNAUTHORIZED);
}
assertNotNull(claims);

// the value should be 12 hours - the default max

assertEquals(12 * 60 * 60 * 1000, claims.getBody().getExpiration().getTime() - claims.getBody().getIssuedAt().getTime());
}

@Test
Expand Down

0 comments on commit bf40b8a

Please sign in to comment.