mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-25 16:42:34 +00:00
KEYCLOAK-9551 KEYCLOAK-16159 Make refresh_token generation for client_credentials optional. Support for revocation of access tokens.
Co-authored-by: mposolda <mposolda@gmail.com>
This commit is contained in:
committed by
Marek Posolda
parent
1281f28bb8
commit
de20830412
@@ -18,6 +18,7 @@ package org.keycloak.client.admin.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.Option;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.client.admin.cli.config.ConfigData;
|
||||
import org.keycloak.client.admin.cli.config.ConfigHandler;
|
||||
import org.keycloak.client.admin.cli.config.FileConfigHandler;
|
||||
@@ -264,6 +265,8 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
|
||||
rdata.setClientId(clientId);
|
||||
if (secret != null)
|
||||
rdata.setSecret(secret);
|
||||
String grantTypeForAuthentication = user == null ? OAuth2Constants.CLIENT_CREDENTIALS : OAuth2Constants.PASSWORD;
|
||||
rdata.setGrantTypeForAuthentication(grantTypeForAuthentication);
|
||||
}
|
||||
|
||||
protected void checkUnsupportedOptions(String ... options) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.client.admin.cli.config.ConfigData;
|
||||
import org.keycloak.client.admin.cli.config.RealmConfigData;
|
||||
import org.keycloak.client.admin.cli.util.AuthUtil;
|
||||
@@ -120,8 +121,10 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd {
|
||||
boolean clientSet = clientId != null;
|
||||
|
||||
applyDefaultOptionValues();
|
||||
String grantTypeForAuthentication = null;
|
||||
|
||||
if (user != null) {
|
||||
grantTypeForAuthentication = OAuth2Constants.PASSWORD;
|
||||
printErr("Logging into " + server + " as user " + user + " of realm " + realm);
|
||||
|
||||
// if user was set there needs to be a password so we can authenticate
|
||||
@@ -133,6 +136,7 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd {
|
||||
secret = readSecret("Enter client secret: ", commandInvocation);
|
||||
}
|
||||
} else if (keystore != null || secret != null || clientSet) {
|
||||
grantTypeForAuthentication = OAuth2Constants.CLIENT_CREDENTIALS;
|
||||
printErr("Logging into " + server + " as " + "service-account-" + clientId + " of realm " + realm);
|
||||
if (keystore == null) {
|
||||
if (secret == null) {
|
||||
@@ -190,7 +194,7 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd {
|
||||
Long sigExpiresAt = signedRequestToken == null ? null : System.currentTimeMillis() + sigLifetime * 1000;
|
||||
|
||||
// save tokens to config file
|
||||
saveTokens(tokens, server, realm, clientId, signedRequestToken, sigExpiresAt, secret);
|
||||
saveTokens(tokens, server, realm, clientId, signedRequestToken, sigExpiresAt, secret, grantTypeForAuthentication);
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ public class RealmConfigData {
|
||||
|
||||
private String secret;
|
||||
|
||||
private String grantTypeForAuthentication;
|
||||
|
||||
private Long expiresAt;
|
||||
|
||||
private Long refreshExpiresAt;
|
||||
@@ -102,6 +104,14 @@ public class RealmConfigData {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public String getGrantTypeForAuthentication() {
|
||||
return grantTypeForAuthentication;
|
||||
}
|
||||
|
||||
public void setGrantTypeForAuthentication(String grantTypeForAuthentication) {
|
||||
this.grantTypeForAuthentication = grantTypeForAuthentication;
|
||||
}
|
||||
|
||||
public Long getExpiresAt() {
|
||||
return expiresAt;
|
||||
}
|
||||
@@ -134,6 +144,7 @@ public class RealmConfigData {
|
||||
refreshToken = source.refreshToken;
|
||||
signingToken = source.signingToken;
|
||||
secret = source.secret;
|
||||
grantTypeForAuthentication = source.grantTypeForAuthentication;
|
||||
expiresAt = source.expiresAt;
|
||||
refreshExpiresAt = source.refreshExpiresAt;
|
||||
sigExpiresAt = source.sigExpiresAt;
|
||||
@@ -164,6 +175,7 @@ public class RealmConfigData {
|
||||
data.refreshToken = refreshToken;
|
||||
data.signingToken = signingToken;
|
||||
data.secret = secret;
|
||||
data.grantTypeForAuthentication = grantTypeForAuthentication;
|
||||
data.expiresAt = expiresAt;
|
||||
data.refreshExpiresAt = refreshExpiresAt;
|
||||
data.sigExpiresAt = sigExpiresAt;
|
||||
|
||||
@@ -62,7 +62,7 @@ public class AuthUtil {
|
||||
|
||||
// check refresh_token against expiry time
|
||||
// if it's less than 5s to expiry, fail with credentials expired
|
||||
if (realmConfig.getRefreshExpiresAt() - now < 5000) {
|
||||
if (realmConfig.getRefreshExpiresAt() != null && realmConfig.getRefreshExpiresAt() - now < 5000) {
|
||||
throw new RuntimeException("Session has expired. Login again with '" + OsUtil.CMD + " config credentials'");
|
||||
}
|
||||
|
||||
@@ -72,10 +72,15 @@ public class AuthUtil {
|
||||
|
||||
try {
|
||||
String authorization = null;
|
||||
StringBuilder body = new StringBuilder();
|
||||
if (realmConfig.getRefreshToken() != null) {
|
||||
body.append("grant_type=refresh_token")
|
||||
.append("&refresh_token=").append(realmConfig.getRefreshToken());
|
||||
} else {
|
||||
body.append("grant_type=").append(realmConfig.getGrantTypeForAuthentication());
|
||||
}
|
||||
|
||||
StringBuilder body = new StringBuilder("grant_type=refresh_token")
|
||||
.append("&refresh_token=").append(realmConfig.getRefreshToken())
|
||||
.append("&client_id=").append(urlencode(realmConfig.getClientId()));
|
||||
body.append("&client_id=").append(urlencode(realmConfig.getClientId()));
|
||||
|
||||
if (realmConfig.getSigningToken() != null) {
|
||||
body.append("&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
|
||||
@@ -94,7 +99,9 @@ public class AuthUtil {
|
||||
realmData.setToken(token.getToken());
|
||||
realmData.setRefreshToken(token.getRefreshToken());
|
||||
realmData.setExpiresAt(currentTimeMillis() + token.getExpiresIn() * 1000);
|
||||
realmData.setRefreshExpiresAt(currentTimeMillis() + token.getRefreshExpiresIn() * 1000);
|
||||
if (token.getRefreshToken() != null) {
|
||||
realmData.setRefreshExpiresAt(currentTimeMillis() + token.getRefreshExpiresIn() * 1000);
|
||||
}
|
||||
});
|
||||
return token.getToken();
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.keycloak.client.admin.cli.util;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.client.admin.cli.config.ConfigData;
|
||||
import org.keycloak.client.admin.cli.config.ConfigHandler;
|
||||
import org.keycloak.client.admin.cli.config.ConfigUpdateOperation;
|
||||
@@ -44,7 +45,8 @@ public class ConfigUtil {
|
||||
ConfigUtil.handler = handler;
|
||||
}
|
||||
|
||||
public static void saveTokens(AccessTokenResponse tokens, String endpoint, String realm, String clientId, String signKey, Long sigExpiresAt, String secret) {
|
||||
public static void saveTokens(AccessTokenResponse tokens, String endpoint, String realm, String clientId, String signKey, Long sigExpiresAt, String secret,
|
||||
String grantTypeForAuthentication) {
|
||||
handler.saveMergeConfig(config -> {
|
||||
config.setServerUrl(endpoint);
|
||||
config.setRealm(realm);
|
||||
@@ -55,10 +57,13 @@ public class ConfigUtil {
|
||||
realmConfig.setSigningToken(signKey);
|
||||
realmConfig.setSecret(secret);
|
||||
realmConfig.setExpiresAt(System.currentTimeMillis() + tokens.getExpiresIn() * 1000);
|
||||
realmConfig.setRefreshExpiresAt(tokens.getRefreshExpiresIn() == 0 ?
|
||||
Long.MAX_VALUE : System.currentTimeMillis() + tokens.getRefreshExpiresIn() * 1000);
|
||||
if (realmConfig.getRefreshToken() != null) {
|
||||
realmConfig.setRefreshExpiresAt(tokens.getRefreshExpiresIn() == 0 ?
|
||||
Long.MAX_VALUE : System.currentTimeMillis() + tokens.getRefreshExpiresIn() * 1000);
|
||||
}
|
||||
realmConfig.setSigExpiresAt(sigExpiresAt);
|
||||
realmConfig.setClientId(clientId);
|
||||
realmConfig.setGrantTypeForAuthentication(grantTypeForAuthentication);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,8 +81,12 @@ public class ConfigUtil {
|
||||
}
|
||||
|
||||
public static boolean credentialsAvailable(ConfigData config) {
|
||||
return config.getServerUrl() != null && (config.getExternalToken() != null || (config.getRealm() != null
|
||||
&& config.sessionRealmConfigData() != null && config.sessionRealmConfigData().getRefreshToken() != null));
|
||||
// Just supporting "client_credentials" grant type for the case when refresh token is missing
|
||||
boolean credsAvailable = config.getServerUrl() != null && (config.getExternalToken() != null || (config.getRealm() != null
|
||||
&& config.sessionRealmConfigData() != null &&
|
||||
(config.sessionRealmConfigData().getRefreshToken() != null || (config.sessionRealmConfigData().getToken() != null && OAuth2Constants.CLIENT_CREDENTIALS.equals(config.sessionRealmConfigData().getGrantTypeForAuthentication())))
|
||||
));
|
||||
return credsAvailable;
|
||||
}
|
||||
|
||||
public static ConfigData loadConfig() {
|
||||
|
||||
Reference in New Issue
Block a user