added landing page to client properties
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -29,6 +29,7 @@ public class Constants {
|
||||
public static final String INVALID_REQUEST = "invalid_request";
|
||||
public static final String INVALID_REQUEST_OBJECT = "invalid_request_object";
|
||||
public static final String INVALID_SCOPE = "invalid_scope";
|
||||
public static final String LANDING_PAGE = "landing_page";
|
||||
public static final String MAILCONFIG = "mail_config";
|
||||
public static final String NAME = "name";
|
||||
public static final String NONCE = "nonce";
|
||||
|
||||
@@ -3,16 +3,21 @@ package de.srsoftware.oidc.api.data;
|
||||
|
||||
|
||||
import static de.srsoftware.oidc.api.Constants.*;
|
||||
import static de.srsoftware.utils.Optionals.nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class Client {
|
||||
private static System.Logger LOG = System.getLogger(Client.class.getSimpleName());
|
||||
private final String id, name, secret;
|
||||
private final String id;
|
||||
private String landingPage;
|
||||
private final String name;
|
||||
private final String secret;
|
||||
private final Set<String> redirectUris;
|
||||
|
||||
public Client(String id, String name, String secret, Set<String> redirectUris) {
|
||||
this.id = id;
|
||||
landingPage = null;
|
||||
this.name = name;
|
||||
this.secret = secret;
|
||||
this.redirectUris = redirectUris;
|
||||
@@ -22,8 +27,23 @@ public final class Client {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String landingPage() {
|
||||
return landingPage;
|
||||
}
|
||||
|
||||
public Client landingPage(String newVal) {
|
||||
landingPage = newVal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<String, Object> map() {
|
||||
return Map.of(CLIENT_ID, id, NAME, name, SECRET, secret, REDIRECT_URIS, redirectUris);
|
||||
var map = new HashMap<String, Object>();
|
||||
map.put(CLIENT_ID, id);
|
||||
map.put(NAME, name);
|
||||
map.put(SECRET, secret);
|
||||
nullable(redirectUris).ifPresent(uris -> map.put(REDIRECT_URIS, uris));
|
||||
nullable(landingPage).ifPresent(lp -> map.put(LANDING_PAGE, lp));
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +77,7 @@ public final class Client {
|
||||
public String toString() {
|
||||
return "Client["
|
||||
+ "id=" + id + ", "
|
||||
+ "landing_page=" + landingPage + ", "
|
||||
+ "name=" + name + ", "
|
||||
+ "secret=" + secret + ", "
|
||||
+ "redirectUris=" + redirectUris + ']';
|
||||
|
||||
@@ -22,7 +22,8 @@ public abstract class ClientServiceTest {
|
||||
assertTrue(cs.listClients().isEmpty());
|
||||
var clientId = uuid();
|
||||
var clientSecret = uuid();
|
||||
var client = new Client(clientId, NAME, clientSecret, Set.of(URI));
|
||||
var landingPage = uuid();
|
||||
var client = new Client(clientId, NAME, clientSecret, Set.of(URI)).landingPage(landingPage);
|
||||
var list = cs.save(client).listClients();
|
||||
assertEquals(1, list.size());
|
||||
assertTrue(list.contains(client));
|
||||
@@ -35,7 +36,8 @@ public abstract class ClientServiceTest {
|
||||
var cs = clientService();
|
||||
var clientId = uuid();
|
||||
var clientSecret = uuid();
|
||||
var client = new Client(clientId, NAME, clientSecret, Set.of(URI));
|
||||
var landingPage = uuid();
|
||||
var client = new Client(clientId, NAME, clientSecret, Set.of(URI)).landingPage(landingPage);
|
||||
var optClient = cs.save(client).getClient(clientId);
|
||||
assertTrue(optClient.isPresent());
|
||||
assertEquals(client, optClient.get());
|
||||
@@ -49,8 +51,10 @@ public abstract class ClientServiceTest {
|
||||
var clientId = uuid();
|
||||
var clientSecret = uuid();
|
||||
var clientSecret2 = uuid();
|
||||
var client1 = new Client(clientId, NAME, clientSecret, Set.of(URI));
|
||||
var client2 = new Client(clientId, "test", clientSecret2, Set.of(URI2));
|
||||
var landingPage1 = uuid();
|
||||
|
||||
var client1 = new Client(clientId, NAME, clientSecret, Set.of(URI)).landingPage(landingPage1);
|
||||
var client2 = new Client(clientId, "test", clientSecret2, Set.of(URI2));
|
||||
|
||||
var optClient = cs.save(client1).getClient(clientId);
|
||||
assertTrue(optClient.isPresent());
|
||||
|
||||
@@ -161,7 +161,7 @@ public class ClientController extends Controller {
|
||||
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||
if (!optUser.get().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())));
|
||||
clients.listClients().forEach(client -> json.put(client.id(), client.map()));
|
||||
return sendContent(ex, json);
|
||||
}
|
||||
|
||||
@@ -188,7 +188,8 @@ public class ClientController extends Controller {
|
||||
for (Object o : json.getJSONArray(REDIRECT_URIS)) {
|
||||
if (o instanceof String s) redirects.add(s);
|
||||
}
|
||||
var client = new Client(json.getString(CLIENT_ID), json.getString(NAME), json.getString(SECRET), redirects);
|
||||
var landingPage = json.has(LANDING_PAGE) ? json.getString(LANDING_PAGE) : null;
|
||||
var client = new Client(json.getString(CLIENT_ID), json.getString(NAME), json.getString(SECRET), redirects).landingPage(landingPage);
|
||||
clients.save(client);
|
||||
return sendContent(ex, client);
|
||||
}
|
||||
|
||||
@@ -168,8 +168,8 @@ public class TokenController extends PathHandler {
|
||||
}
|
||||
|
||||
private JwtClaims createIdTokenClaims(User user, Client client, String atHash) {
|
||||
var optNonce = authorizations.consumeNonce(user.uuid(), client.id());
|
||||
JwtClaims claims = new JwtClaims();
|
||||
var optNonce = authorizations.consumeNonce(user.uuid(), client.id());
|
||||
JwtClaims claims = new JwtClaims();
|
||||
|
||||
// required claims:
|
||||
claims.setIssuer(config.issuer); // who creates the token and signs it
|
||||
|
||||
@@ -298,17 +298,20 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe
|
||||
@Override
|
||||
public ClientService save(Client client) {
|
||||
if (!json.has(CLIENTS)) json.put(CLIENTS, new JSONObject());
|
||||
json.getJSONObject(CLIENTS).put(client.id(), Map.of(NAME, client.name(), SECRET, client.secret(), REDIRECT_URIS, client.redirectUris()));
|
||||
json.getJSONObject(CLIENTS).put(client.id(), client.map());
|
||||
save();
|
||||
return this;
|
||||
}
|
||||
|
||||
private Client toClient(String clientId, JSONObject clientData) {
|
||||
var redirectUris = new HashSet<String>();
|
||||
for (var o : clientData.getJSONArray(REDIRECT_URIS)) {
|
||||
if (o instanceof String s) redirectUris.add(s);
|
||||
}
|
||||
return new Client(clientId, clientData.getString(NAME), clientData.getString(SECRET), redirectUris);
|
||||
if (clientData.has(REDIRECT_URIS))
|
||||
for (var o : clientData.getJSONArray(REDIRECT_URIS)) {
|
||||
if (o instanceof String s) redirectUris.add(s);
|
||||
}
|
||||
var client = new Client(clientId, clientData.getString(NAME), clientData.getString(SECRET), redirectUris);
|
||||
if (clientData.has(LANDING_PAGE)) client.landingPage(clientData.getString(LANDING_PAGE));
|
||||
return client;
|
||||
}
|
||||
|
||||
/*** AuthorizationService methods ***/
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/* © SRSoftware 2024 */
|
||||
package de.srsoftware.oidc.datastore.sqlite;
|
||||
|
||||
import static de.srsoftware.oidc.api.Constants.NAME;
|
||||
import static de.srsoftware.oidc.api.Constants.SECRET;
|
||||
import static de.srsoftware.oidc.api.Constants.*;
|
||||
|
||||
import de.srsoftware.oidc.api.ClientService;
|
||||
import de.srsoftware.oidc.api.data.Client;
|
||||
@@ -17,9 +16,9 @@ public class SqliteClientService extends SqliteStore implements ClientService {
|
||||
private static final String SELECT_STORE_VERSION = "SELECT * FROM metainfo WHERE key = '" + STORE_VERSION + "'";
|
||||
private static final String SET_STORE_VERSION = "UPDATE metainfo SET value = ? WHERE key = '" + STORE_VERSION + "'";
|
||||
|
||||
private static final String CREATE_CLIENT_TABLE = "CREATE TABLE IF NOT EXISTS clients(id VARCHAR(255) NOT NULL PRIMARY KEY, name VARCHAR(255), secret VARCHAR(255));";
|
||||
private static final String CREATE_CLIENT_TABLE = "CREATE TABLE IF NOT EXISTS clients(id VARCHAR(255) NOT NULL PRIMARY KEY, name VARCHAR(255), secret VARCHAR(255), landing_page VARCHAR(255));";
|
||||
private static final String CREATE_REDIRECT_TABLE = "CREATE TABLE IF NOT EXISTS client_redirects(clientId VARCHAR(255), uri VARCHAR(255), PRIMARY KEY(clientId, uri));";
|
||||
private static final String SAVE_CLIENT = "INSERT INTO clients (id, name, secret) VALUES (?,?,?) ON CONFLICT DO UPDATE SET name = ?, secret = ?;";
|
||||
private static final String SAVE_CLIENT = "INSERT INTO clients (id, name, secret, landing_page) VALUES (?,?,?,?) ON CONFLICT DO UPDATE SET name = ?, secret = ?, landing_page = ?;";
|
||||
private static final String SAVE_REDIRECT = "INSERT OR IGNORE INTO client_redirects(clientId, uri) VALUES (?, ?)";
|
||||
private static final String DROP_OTHER_REDIRECTS = "DELETE FROM client_redirects WHERE clientId = ? AND uri NOT IN";
|
||||
private static final String SELECT_CLIENT = "SELECT * FROM clients WHERE id = ?";
|
||||
@@ -87,9 +86,10 @@ public class SqliteClientService extends SqliteStore implements ClientService {
|
||||
stmt.setString(1, clientId);
|
||||
rs = stmt.executeQuery();
|
||||
if (rs.next()) {
|
||||
var name = rs.getString(NAME);
|
||||
var secret = rs.getString(SECRET);
|
||||
result = Optional.of(new Client(clientId, name, secret, uris));
|
||||
var name = rs.getString(NAME);
|
||||
var secret = rs.getString(SECRET);
|
||||
var landing = rs.getString(LANDING_PAGE);
|
||||
result = Optional.of(new Client(clientId, name, secret, uris).landingPage(landing));
|
||||
}
|
||||
rs.close();
|
||||
return result;
|
||||
@@ -115,10 +115,11 @@ public class SqliteClientService extends SqliteStore implements ClientService {
|
||||
rs = stmt.executeQuery();
|
||||
var result = new ArrayList<Client>();
|
||||
while (rs.next()) {
|
||||
var id = rs.getString("id");
|
||||
var name = rs.getString(NAME);
|
||||
var secret = rs.getString(SECRET);
|
||||
result.add(new Client(id, name, secret, redirects.get(id)));
|
||||
var id = rs.getString("id");
|
||||
var name = rs.getString(NAME);
|
||||
var secret = rs.getString(SECRET);
|
||||
var landing = rs.getString(LANDING_PAGE);
|
||||
result.add(new Client(id, name, secret, redirects.get(id)).landingPage(landing));
|
||||
}
|
||||
rs.close();
|
||||
return result;
|
||||
@@ -149,8 +150,10 @@ public class SqliteClientService extends SqliteStore implements ClientService {
|
||||
stmt.setString(1, client.id());
|
||||
stmt.setString(2, client.name());
|
||||
stmt.setString(3, client.secret());
|
||||
stmt.setString(4, client.name());
|
||||
stmt.setString(5, client.secret());
|
||||
stmt.setString(4, client.landingPage());
|
||||
stmt.setString(5, client.name());
|
||||
stmt.setString(6, client.secret());
|
||||
stmt.setString(7, client.landingPage());
|
||||
stmt.execute();
|
||||
stmt = conn.prepareStatement(SAVE_REDIRECT);
|
||||
stmt.setString(1, client.id());
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
<th>Client</th>
|
||||
<th>ID</th>
|
||||
<th>Redirect URLs</th>
|
||||
<th>Landing page</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
<tr id="bottom">
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
<fieldset class="wide">
|
||||
<legend>Data</legend>
|
||||
<table>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<td><input type="text" disabled="true" id="client-id" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<td><input type="text" id="client-name" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<td><input type="text" disabled="true" id="client-id" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Secret</th>
|
||||
<td><input type="text" id="client-secret" /></td>
|
||||
@@ -33,6 +33,10 @@
|
||||
<textarea id="redirect-urls"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Landing page</th>
|
||||
<td><input type="text" id="landing-page" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><button type="button" id="button" onclick="updateClient();">Update</button></td>
|
||||
|
||||
@@ -17,21 +17,25 @@
|
||||
<legend>Settings</legend>
|
||||
<table>
|
||||
<tr>
|
||||
<th>client id</th>
|
||||
<td><input type="text" size="50" id="client-id"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>client name</th>
|
||||
<th>Client Name</th>
|
||||
<td><input type="text" size="50" id="client-name"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>client secret</th>
|
||||
<th>Client ID</th>
|
||||
<td><input type="text" size="50" id="client-id"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Client Secret</th>
|
||||
<td><input type="text" size="50" id="client-secret"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>redirect urls</th>
|
||||
<th>Redirect URLs</th>
|
||||
<td><textarea cols="50" rows="5" id="redirect-urls"></textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Landing page</th>
|
||||
<td><input type="text" size="50" id="landing-page" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><button id="button" type="button" onclick="addClient()">Add client</button></td>
|
||||
|
||||
@@ -15,6 +15,7 @@ function handleClients(response){
|
||||
row.innerHTML = `<td>${client.name}</td>
|
||||
<td>${id}</td>
|
||||
<td>${client.redirect_uris.join("<br/>")}</td>
|
||||
<td>${link(client.landing_page)}</td>
|
||||
<td>
|
||||
<button type="button" onclick="edit('${id}')">Edit</button>
|
||||
<button class="danger" onclick="remove('${id}')" type="button">Remove</button>
|
||||
@@ -24,6 +25,10 @@ function handleClients(response){
|
||||
});
|
||||
}
|
||||
|
||||
function link(url){
|
||||
return url ? '<a href="'+url+'">'+url.split('?')[0]+'</a>': "";
|
||||
}
|
||||
|
||||
function handleRemove(response){
|
||||
redirect("clients.html");
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ function handleLoadResponse(response){
|
||||
get('client-name').value = json.name;
|
||||
get('client-secret').value = json.secret;
|
||||
get('redirect-urls').value = json.redirect_uris.join("\n");
|
||||
get('landing-page').value = json.landing_page?json.landing_page:'';
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -17,6 +18,7 @@ function handleUpdateResponse(response){
|
||||
if (response.ok) {
|
||||
enable('button');
|
||||
setText('button','saved.');
|
||||
redirect('clients.html');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +34,8 @@ function updateClient(){
|
||||
client_id : getValue('client-id'),
|
||||
name : getValue('client-name'),
|
||||
secret : getValue('client-secret'),
|
||||
redirect_uris : getValue('redirect-urls').split("\n")
|
||||
redirect_uris : getValue('redirect-urls').split("\n"),
|
||||
landing_page : getValue('landing-page')
|
||||
};
|
||||
fetch(client_controller+'/update',{
|
||||
method : 'POST',
|
||||
|
||||
@@ -4,7 +4,8 @@ function addClient(){
|
||||
client_id : getValue('client-id'),
|
||||
name : getValue('client-name'),
|
||||
secret : getValue('client-secret'),
|
||||
redirect_uris : getValue('redirect-urls').split("\n")
|
||||
redirect_uris : getValue('redirect-urls').split("\n"),
|
||||
landing_page : getValue('landing-page')
|
||||
};
|
||||
fetch(client_controller+'/add',{
|
||||
method : 'POST',
|
||||
|
||||
Reference in New Issue
Block a user