diff --git a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Client.java b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Client.java new file mode 100644 index 0000000..08743cd --- /dev/null +++ b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Client.java @@ -0,0 +1,6 @@ +package de.srsoftware.oidc.api; + +import java.util.Set; + +public record Client(String id, Set redirectUris) { +} diff --git a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/ClientService.java b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/ClientService.java new file mode 100644 index 0000000..f8b3586 --- /dev/null +++ b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/ClientService.java @@ -0,0 +1,10 @@ +package de.srsoftware.oidc.api; + +import java.util.Optional; + +public interface ClientService { + Optional getClient(String clientId); + ClientService add(Client client); + ClientService remove(Client client); + ClientService update(Client client); +} diff --git a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Permission.java b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Permission.java new file mode 100644 index 0000000..c9b03ed --- /dev/null +++ b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Permission.java @@ -0,0 +1,7 @@ +package de.srsoftware.oidc.api; + +public enum Permission { + CREATE_CLIENT, + ALTER_CLIENT, + REMOVE_CLIENT +} diff --git a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/User.java b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/User.java index 659059c..31f96a3 100644 --- a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/User.java +++ b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/User.java @@ -1,15 +1,17 @@ /* © SRSoftware 2024 */ package de.srsoftware.oidc.api; -import java.util.Map; -import java.util.Objects; +import java.util.*; public final class User { public static final String EMAIL = "email"; public static final String PASSWORD = "password"; + public static final String PERMISSIONS = "permissions"; public static final String REALNAME = "realname"; public static final String USERNAME = "username"; + private final Set permissions = new HashSet<>(); + private String email, hashedPassword, realName, uuid, username; public User(String username, String hashedPassword, String realName, String email, String uuid) { @@ -20,6 +22,11 @@ public final class User { this.uuid = uuid; } + public User add(Permission permission) { + permissions.add(permission); + return this; + } + public String email() { return email; } @@ -37,6 +44,10 @@ public final class User { return Objects.equals(this.uuid, that.uuid); } + public boolean hasPermission(Permission permission){ + return permissions.contains(permission); + } + public String hashedPassword() { return hashedPassword; } @@ -52,8 +63,10 @@ public final class User { } - public Map map(boolean includePassword) { - return includePassword ? Map.of(USERNAME, username, REALNAME, realName, PASSWORD, hashedPassword, EMAIL, email) : Map.of(USERNAME, username, REALNAME, realName, EMAIL, email); + public Map map(boolean includePassword) { + return includePassword + ? Map.of(USERNAME, username, REALNAME, realName, EMAIL, email, PERMISSIONS, permissions, PASSWORD, hashedPassword) + : Map.of(USERNAME, username, REALNAME, realName, EMAIL, email, PERMISSIONS, permissions); } public String realName() { 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 9823706..444901d 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 @@ -3,6 +3,7 @@ package de.srsoftware.oidc.app; import com.sun.net.httpserver.HttpServer; +import de.srsoftware.oidc.api.ClientService; import de.srsoftware.oidc.api.SessionService; import de.srsoftware.oidc.api.User; import de.srsoftware.oidc.api.UserService; @@ -17,6 +18,8 @@ import java.nio.file.Path; import java.util.*; import java.util.concurrent.Executors; +import static de.srsoftware.oidc.api.Permission.CREATE_CLIENT; + public class Application { public static final String BACKEND = "/api"; private static final String FAVICON = "/favicon.ico"; @@ -35,14 +38,15 @@ public class Application { var storageFile = new File("/tmp/lightoidc.json"); var passwordHasher = new UuidHasher(); var firstHash = passwordHasher.hash(FIRST_USER_PASS, FIRST_UUID); - var firstUser = new User(FIRST_USER, firstHash, FIRST_USER, "%s@internal".formatted(FIRST_USER), FIRST_UUID); + var firstUser = new User(FIRST_USER, firstHash, FIRST_USER, "%s@internal".formatted(FIRST_USER), FIRST_UUID).add(CREATE_CLIENT); FileStore fileStore = new FileStore(storageFile, passwordHasher).init(firstUser); - UserService userService = fileStore; + ClientService clientService = fileStore; SessionService sessionService = fileStore; + UserService userService = fileStore; HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); new StaticPages(basePath).bindPath(STATIC_PATH, FAVICON).on(server); new Forward(INDEX).bindPath(ROOT).on(server); - new Backend(sessionService, userService).bindPath(BACKEND, WELL_KNOWN).on(server); + new Backend(clientService, sessionService, userService).bindPath(BACKEND, WELL_KNOWN).on(server); server.setExecutor(Executors.newCachedThreadPool()); server.start(); } diff --git a/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/Backend.java b/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/Backend.java index 690e77c..58bbc34 100644 --- a/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/Backend.java +++ b/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/Backend.java @@ -19,8 +19,10 @@ public class Backend extends PathHandler { private static final String REDIRECT_URI = "redirect_uri"; private final SessionService sessions; private final UserService users; + private final ClientService clients; - public Backend(SessionService sessionService, UserService userService) { + public Backend(ClientService clientService, SessionService sessionService, UserService userService) { + clients = clientService; sessions = sessionService; users = userService; } diff --git a/de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/FileStore.java b/de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/FileStore.java index bba68b7..bb92af9 100644 --- a/de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/FileStore.java +++ b/de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/FileStore.java @@ -14,7 +14,7 @@ import java.time.temporal.ChronoUnit; import java.util.*; import org.json.JSONObject; -public class FileStore implements SessionService, UserService { +public class FileStore implements ClientService, SessionService, UserService { private static final String EXPIRATION = "expiration"; private static final String SESSIONS = "sessions"; private static final String USERS = "users"; @@ -54,6 +54,7 @@ public class FileStore implements SessionService, UserService { return null; } + @Override public FileStore init(User defaultUser) { if (!json.has(SESSIONS)) json.put(SESSIONS, new JSONObject()); @@ -71,8 +72,8 @@ public class FileStore implements SessionService, UserService { public Optional load(String userId) { try { var users = json.getJSONObject(USERS); - var user = users.getJSONObject(userId); - return Optional.of(new User(user.getString(USERNAME), user.getString(PASSWORD), user.getString(REALNAME), user.getString(EMAIL), userId)); + var userData = users.getJSONObject(userId); + return userOf(userData,userId); } catch (Exception ignored) { } return Optional.empty(); @@ -83,12 +84,12 @@ public class FileStore implements SessionService, UserService { try { var users = json.getJSONObject(USERS); var uuids = users.keySet(); - for (String uuid : uuids) { - var user = users.getJSONObject(uuid); - if (!user.getString(USERNAME).equals(username)) continue; - var hashedPass = user.getString(PASSWORD); + for (String userId : uuids) { + var userData = users.getJSONObject(userId); + if (!userData.getString(USERNAME).equals(username)) continue; + var hashedPass = userData.getString(PASSWORD); if (passwordHasher.matches(password, hashedPass)) { - return Optional.of(new User(username, hashedPass, user.getString(REALNAME), user.getString(EMAIL), uuid)); + return userOf(userData,userId); } } return Optional.empty(); @@ -109,6 +110,21 @@ public class FileStore implements SessionService, UserService { return save(); } + private Optional userOf(JSONObject json, String userId){ + var user = new User(json.getString(USERNAME), json.getString(PASSWORD), json.getString(REALNAME), json.getString(EMAIL), userId); + var perms = json.getJSONArray(PERMISSIONS); + for (Object perm : perms){ + try { + if (perm instanceof String s) user.add(Permission.valueOf(s)); + } catch (Exception e){ + e.printStackTrace(); + } + } + + return Optional.of(user); + } + + /*** Session Service Methods ***/ @Override @@ -153,4 +169,25 @@ public class FileStore implements SessionService, UserService { public SessionService setDuration(Duration duration) { return null; } + + /** client service methods **/ + @Override + public Optional getClient(String clientId) { + return Optional.empty(); + } + + @Override + public ClientService add(Client client) { + return null; + } + + @Override + public ClientService remove(Client client) { + return null; + } + + @Override + public ClientService update(Client client) { + return null; + } } diff --git a/de.srsoftware.oidc.web/src/main/resources/en/index.html b/de.srsoftware.oidc.web/src/main/resources/en/index.html index d96e342..46388d9 100644 --- a/de.srsoftware.oidc.web/src/main/resources/en/index.html +++ b/de.srsoftware.oidc.web/src/main/resources/en/index.html @@ -7,11 +7,11 @@

Welcome!

-

Connected sites

- These are sites that are connected with your account: +

Clients

+ These are clients that are registered with LightOIDC: - +
SiteClient Actions