Merge pull request #873 from stianst/master
Use HmacSHA256 for code signatures
This commit is contained in:
commit
5c2e7df7de
8 changed files with 49 additions and 14 deletions
|
@ -2,6 +2,7 @@ package org.keycloak.models;
|
|||
|
||||
import org.keycloak.enums.SslRequired;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
@ -99,6 +100,8 @@ public interface RealmModel extends RoleContainerModel {
|
|||
|
||||
String getCodeSecret();
|
||||
|
||||
Key getCodeSecretKey();
|
||||
|
||||
void setCodeSecret(String codeSecret);
|
||||
|
||||
X509Certificate getCertificate();
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.util.CertificateUtils;
|
||||
import org.keycloak.util.PemUtils;
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.security.Key;
|
||||
|
@ -77,6 +78,10 @@ public final class KeycloakModelUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Key getSecretKey(String secret) {
|
||||
return secret != null ? new SecretKeySpec(secret.getBytes(), "HmacSHA256") : null;
|
||||
}
|
||||
|
||||
public static String getPemFromKey(Key key) {
|
||||
StringWriter writer = new StringWriter();
|
||||
PEMWriter pemWriter = new PEMWriter(writer);
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.keycloak.models.UserFederationProviderModel;
|
|||
import org.keycloak.models.cache.entities.CachedRealm;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
@ -34,6 +35,7 @@ public class RealmAdapter implements RealmModel {
|
|||
protected RealmCache cache;
|
||||
protected volatile transient PublicKey publicKey;
|
||||
protected volatile transient PrivateKey privateKey;
|
||||
protected volatile transient Key codeSecretKey;
|
||||
protected volatile transient X509Certificate certificate;
|
||||
|
||||
public RealmAdapter(CachedRealm cached, CacheRealmProvider cacheSession) {
|
||||
|
@ -379,6 +381,14 @@ public class RealmAdapter implements RealmModel {
|
|||
return updated != null ? updated.getCodeSecret() : cached.getCodeSecret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key getCodeSecretKey() {
|
||||
if (codeSecretKey == null) {
|
||||
codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
|
||||
}
|
||||
return codeSecretKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCodeSecret(String codeSecret) {
|
||||
getDelegateForUpdate();
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
|||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
@ -46,6 +47,7 @@ public class RealmAdapter implements RealmModel {
|
|||
protected volatile transient PublicKey publicKey;
|
||||
protected volatile transient PrivateKey privateKey;
|
||||
protected volatile transient X509Certificate certificate;
|
||||
protected volatile transient Key codeSecretKey;
|
||||
protected KeycloakSession session;
|
||||
private PasswordPolicy passwordPolicy;
|
||||
|
||||
|
@ -439,6 +441,14 @@ public class RealmAdapter implements RealmModel {
|
|||
return realm.getCodeSecret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key getCodeSecretKey() {
|
||||
if (codeSecretKey == null) {
|
||||
codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
|
||||
}
|
||||
return codeSecretKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCodeSecret(String codeSecret) {
|
||||
realm.setCodeSecret(codeSecret);
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
|
|||
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
@ -43,14 +44,13 @@ import java.util.Set;
|
|||
*/
|
||||
public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> implements RealmModel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RealmAdapter.class);
|
||||
|
||||
private final MongoRealmEntity realm;
|
||||
private final RealmProvider model;
|
||||
|
||||
protected volatile transient PublicKey publicKey;
|
||||
protected volatile transient PrivateKey privateKey;
|
||||
protected volatile transient X509Certificate certificate;
|
||||
protected volatile transient Key codeSecretKey;
|
||||
|
||||
private volatile transient PasswordPolicy passwordPolicy;
|
||||
private volatile transient KeycloakSession session;
|
||||
|
@ -424,6 +424,14 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
return realm.getCodeSecret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key getCodeSecretKey() {
|
||||
if (codeSecretKey == null) {
|
||||
codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
|
||||
}
|
||||
return codeSecretKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCodeSecret(String codeSecret) {
|
||||
realm.setCodeSecret(codeSecret);
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -108,7 +108,7 @@
|
|||
<module>events</module>
|
||||
<module>model</module>
|
||||
<module>integration</module>
|
||||
<module>proxy/proxy-server</module>
|
||||
<module>proxy</module>
|
||||
<module>picketlink</module>
|
||||
<module>federation</module>
|
||||
<module>services</module>
|
||||
|
|
|
@ -8,7 +8,8 @@ import org.keycloak.models.UserModel.RequiredAction;
|
|||
import org.keycloak.util.Base64Url;
|
||||
import org.keycloak.util.Time;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import javax.crypto.Mac;
|
||||
import java.security.Key;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
@ -147,13 +148,13 @@ public class ClientSessionCode {
|
|||
|
||||
private static String createHash(RealmModel realm, ClientSessionModel clientSession) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("sha-256");
|
||||
digest.update(realm.getCodeSecret().getBytes());
|
||||
digest.update(HASH_SEPERATOR);
|
||||
digest.update(clientSession.getId().getBytes());
|
||||
digest.update(HASH_SEPERATOR);
|
||||
digest.update(clientSession.getNote(ACTION_KEY).getBytes());
|
||||
return Base64Url.encode(digest.digest());
|
||||
Key codeSecretKey = realm.getCodeSecretKey();
|
||||
Mac mac = Mac.getInstance(codeSecretKey.getAlgorithm());
|
||||
mac.init(codeSecretKey);
|
||||
mac.update(clientSession.getId().getBytes());
|
||||
mac.update(HASH_SEPERATOR);
|
||||
mac.update(clientSession.getNote(ACTION_KEY).getBytes());
|
||||
return Base64Url.encode(mac.doFinal());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -73,9 +73,7 @@ import java.security.Principal;
|
|||
import java.util.Enumeration;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
@Ignore
|
||||
public class ProxyTest {
|
||||
static String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth"))
|
||||
.queryParam(OAuth2Constants.REDIRECT_URI, "http://localhost:8080/customer-portal").build("demo").toString();
|
||||
|
|
Loading…
Reference in a new issue