working on backend:
- started FileStore implementation - implemented placing cookies Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
21
de.srsoftware.oidc.datastore.file/build.gradle
Normal file
21
de.srsoftware.oidc.datastore.file/build.gradle
Normal file
@@ -0,0 +1,21 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
group = 'de.srsoftware'
|
||||
version = '1.0-SNAPSHOT'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation platform('org.junit:junit-bom:5.10.0')
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||
implementation project(':de.srsoftware.oidc.api')
|
||||
implementation 'org.json:json:20240303'
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/* © SRSoftware 2024 */
|
||||
package de.srsoftware.oidc.datastore.file; /* © SRSoftware 2024 */
|
||||
import static de.srsoftware.oidc.api.User.*;
|
||||
|
||||
import de.srsoftware.oidc.api.PasswordHasher;
|
||||
import de.srsoftware.oidc.api.User;
|
||||
import de.srsoftware.oidc.api.UserService;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class FileStore implements UserService {
|
||||
private static final String USERS = "users";
|
||||
|
||||
private final Path storageFile;
|
||||
private final JSONObject json;
|
||||
private final PasswordHasher<String> passwordHasher;
|
||||
|
||||
public FileStore(File storage, PasswordHasher<String> passwordHasher) throws IOException {
|
||||
this.storageFile = storage.toPath();
|
||||
this.passwordHasher = passwordHasher;
|
||||
|
||||
if (!storage.exists()) {
|
||||
var parent = storage.getParentFile();
|
||||
if (!parent.exists() && !parent.mkdirs()) throw new FileNotFoundException("Failed to create directory %s".formatted(parent));
|
||||
Files.writeString(storageFile, "{}");
|
||||
}
|
||||
json = new JSONObject(Files.readString(storageFile));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> load(String username, String password) {
|
||||
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);
|
||||
if (passwordHasher.matches(password, hashedPass)) {
|
||||
return Optional.of(new User(username, hashedPass, user.getString(REALNAME), user.getString(EMAIL), uuid));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
} catch (Exception e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserService delete(User user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserService init(User defaultUser) {
|
||||
if (!json.has(USERS)) save(defaultUser);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserService save(User user) {
|
||||
JSONObject users;
|
||||
if (!json.has(USERS)) {
|
||||
json.put(USERS, users = new JSONObject());
|
||||
} else
|
||||
users = json.getJSONObject(USERS);
|
||||
users.put(user.uuid(), user.map(true));
|
||||
try {
|
||||
Files.writeString(storageFile, json.toString(2));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<User> list() {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/* © SRSoftware 2024 */
|
||||
package de.srsoftware.oidc.datastore.file;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import de.srsoftware.oidc.api.PasswordHasher;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
|
||||
public class UuidHasher implements PasswordHasher<String> {
|
||||
private static final String SHA256 = "SHA-256";
|
||||
|
||||
private final MessageDigest digest;
|
||||
|
||||
public UuidHasher() throws NoSuchAlgorithmException {
|
||||
digest = MessageDigest.getInstance(SHA256);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String hash(String password, String uuid) {
|
||||
var salt = uuid;
|
||||
var saltedPass = "%s %s".formatted(salt, password);
|
||||
var bytes = digest.digest(saltedPass.getBytes(UTF_8));
|
||||
|
||||
return "%s@%s".formatted(hex(bytes), salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String salt(String hashedPassword) {
|
||||
return hashedPassword.split("@")[1];
|
||||
}
|
||||
|
||||
public static String hex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||||
for (byte b : bytes) sb.append(String.format("%02x", b));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user