KEYCLOAK-2986 Require either expiration or issuedAt for client authentication with signed JWT
This commit is contained in:
parent
3bfd999590
commit
629390dd4a
3 changed files with 12 additions and 4 deletions
|
@ -54,6 +54,10 @@ public class JWTClientCredentialsProvider implements ClientCredentialsProvider {
|
||||||
this.tokenTimeout = tokenTimeout;
|
this.tokenTimeout = tokenTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int getTokenTimeout() {
|
||||||
|
return tokenTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(KeycloakDeployment deployment, Object config) {
|
public void init(KeycloakDeployment deployment, Object config) {
|
||||||
if (config == null || !(config instanceof Map)) {
|
if (config == null || !(config instanceof Map)) {
|
||||||
|
|
|
@ -32,6 +32,7 @@ import javax.ws.rs.core.Response;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.authentication.AuthenticationFlowError;
|
import org.keycloak.authentication.AuthenticationFlowError;
|
||||||
import org.keycloak.authentication.ClientAuthenticationFlowContext;
|
import org.keycloak.authentication.ClientAuthenticationFlowContext;
|
||||||
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||||
import org.keycloak.models.AuthenticationExecutionModel;
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
@ -145,6 +146,11 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
|
||||||
throw new RuntimeException("Token is not active");
|
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();
|
context.success();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.errorValidatingAssertion(e);
|
logger.errorValidatingAssertion(e);
|
||||||
|
|
|
@ -613,7 +613,7 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore // Waiting for KEYCLOAK-2986 to be implemented
|
// KEYCLOAK-2986
|
||||||
public void testMissingExpirationClaim() throws Exception {
|
public void testMissingExpirationClaim() throws Exception {
|
||||||
// Missing only exp; the lifespan should be calculated from issuedAt
|
// Missing only exp; the lifespan should be calculated from issuedAt
|
||||||
OAuthClient.AccessTokenResponse response = testMissingClaim("expiration");
|
OAuthClient.AccessTokenResponse response = testMissingClaim("expiration");
|
||||||
|
@ -840,9 +840,7 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
int now = Time.currentTime();
|
int now = Time.currentTime();
|
||||||
if (isClaimEnabled("issuedAt")) reqToken.issuedAt(now);
|
if (isClaimEnabled("issuedAt")) reqToken.issuedAt(now);
|
||||||
// For the time being there's no getter for tokenTimeout in JWTClientCredentialsProvider
|
if (isClaimEnabled("expiration")) reqToken.expiration(now + getTokenTimeout());
|
||||||
// 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("notBefore")) reqToken.notBefore(now);
|
if (isClaimEnabled("notBefore")) reqToken.notBefore(now);
|
||||||
|
|
||||||
return reqToken;
|
return reqToken;
|
||||||
|
|
Loading…
Reference in a new issue