From 629390dd4aaa17c67a8c6dc426ebc381ef98fc09 Mon Sep 17 00:00:00 2001 From: mposolda Date: Fri, 8 Jul 2016 16:16:38 +0200 Subject: [PATCH] KEYCLOAK-2986 Require either expiration or issuedAt for client authentication with signed JWT --- .../authentication/JWTClientCredentialsProvider.java | 4 ++++ .../authenticators/client/JWTClientAuthenticator.java | 6 ++++++ .../keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java | 6 ++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authentication/JWTClientCredentialsProvider.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authentication/JWTClientCredentialsProvider.java index 747137db80..2490c0e653 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authentication/JWTClientCredentialsProvider.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authentication/JWTClientCredentialsProvider.java @@ -54,6 +54,10 @@ public class JWTClientCredentialsProvider implements ClientCredentialsProvider { this.tokenTimeout = tokenTimeout; } + protected int getTokenTimeout() { + return tokenTimeout; + } + @Override public void init(KeycloakDeployment deployment, Object config) { if (config == null || !(config instanceof Map)) { diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java index f97dce07f0..2ee2fcb37d 100644 --- a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java +++ b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java @@ -32,6 +32,7 @@ import javax.ws.rs.core.Response; import org.keycloak.OAuth2Constants; import org.keycloak.authentication.AuthenticationFlowError; import org.keycloak.authentication.ClientAuthenticationFlowContext; +import org.keycloak.common.util.Time; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.crypto.RSAProvider; import org.keycloak.models.AuthenticationExecutionModel; @@ -145,6 +146,11 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator { throw new RuntimeException("Token is not active"); } + // KEYCLOAK-2986 + if (token.getExpiration() == 0 && token.getIssuedAt() + 10 < Time.currentTime()) { + throw new RuntimeException("Token is not active"); + } + context.success(); } catch (Exception e) { logger.errorValidatingAssertion(e); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java index 8a890df464..087a1e651b 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java @@ -613,7 +613,7 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest { } @Test - @Ignore // Waiting for KEYCLOAK-2986 to be implemented + // KEYCLOAK-2986 public void testMissingExpirationClaim() throws Exception { // Missing only exp; the lifespan should be calculated from issuedAt OAuthClient.AccessTokenResponse response = testMissingClaim("expiration"); @@ -840,9 +840,7 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest { int now = Time.currentTime(); if (isClaimEnabled("issuedAt")) reqToken.issuedAt(now); - // For the time being there's no getter for tokenTimeout in JWTClientCredentialsProvider - // This is fine because KC doesn't care when exp claim is missing (see KEYCLOAK-2986) - /*if (isClaimEnabled("expiration")) reqToken.expiration(now + getTokenTimeout());*/ + if (isClaimEnabled("expiration")) reqToken.expiration(now + getTokenTimeout()); if (isClaimEnabled("notBefore")) reqToken.notBefore(now); return reqToken;