Browse Source

implemented key rotation in RotatingKeyManager

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
sqlite
Stephan Richter 3 months ago
parent
commit
0e7bdb5442
  1. 21
      de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/RotatingKeyManager.java
  2. 4
      de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/PlaintextKeyStore.java

21
de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/RotatingKeyManager.java

@ -1,12 +1,16 @@
/* © SRSoftware 2024 */ /* © SRSoftware 2024 */
package de.srsoftware.oidc.backend; package de.srsoftware.oidc.backend;
import static de.srsoftware.oidc.api.Constants.EXPIRATION;
import static de.srsoftware.utils.Optionals.nullable;
import static de.srsoftware.utils.Strings.uuid; import static de.srsoftware.utils.Strings.uuid;
import static org.jose4j.jws.AlgorithmIdentifiers.RSA_USING_SHA256; import static org.jose4j.jws.AlgorithmIdentifiers.RSA_USING_SHA256;
import de.srsoftware.oidc.api.KeyManager; import de.srsoftware.oidc.api.KeyManager;
import de.srsoftware.oidc.api.KeyStorage; import de.srsoftware.oidc.api.KeyStorage;
import java.io.IOException; import java.io.IOException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import org.jose4j.jwk.PublicJsonWebKey; import org.jose4j.jwk.PublicJsonWebKey;
import org.jose4j.jwk.RsaJwkGenerator; import org.jose4j.jwk.RsaJwkGenerator;
import org.jose4j.lang.JoseException; import org.jose4j.lang.JoseException;
@ -21,8 +25,19 @@ public class RotatingKeyManager implements KeyManager {
@Override @Override
public PublicJsonWebKey getKey() throws KeyCreationException, IOException { public PublicJsonWebKey getKey() throws KeyCreationException, IOException {
var list = store.listKeys(); for (var keyId : store.listKeys()) {
return list.isEmpty() ? createNewKey() : store.load(list.get(0)); try {
var key = store.load(keyId);
var expired = nullable(key.getOtherParameterValue(EXPIRATION, Long.class)).map(Instant::ofEpochSecond).map(expiration -> expiration.isBefore(Instant.now())).orElse(false);
if (expired) {
store.drop(keyId);
} else
return key;
} catch (Exception e) {
LOG.log(System.Logger.Level.WARNING, "Failed to load key with id {0}", keyId);
}
}
return createNewKey();
} }
private PublicJsonWebKey createNewKey() throws KeyCreationException, IOException { private PublicJsonWebKey createNewKey() throws KeyCreationException, IOException {
@ -30,7 +45,9 @@ public class RotatingKeyManager implements KeyManager {
var key = RsaJwkGenerator.generateJwk(2048); var key = RsaJwkGenerator.generateJwk(2048);
key.setAlgorithm(RSA_USING_SHA256); key.setAlgorithm(RSA_USING_SHA256);
key.setKeyId(uuid()); key.setKeyId(uuid());
key.setOtherParameter(EXPIRATION, Instant.now().plus(1, ChronoUnit.DAYS).getEpochSecond());
store.store(key); store.store(key);
LOG.log(System.Logger.Level.INFO, "Created new JsonWebKey (Id: {0})", key.getKeyId());
return key; return key;
} catch (JoseException e) { } catch (JoseException e) {
throw new KeyCreationException(e); throw new KeyCreationException(e);

4
de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/PlaintextKeyStore.java

@ -1,6 +1,7 @@
/* © SRSoftware 2024 */ /* © SRSoftware 2024 */
package de.srsoftware.oidc.datastore.file; package de.srsoftware.oidc.datastore.file;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.ERROR; import static java.lang.System.Logger.Level.ERROR;
import static org.jose4j.jwk.JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE; import static org.jose4j.jwk.JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE;
@ -26,7 +27,8 @@ public class PlaintextKeyStore implements KeyStorage {
} }
@Override @Override
public KeyStorage drop(String keyId) { public KeyStorage drop(String keyId) {
return null; if (dir.resolve(keyId + ".key").toFile().delete()) LOG.log(DEBUG, "Removed key {0}", keyId);
return this;
} }
@Override @Override

Loading…
Cancel
Save