From e7513fee76bbf56bde673e5950a0e9247b29f200 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sat, 3 Aug 2024 22:20:32 +0200 Subject: [PATCH] made TokenController configurable Signed-off-by: Stephan Richter --- .../de/srsoftware/oidc/app/Application.java | 6 ++--- .../oidc/backend/TokenController.java | 27 ++++++++++++------- .../java/de/srsoftware/utils/Optionals.java | 4 +-- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java b/de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java index 7254545..c3c10b4 100644 --- a/de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java +++ b/de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java @@ -61,11 +61,11 @@ public class Application { new Forward(INDEX).bindPath(ROOT).on(server); new WellKnownController().bindPath(WELL_KNOWN).on(server); new UserController(fileStore, fileStore).bindPath(API_USER).on(server); - new TokenController(fileStore, fileStore, keyManager, fileStore).bindPath(API_TOKEN).on(server); + var tokenControllerconfig = new TokenController.Configuration("https://lightoidc.srsoftware.de", 10); // TODO configure or derive from hostname + new TokenController(fileStore, fileStore, keyManager, fileStore, tokenControllerconfig).bindPath(API_TOKEN).on(server); new ClientController(fileStore, fileStore, fileStore).bindPath(API_CLIENT).on(server); new KeyStoreController(keyStore).bindPath(JWKS).on(server); - // server.setExecutor(Executors.newCachedThreadPool()); - server.setExecutor(Executors.newSingleThreadExecutor()); + server.setExecutor(Executors.newCachedThreadPool()); server.start(); } diff --git a/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/TokenController.java b/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/TokenController.java index b6554b9..6243814 100644 --- a/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/TokenController.java +++ b/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/TokenController.java @@ -20,16 +20,20 @@ import org.jose4j.lang.JoseException; import org.json.JSONObject; public class TokenController extends PathHandler { + public record Configuration(String issuer, int tokenExpirationMinutes) { + } private final ClientService clients; private final AuthorizationService authorizations; private final UserService users; private final KeyManager keyManager; + private Configuration config; - public TokenController(AuthorizationService authorizationService, ClientService clientService, KeyManager keyManager, UserService userService) { + public TokenController(AuthorizationService authorizationService, ClientService clientService, KeyManager keyManager, UserService userService, Configuration configuration) { authorizations = authorizationService; clients = clientService; this.keyManager = keyManager; users = userService; + config = configuration; } private Map deserialize(String body) { @@ -90,7 +94,7 @@ public class TokenController extends PathHandler { try { PublicJsonWebKey key = keyManager.getKey(); key.setUse("sig"); - JwtClaims claims = getJwtClaims(user, client); + JwtClaims claims = createIdTokenClaims(user, client); // A JWT is a JWS and/or a JWE with JSON claims as the payload. // In this example it is a JWS so we create a JsonWebSignature object. @@ -108,17 +112,20 @@ public class TokenController extends PathHandler { } } - private static JwtClaims getJwtClaims(User user, Client client) { + private JwtClaims createIdTokenClaims(User user, Client client) { JwtClaims claims = new JwtClaims(); - claims.setAudience(client.id(), "test"); + + // required claims: + claims.setIssuer(config.issuer); // who creates the token and signs it + claims.setSubject(user.uuid()); // the subject/principal is whom the token is about + claims.setAudience(client.id()); + claims.setExpirationTimeMinutesInTheFuture(config.tokenExpirationMinutes); // time when the token will expire (10 minutes from now) + claims.setIssuedAtToNow(); // when the token was issued/created (now) + claims.setClaim("client_id", client.id()); - claims.setClaim("email", user.email()); // additional claims/attributes about the subject can be added - claims.setExpirationTimeMinutesInTheFuture(10); // time when the token will expire (10 minutes from now) - claims.setIssuedAtToNow(); // when the token was issued/created (now) - claims.setIssuer("https://lightoidc.srsoftware.de"); // who creates the token and signs it - claims.setGeneratedJwtId(); // a unique identifier for the token - claims.setSubject(user.uuid()); // the subject/principal is whom the token is about + claims.setClaim("email", user.email()); // additional claims/attributes about the subject can be added client.nonce().ifPresent(nonce -> claims.setClaim(NONCE, nonce)); + claims.setGeneratedJwtId(); // a unique identifier for the token return claims; } } diff --git a/de.srsoftware.utils/src/main/java/de/srsoftware/utils/Optionals.java b/de.srsoftware.utils/src/main/java/de/srsoftware/utils/Optionals.java index 5c208d4..2a239af 100644 --- a/de.srsoftware.utils/src/main/java/de/srsoftware/utils/Optionals.java +++ b/de.srsoftware.utils/src/main/java/de/srsoftware/utils/Optionals.java @@ -1,9 +1,9 @@ /* © SRSoftware 2024 */ package de.srsoftware.utils; -import java.util.Optional; - import static java.util.Optional.empty; +import java.util.Optional; + public class Optionals { public static Optional nullable(T val) { return Optional.ofNullable(val);