Browse Source

Merge commit '41466943eb5bd93fa948c486ca7253b33767c835' into sqlite

sqlite
Stephan Richter 4 months ago
parent
commit
93721175ac
  1. 2
      de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java
  2. 15
      de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/TokenController.java
  3. 1
      de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/UserController.java
  4. 42
      de.srsoftware.oidc.web/src/main/resources/de/authorization.html
  5. 12
      de.srsoftware.oidc.web/src/main/resources/de/reset_password.template.txt
  6. 5
      de.srsoftware.oidc.web/src/main/resources/en/scripts/authorization.js
  7. 12
      de.srsoftware.oidc.web/src/main/resources/en/scripts/clients.js
  8. 21
      de.srsoftware.oidc.web/src/main/resources/en/scripts/users.js

2
de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java

@ -81,7 +81,7 @@ public class Application {
new Forward(INDEX).bindPath(ROOT).on(server); new Forward(INDEX).bindPath(ROOT).on(server);
new WellKnownController().bindPath(WELL_KNOWN, "/realms/oidc" + WELL_KNOWN).on(server); new WellKnownController().bindPath(WELL_KNOWN, "/realms/oidc" + WELL_KNOWN).on(server);
new UserController(mailConfig, sessionService, userService, staticPages).bindPath(API_USER).on(server); new UserController(mailConfig, sessionService, userService, staticPages).bindPath(API_USER).on(server);
var tokenControllerConfig = new TokenController.Configuration("https://lightoidc.srsoftware.de", 10); // TODO configure or derive from hostname var tokenControllerConfig = new TokenController.Configuration(10);
new TokenController(authService, clientService, keyManager, userService, tokenControllerConfig).bindPath(API_TOKEN).on(server); new TokenController(authService, clientService, keyManager, userService, tokenControllerConfig).bindPath(API_TOKEN).on(server);
new ClientController(authService, clientService, sessionService, userService).bindPath(API_CLIENT).on(server); new ClientController(authService, clientService, sessionService, userService).bindPath(API_CLIENT).on(server);
new KeyStoreController(keyStore).bindPath(JWKS).on(server); new KeyStoreController(keyStore).bindPath(JWKS).on(server);

15
de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/TokenController.java

@ -27,7 +27,7 @@ import org.jose4j.lang.JoseException;
import org.json.JSONObject; import org.json.JSONObject;
public class TokenController extends PathHandler { public class TokenController extends PathHandler {
public record Configuration(String issuer, int tokenExpirationMinutes) { public record Configuration(int tokenExpirationMinutes) {
} }
private final ClientService clients; private final ClientService clients;
private final AuthorizationService authorizations; private final AuthorizationService authorizations;
@ -115,7 +115,8 @@ public class TokenController extends PathHandler {
var user = optUser.get(); var user = optUser.get();
var accessToken = users.accessToken(user); var accessToken = users.accessToken(user);
String jwToken = createJWT(client, user, accessToken); var issuer = hostname(ex);
String jwToken = createJWT(client, user, accessToken, issuer);
ex.getResponseHeaders().add("Cache-Control", "no-store"); ex.getResponseHeaders().add("Cache-Control", "no-store");
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
response.put(ACCESS_TOKEN, accessToken.id()); response.put(ACCESS_TOKEN, accessToken.id());
@ -126,13 +127,13 @@ public class TokenController extends PathHandler {
return sendContent(ex, response); return sendContent(ex, response);
} }
private String createJWT(Client client, User user, AccessToken accessToken) { private String createJWT(Client client, User user, AccessToken accessToken, String issuer) {
try { try {
PublicJsonWebKey key = keyManager.getKey(); PublicJsonWebKey key = keyManager.getKey();
var algo = key.getAlgorithm(); var algo = key.getAlgorithm();
var atHash = this.atHash(algo, accessToken); var atHash = this.atHash(algo, accessToken);
key.setUse("sig"); key.setUse("sig");
JwtClaims claims = createIdTokenClaims(user, client, atHash); JwtClaims claims = createIdTokenClaims(user, client, atHash, issuer);
// A JWT is a JWS and/or a JWE with JSON claims as the payload. // 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. // In this example it is a JWS so we create a JsonWebSignature object.
@ -167,13 +168,13 @@ public class TokenController extends PathHandler {
} }
} }
private JwtClaims createIdTokenClaims(User user, Client client, String atHash) { private JwtClaims createIdTokenClaims(User user, Client client, String atHash, String issuer) {
var optNonce = authorizations.consumeNonce(user.uuid(), client.id()); var optNonce = authorizations.consumeNonce(user.uuid(), client.id());
JwtClaims claims = new JwtClaims(); JwtClaims claims = new JwtClaims();
// required claims: // required claims:
claims.setIssuer(config.issuer); // who creates the token and signs it claims.setIssuer(issuer); // who creates the token and signs it
claims.setSubject(user.uuid()); // the subject/principal is whom the token is about claims.setSubject(user.uuid()); // the subject/principal is whom the token is about
claims.setAudience(client.id()); claims.setAudience(client.id());
claims.setExpirationTimeMinutesInTheFuture(config.tokenExpirationMinutes); // time when the token will expire (10 minutes from now) claims.setExpirationTimeMinutesInTheFuture(config.tokenExpirationMinutes); // time when the token will expire (10 minutes from now)
claims.setIssuedAtToNow(); claims.setIssuedAtToNow();

1
de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/UserController.java

@ -21,6 +21,7 @@ import jakarta.mail.*;
import jakarta.mail.internet.*; import jakarta.mail.internet.*;
import java.io.IOException; import java.io.IOException;
import java.time.Duration; import java.time.Duration;
import java.util.Comparator;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;

42
de.srsoftware.oidc.web/src/main/resources/de/authorization.html

@ -0,0 +1,42 @@
<html>
<head>
<meta charset="utf-8">
<title>Light OIDC</title>
<script src="scripts/common.js"></script>
<script src="scripts/user.js"></script>
<script src="scripts/authorization.js"></script>
<link rel="stylesheet" href="style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<nav></nav>
<div id="content" style="display: none">
Eine vertrauende Seite, <span id="rp">unknown</span>, hat Zugriff auf die folgenden Informationen erfragt:
<ul id="scopes">
</ul>
Stimmen Sie zu, diese Informationen mit <span id="rp2">unknown</span> zu teilen?
<button type="button" onclick="grantAutorization(1)">Ja - für einen Tag</button>
<button type="button" onclick="grantAutorization(7)">Ja - für eine Woche</button>
<button type="button" onclick="grantAutorization(30)">Ja - für einen Monat</button>
<button type="button" onclick="grantAutorization(365)">Ja - für ein Jahr</button>
<button type="button" onclick="denyAutorization()">No</button>
</div>
<div id="error_missing_parameter" class="error" style="display: none">
Request enthält den benötigten Parameter "<span id="parameter"></span>" nicht!
</div>
<div id="error_unknown_client" class="error" style="display: none">
Client "<span id="client_id"></span>" ist dem Backend nicht bekannt!
</div>
<div id="error_unsupported_response_type" class="error" style="display: none">
Rückgabe-Typ "<span id="response_type"></span>" wird nicht unterstützt!
</div>
<div id="error_missing_code" class="error">
Fehlender Rückgabe-Typ: code
</div>
<div id="error_invalid_redirect" class="error" style="display: none">
Ungültige Umleitung: <span id="redirect_uri"></span>
</div>
<div id="missing_scopes" class="error" style="display: none">Authorisierungs-Quelle lieferte weder eine Liste von <em>nicht-autorisierten Scopes</em> noch eine Liste von <em>authorisierten Scopes</em>! Das ist ein Server-Fehler.</div>
</body>
</html>

12
de.srsoftware.oidc.web/src/main/resources/de/reset_password.template.txt

@ -0,0 +1,12 @@
Link zum Zurückseten des Passworts für {service}
Liebe(r) {displayname},
Jemand – wahrscheinlich du – beauftragte das Passwort für {service} zurückzusetzen.
Falls du das warst öffne bitte den folgenden Link in deinem Browser:
{link}
Falls du das Zurücksetzen *nicht angefragt hast* (oder versehentlich), kannst du diese Mail einfach ignorieren.
Beste Grüße, dein OIDC-Admin.

5
de.srsoftware.oidc.web/src/main/resources/en/scripts/authorization.js

@ -84,4 +84,7 @@ function backendAutorization(){
}).then(handleResponse); }).then(handleResponse);
} }
backendAutorization(); document.addEventListener("logged_in", function(event) { // wait until page loaded
backendAutorization();
});

12
de.srsoftware.oidc.web/src/main/resources/en/scripts/clients.js

@ -8,17 +8,19 @@ function handleClients(response){
return; return;
} }
var clients = response.json().then(clients => { var clients = response.json().then(clients => {
var arr = [];
for (let id in clients) arr.push(clients[id]);
arr.sort((a,b) => a.name < b.name ? -1 : 1);
var bottom = document.getElementById('bottom'); var bottom = document.getElementById('bottom');
for (let id in clients){ for (let client of arr){
var row = document.createElement("tr"); var row = document.createElement("tr");
var client = clients[id];
row.innerHTML = `<td>${client.name}</td> row.innerHTML = `<td>${client.name}</td>
<td>${id}</td> <td>${client.client_id}</td>
<td>${client.redirect_uris.join("<br/>")}</td> <td>${client.redirect_uris.join("<br/>")}</td>
<td>${link(client.landing_page)}</td> <td>${link(client.landing_page)}</td>
<td> <td>
<button type="button" onclick="edit('${id}')">Edit</button> <button type="button" onclick="edit('${client.client_id}')">Edit</button>
<button class="danger" onclick="remove('${id}')" type="button">Remove</button> <button class="danger" onclick="remove('${client.client_id}')" type="button">Remove</button>
</td>`; </td>`;
bottom.parentNode.insertBefore(row,bottom); bottom.parentNode.insertBefore(row,bottom);
} }

21
de.srsoftware.oidc.web/src/main/resources/en/scripts/users.js

@ -39,10 +39,13 @@ function handleUsers(response){
return; return;
} }
response.json().then(users => { response.json().then(users => {
var arr = [];
for (let id in users) arr.push(users[id]);
arr.sort((a,b) => a.username < b.username ? -1 : 1);
var bottom = document.getElementById('bottom'); var bottom = document.getElementById('bottom');
for (let id in users){ for (var u of arr){
var row = document.createElement("tr"); var row = document.createElement("tr");
var u = users[id]; //var u = users[id];
var manage = { var manage = {
clients : u.permissions.includes('MANAGE_CLIENTS'), clients : u.permissions.includes('MANAGE_CLIENTS'),
perms : u.permissions.includes('MANAGE_PERMISSIONS'), perms : u.permissions.includes('MANAGE_PERMISSIONS'),
@ -52,16 +55,16 @@ function handleUsers(response){
row.innerHTML = `<td>${u.username}</td> row.innerHTML = `<td>${u.username}</td>
<td>${u.realname}</td> <td>${u.realname}</td>
<td>${u.email}</td> <td>${u.email}</td>
<td>${id}</td> <td>${u.uuid}</td>
<td style="display: none" class="permissions"> <td style="display: none" class="permissions">
<button onclick="editPermission('${id}','MANAGE_CLIENTS',${manage.clients})">${manage.clients ?'-':'+'} <span>Manage</span> Clients</button> <button onclick="editPermission('${u.uuid}','MANAGE_CLIENTS',${manage.clients})">${manage.clients ?'-':'+'} <span>Manage</span> Clients</button>
<button onclick="editPermission('${id}','MANAGE_PERMISSIONS',${manage.perms})">${manage.perms ?'-':'+'} <span>Manage</span> Permissions</button> <button onclick="editPermission('${u.uuid}','MANAGE_PERMISSIONS',${manage.perms})">${manage.perms ?'-':'+'} <span>Manage</span> Permissions</button>
<button onclick="editPermission('${id}','MANAGE_SMTP',${manage.smtp})">${manage.smtp ?'-':'+'} <span>Manage</span> SMTP</button> <button onclick="editPermission('${u.uuid}','MANAGE_SMTP',${manage.smtp})">${manage.smtp ?'-':'+'} <span>Manage</span> SMTP</button>
<button onclick="editPermission('${id}','MANAGE_USERS',${manage.users})">${manage.users ?'-':'+'} <span>Manage</span> Users</button> <button onclick="editPermission('${u.uuid}','MANAGE_USERS',${manage.users})">${manage.users ?'-':'+'} <span>Manage</span> Users</button>
</td> </td>
<td> <td>
<button type="button" onclick="reset_password('${id}')" id="reset-${id}">Reset password</button> <button type="button" onclick="reset_password('${u.uuid}')" id="reset-${u.uuid}">Reset password</button>
<button id="remove-${u.uuid}" class="danger" onclick="remove('${id}','${u.realname}')" type="button">Remove</button> <button id="remove-${u.uuid}" class="danger" onclick="remove('${u.uuid}','${u.realname}')" type="button">Remove</button>
</td>`; </td>`;
bottom.parentNode.insertBefore(row,bottom); bottom.parentNode.insertBefore(row,bottom);
if (user.permissions.includes('MANAGE_PERMISSIONS')) showAll('permissions'); if (user.permissions.includes('MANAGE_PERMISSIONS')) showAll('permissions');

Loading…
Cancel
Save