working on client service
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -2,5 +2,5 @@ package de.srsoftware.oidc.api;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public record Client(String id, Set<String> redirectUris) {
|
public record Client(String id, String name, Set<String> redirectUris) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package de.srsoftware.oidc.api;
|
package de.srsoftware.oidc.api;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface ClientService {
|
public interface ClientService {
|
||||||
Optional<Client> getClient(String clientId);
|
Optional<Client> getClient(String clientId);
|
||||||
ClientService add(Client client);
|
ClientService add(Client client);
|
||||||
|
List<Client> listClients();
|
||||||
ClientService remove(Client client);
|
ClientService remove(Client client);
|
||||||
ClientService update(Client client);
|
ClientService update(Client client);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package de.srsoftware.oidc.api;
|
package de.srsoftware.oidc.api;
|
||||||
|
|
||||||
public enum Permission {
|
public enum Permission {
|
||||||
CREATE_CLIENT,
|
MANAGE_CLIENTS
|
||||||
ALTER_CLIENT,
|
|
||||||
REMOVE_CLIENT
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.nio.file.Path;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import static de.srsoftware.oidc.api.Permission.CREATE_CLIENT;
|
import static de.srsoftware.oidc.api.Permission.MANAGE_CLIENTS;
|
||||||
|
|
||||||
public class Application {
|
public class Application {
|
||||||
public static final String BACKEND = "/api";
|
public static final String BACKEND = "/api";
|
||||||
@@ -38,7 +38,7 @@ public class Application {
|
|||||||
var storageFile = new File("/tmp/lightoidc.json");
|
var storageFile = new File("/tmp/lightoidc.json");
|
||||||
var passwordHasher = new UuidHasher();
|
var passwordHasher = new UuidHasher();
|
||||||
var firstHash = passwordHasher.hash(FIRST_USER_PASS, FIRST_UUID);
|
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).add(CREATE_CLIENT);
|
var firstUser = new User(FIRST_USER, firstHash, FIRST_USER, "%s@internal".formatted(FIRST_USER), FIRST_UUID).add(MANAGE_CLIENTS);
|
||||||
FileStore fileStore = new FileStore(storageFile, passwordHasher).init(firstUser);
|
FileStore fileStore = new FileStore(storageFile, passwordHasher).init(firstUser);
|
||||||
ClientService clientService = fileStore;
|
ClientService clientService = fileStore;
|
||||||
SessionService sessionService = fileStore;
|
SessionService sessionService = fileStore;
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
/* © SRSoftware 2024 */
|
/* © SRSoftware 2024 */
|
||||||
package de.srsoftware.oidc.backend;
|
package de.srsoftware.oidc.backend;
|
||||||
|
|
||||||
|
import static de.srsoftware.oidc.api.Permission.MANAGE_CLIENTS;
|
||||||
import static de.srsoftware.oidc.api.User.PASSWORD;
|
import static de.srsoftware.oidc.api.User.PASSWORD;
|
||||||
import static de.srsoftware.oidc.api.User.USERNAME;
|
import static de.srsoftware.oidc.api.User.USERNAME;
|
||||||
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
|
import static java.net.HttpURLConnection.*;
|
||||||
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import de.srsoftware.cookies.SessionToken;
|
import de.srsoftware.cookies.SessionToken;
|
||||||
import de.srsoftware.oidc.api.*;
|
import de.srsoftware.oidc.api.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class Backend extends PathHandler {
|
public class Backend extends PathHandler {
|
||||||
@@ -35,6 +38,14 @@ public class Backend extends PathHandler {
|
|||||||
return sendEmptyResponse(HTTP_NOT_FOUND,ex);
|
return sendEmptyResponse(HTTP_NOT_FOUND,ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean clients(HttpExchange ex, Session session) throws IOException {
|
||||||
|
var user = session.user();
|
||||||
|
if (!user.hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN,ex);
|
||||||
|
var json = new JSONObject();
|
||||||
|
clients.listClients().forEach(client -> json.put(client.id(), Map.of("name",client.name(),"redirect_uris",client.redirectUris())));
|
||||||
|
return sendContent(ex,json);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean doLogin(HttpExchange ex) throws IOException {
|
private boolean doLogin(HttpExchange ex) throws IOException {
|
||||||
var body = json(ex);
|
var body = json(ex);
|
||||||
|
|
||||||
@@ -48,7 +59,6 @@ public class Backend extends PathHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean doGet(String path, HttpExchange ex) throws IOException {
|
public boolean doGet(String path, HttpExchange ex) throws IOException {
|
||||||
System.out.printf("GET %s…\n", path);
|
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/openid-configuration":
|
case "/openid-configuration":
|
||||||
return openidConfig(ex);
|
return openidConfig(ex);
|
||||||
@@ -58,8 +68,6 @@ public class Backend extends PathHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean doPost(String path, HttpExchange ex) throws IOException {
|
public boolean doPost(String path, HttpExchange ex) throws IOException {
|
||||||
System.out.printf("POST %s…\n", path);
|
|
||||||
|
|
||||||
// pre-login paths
|
// pre-login paths
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/login":
|
case "/login":
|
||||||
@@ -73,6 +81,8 @@ public class Backend extends PathHandler {
|
|||||||
switch (path) {
|
switch (path) {
|
||||||
case "/authorize":
|
case "/authorize":
|
||||||
return authorize(ex,session);
|
return authorize(ex,session);
|
||||||
|
case "/clients":
|
||||||
|
return clients(ex,session);
|
||||||
case "/user":
|
case "/user":
|
||||||
return sendUserAndCookie(ex, session);
|
return sendUserAndCookie(ex, session);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,8 @@ public class FileStore implements ClientService, SessionService, UserService {
|
|||||||
var perms = json.getJSONArray(PERMISSIONS);
|
var perms = json.getJSONArray(PERMISSIONS);
|
||||||
for (Object perm : perms){
|
for (Object perm : perms){
|
||||||
try {
|
try {
|
||||||
if (perm instanceof String s) user.add(Permission.valueOf(s));
|
if (perm instanceof String s) perm = Permission.valueOf(s);
|
||||||
|
if (perm instanceof Permission p) user.add(p);
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -171,14 +172,20 @@ public class FileStore implements ClientService, SessionService, UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** client service methods **/
|
/** client service methods **/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientService add(Client client) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Client> getClient(String clientId) {
|
public Optional<Client> getClient(String clientId) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientService add(Client client) {
|
public List<Client> listClients() {
|
||||||
return null;
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
28
de.srsoftware.oidc.web/src/main/resources/en/clients.html
Normal file
28
de.srsoftware.oidc.web/src/main/resources/en/clients.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Light OIDC</title>
|
||||||
|
<script src="config.js"></script>
|
||||||
|
<script src="user.js"></script>
|
||||||
|
<script src="clients.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav>
|
||||||
|
<a id="clients" href="clients.html">Clients</a>
|
||||||
|
</nav>
|
||||||
|
<h1>Welcome!</h1>
|
||||||
|
<h2>Clients</h2>
|
||||||
|
These are clients that are registered with LightOIDC:
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Client</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<button onclick="window.location.href='newclient.html';">Add new site…</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
11
de.srsoftware.oidc.web/src/main/resources/en/clients.js
Normal file
11
de.srsoftware.oidc.web/src/main/resources/en/clients.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
async function handleClients(response){
|
||||||
|
if (response.status == UNAUTHORIZED) {
|
||||||
|
window.location.href = 'login.html?return_to='+encodeURI(window.location.href);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var clients = await response.json();
|
||||||
|
console.log(clients);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(api+"/clients",{method:'POST'}).then(handleClients);
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
var api = "/api";
|
var api = "/api";
|
||||||
var web = "/web";
|
var web = "/web";
|
||||||
|
|
||||||
|
const UNAUTHORIZED = 401;
|
||||||
|
|||||||
@@ -6,19 +6,9 @@
|
|||||||
<script src="user.js"></script>
|
<script src="user.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<nav>
|
||||||
|
<a id="clients" href="clients.html">Clients</a>
|
||||||
|
</nav>
|
||||||
<h1>Welcome!</h1>
|
<h1>Welcome!</h1>
|
||||||
<h2>Clients</h2>
|
|
||||||
These are clients that are registered with LightOIDC:
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Client</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<button onclick="window.location.href='newclient.html';">Add new site…</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
const UNAUTHORIZED = 401;
|
|
||||||
|
|
||||||
async function handleUser(response){
|
async function handleUser(response){
|
||||||
if (response.status == UNAUTHORIZED) {
|
if (response.status == UNAUTHORIZED) {
|
||||||
|
|||||||
Reference in New Issue
Block a user