KeyForge is a Java library for generating and parsing structured API keys with optional expiration and custom metadata.
- Security: API keys should be unique, hard to guess, and securely stored.
- Expiration: Keys should have an expiration date to limit the risk if they are compromised.
- Identification: Keys should include metadata to identify the client or user they are associated with.
- Revocation: It should be possible to revoke keys if they are compromised or no longer needed.
- Java 17 or higher
dependencies {
implementation("com.github.bgalek:keyforge:1.0.2")
}Generates a timestamped key backed by a UUIDv7. The issued-at timestamp can be recovered from the key itself.
public class Example {
public static void main(String[] args) {
KeyForge keyForge = new KeyForge();
ApiKey apiKey = keyForge.newKey()
.withIdentifier("myapp")
.build();
System.out.println(apiKey);
// sk_myapp_MDE5MmVkOGFhZGMyNzRiZGJlYTk4M2E4ZDk3NGU4NTc
System.out.println(apiKey.getIssuedAt());
// 2024-10-20T15:03:05.930Z
ApiKey parsed = keyForge.parse(apiKey.toString());
System.out.println(parsed.getIdentifier()); // myapp
}
}Embeds an expiration timestamp in the key. Call isExpired(clock) to validate at request time.
public class Example {
public static void main(String[] args) {
ExpiringKeyForge keyForge = new ExpiringKeyForge();
ExpiringApiKey apiKey = keyForge.newKey()
.withIdentifier("myapp")
.withValidFor(Duration.ofMinutes(15))
.build();
System.out.println(apiKey);
// sk_myapp_MDE5MmVkODZmZWQzNzM2MDg2YWQ0MmYxNzYwOGM2N2UtMTczMDU2MjgwMA
ExpiringApiKey parsed = keyForge.parse(apiKey.toString());
System.out.println(parsed.getIdentifier()); // myapp
System.out.println(parsed.getExpirationDate()); // 2024-10-20T15:18:05Z
System.out.println(parsed.isExpired(Clock.systemUTC())); // false
}
}Embeds arbitrary key-value metadata in the key instead of a UUID.
public class Example {
public static void main(String[] args) {
MetadataKeyForge keyForge = new MetadataKeyForge();
MetadataApiKey apiKey = keyForge.newKey()
.withMetadata(Map.of("account", "123"))
.build();
System.out.println(apiKey);
// sk_YWNjb3VudD0xMjM
MetadataApiKey parsed = keyForge.parse(apiKey.toString());
System.out.println(parsed.getMetadata()); // {account=123}
}
}Both sk (secret key) and pk (public key) prefixes are supported via ApiKeyType:
ApiKey apiKey = keyForge.newKey()
.withType(ApiKeyType.PUBLIC_KEY)
.withIdentifier("myapp")
.build();
// pk_myapp_...All forge implementations accept an optional Clock for testing or time-zone control:
KeyForge keyForge = new KeyForge(Clock.fixed(Instant.parse("2024-01-01T00:00:00Z"), ZoneOffset.UTC));