implemented EncryptedClientService
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -18,6 +18,7 @@ import de.srsoftware.logging.ColorLogger;
|
|||||||
import de.srsoftware.oidc.api.*;
|
import de.srsoftware.oidc.api.*;
|
||||||
import de.srsoftware.oidc.api.data.User;
|
import de.srsoftware.oidc.api.data.User;
|
||||||
import de.srsoftware.oidc.backend.*;
|
import de.srsoftware.oidc.backend.*;
|
||||||
|
import de.srsoftware.oidc.datastore.encrypted.EncryptedClientService;
|
||||||
import de.srsoftware.oidc.datastore.encrypted.EncryptedMailConfig;
|
import de.srsoftware.oidc.datastore.encrypted.EncryptedMailConfig;
|
||||||
import de.srsoftware.oidc.datastore.encrypted.EncryptedUserService;
|
import de.srsoftware.oidc.datastore.encrypted.EncryptedUserService;
|
||||||
import de.srsoftware.oidc.datastore.file.FileStoreProvider;
|
import de.srsoftware.oidc.datastore.file.FileStoreProvider;
|
||||||
@@ -87,11 +88,19 @@ public class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ClientService setupClientService(Configuration config, Path defaultFile, FileStoreProvider fileStoreProvider) throws SQLException {
|
private static ClientService setupClientService(Configuration config, Path defaultFile, FileStoreProvider fileStoreProvider) throws SQLException {
|
||||||
var clientStore = new File(config.getOrDefault("client_store", defaultFile));
|
var clientStore = new File(config.getOrDefault("client_store", defaultFile));
|
||||||
return switch (extension(clientStore)) {
|
var clientService = switch (extension(clientStore)) {
|
||||||
case "db", "sqlite", "sqlite3" -> new SqliteClientService(connectionProvider.get(clientStore));
|
case "db", "sqlite", "sqlite3" -> new SqliteClientService(connectionProvider.get(clientStore));
|
||||||
default -> fileStoreProvider.get(clientStore);
|
default -> fileStoreProvider.get(clientStore);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Optional<String> encryptionKey = config.get(ENCRYPTION_KEY);
|
||||||
|
|
||||||
|
if (encryptionKey.isPresent()){
|
||||||
|
var salt = config.getOrDefault(SALT,uuid());
|
||||||
|
clientService = new EncryptedClientService(encryptionKey.get(),salt,clientService);
|
||||||
|
}
|
||||||
|
return clientService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AuthorizationService setupAuthService(Configuration config, Path defaultFile, FileStoreProvider fileStoreProvider) throws SQLException {
|
private static AuthorizationService setupAuthService(Configuration config, Path defaultFile, FileStoreProvider fileStoreProvider) throws SQLException {
|
||||||
@@ -119,7 +128,6 @@ public class Application {
|
|||||||
|
|
||||||
Optional<String> encryptionKey = config.get(ENCRYPTION_KEY);
|
Optional<String> encryptionKey = config.get(ENCRYPTION_KEY);
|
||||||
|
|
||||||
|
|
||||||
if (encryptionKey.isPresent()){
|
if (encryptionKey.isPresent()){
|
||||||
var salt = config.getOrDefault(SALT,uuid());
|
var salt = config.getOrDefault(SALT,uuid());
|
||||||
mailConfig = new EncryptedMailConfig(mailConfig,encryptionKey.get(),salt);
|
mailConfig = new EncryptedMailConfig(mailConfig,encryptionKey.get(),salt);
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.oidc.datastore.encrypted;
|
||||||
|
|
||||||
|
import static java.util.Optional.empty;
|
||||||
|
|
||||||
|
import de.srsoftware.oidc.api.ClientService;
|
||||||
|
import de.srsoftware.oidc.api.data.Client;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class EncryptedClientService extends EncryptedConfig implements ClientService {
|
||||||
|
private final ClientService backend;
|
||||||
|
|
||||||
|
public EncryptedClientService(String key, String salt, ClientService backend) {
|
||||||
|
super(key, salt);
|
||||||
|
this.backend = backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Client decrypt(Client client) {
|
||||||
|
var decryptedUrls = client.redirectUris().stream().map(this::decrypt).collect(Collectors.toSet());
|
||||||
|
return new Client(decrypt(client.id()), decrypt(client.name()), decrypt(client.secret()), decryptedUrls).landingPage(decrypt(client.landingPage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Client encrypt(Client client) {
|
||||||
|
var encryptedUrls = client.redirectUris().stream().map(this::encrypt).collect(Collectors.toSet());
|
||||||
|
return new Client(encrypt(client.id()), encrypt(client.name()), encrypt(client.secret()), encryptedUrls).landingPage(encrypt(client.landingPage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Client> getClient(String clientId) {
|
||||||
|
if (clientId == null || clientId.isBlank()) return empty();
|
||||||
|
for (var encrypted : backend.listClients()) {
|
||||||
|
var decrypted = decrypt(encrypted);
|
||||||
|
if (decrypted.id().equals(clientId)) return Optional.of(decrypted);
|
||||||
|
}
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Client> listClients() {
|
||||||
|
return backend.listClients().stream().map(this::decrypt).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientService remove(String clientId) {
|
||||||
|
if (clientId == null || clientId.isBlank()) return this;
|
||||||
|
for (var encrypted : backend.listClients()) {
|
||||||
|
var decrypted = decrypt(encrypted);
|
||||||
|
if (decrypted.id().equals(clientId)) {
|
||||||
|
backend.remove(encrypted.id());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientService save(Client client) {
|
||||||
|
remove(client.id());
|
||||||
|
backend.save(encrypt(client));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
import static de.srsoftware.utils.Optionals.nullable;
|
||||||
|
import static de.srsoftware.utils.Strings.uuid;
|
||||||
|
|
||||||
|
import de.srsoftware.oidc.api.ClientService;
|
||||||
|
import de.srsoftware.oidc.api.ClientServiceTest;
|
||||||
|
import de.srsoftware.oidc.api.data.Client;
|
||||||
|
import de.srsoftware.oidc.datastore.encrypted.EncryptedClientService;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
||||||
|
public class EncryptedClientServiceTest extends ClientServiceTest {
|
||||||
|
private static class InMemoryClientService implements ClientService {
|
||||||
|
private HashMap<String, Client> clients = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Client> getClient(String clientId) {
|
||||||
|
return nullable(clients.get(clientId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Client> listClients() {
|
||||||
|
return List.copyOf(clients.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientService remove(String clientId) {
|
||||||
|
clients.remove(clientId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientService save(Client client) {
|
||||||
|
clients.put(client.id(), client);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private ClientService clientService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClientService clientService() {
|
||||||
|
return clientService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() throws SQLException {
|
||||||
|
var secret = uuid();
|
||||||
|
var salt = uuid();
|
||||||
|
var backend = new InMemoryClientService();
|
||||||
|
clientService = new EncryptedClientService(secret, salt, backend);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user