Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public Optional<String> getClientSecret() {

@Override
public Map<String, Key> getSigningKeys() {
return null;
return java.util.Collections.emptyMap();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public AuthFilter<String, User> getAuthFilter() {
JwtTokenAuthenticator tokenAuthenticator = new JwtTokenAuthenticator(tokenHandler);

CachingAuthenticator<String, User> cachingAuthenticator =
new CachingAuthenticator<String, User>(
new CachingAuthenticator<>(
metricRegistry,
tokenAuthenticator,
CaffeineSpec.parse("maximumSize=10000, expireAfterAccess=10m"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import de.ii.xtraplatform.auth.domain.Role;
import de.ii.xtraplatform.auth.domain.User;
import de.ii.xtraplatform.auth.domain.UserAuthenticator;
import de.ii.xtraplatform.base.domain.AppContext;
import de.ii.xtraplatform.entities.domain.EntityData;
import de.ii.xtraplatform.entities.domain.EntityDataStore;
import java.time.Instant;
Expand Down Expand Up @@ -41,82 +40,74 @@ public class InternalUserAuthenticator implements UserAuthenticator {
private final EntityDataStore<de.ii.xtraplatform.auth.app.User.UserData> userRepository;

@Inject
public InternalUserAuthenticator(AppContext appContext, EntityDataStore<?> entityRepository) {
public InternalUserAuthenticator(EntityDataStore<?> entityRepository) {
this.isAccessRestricted = true;
/*Optional.ofNullable(appContext.getConfiguration().getAuth())
.map(authConfig -> !authConfig.allowAnonymousAccess)
.orElse(true);*/
this.userRepository =
((EntityDataStore<EntityData>) entityRepository)
.forType(de.ii.xtraplatform.auth.app.User.UserData.class);
}

@Override
public Optional<User> authenticate(String username, String password) {

if (userRepository.has(username)) {

de.ii.xtraplatform.auth.app.User.UserData userData = userRepository.get(username);

if (PasswordHash.validatePassword(password, userData.getPassword())) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(
"Authenticated {} {} {}",
userData.getId(),
userData.getRole(),
PasswordHash.createHash(password));
}

long now = Instant.now().toEpochMilli();

return Optional.of(
ImmutableUser.builder()
.name(userData.getId())
.role(userData.getRole())
.forceChangePassword(userData.getPasswordExpiresAt().orElse(now) < now)
.build());
}
return authenticateExistingUser(username, password);
}

// TODO: for ldproxy make admin password settable via env variable, get from bundlecontext
// then save the user with that password below (or just validate and return for read-only store
// )

// no user exists yet
if (userRepository.ids().isEmpty()) {

if (!isAccessRestricted) {
return Optional.of(
ImmutableUser.builder().name(SUPER_ADMIN.getId()).role(SUPER_ADMIN.getRole()).build());
}

if (Objects.equals(username, SUPER_ADMIN.getId())
&& PasswordHash.validatePassword(password, SUPER_ADMIN.getPassword())) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(
"Authenticated {} {} {}",
SUPER_ADMIN.getId(),
SUPER_ADMIN.getRole(),
PasswordHash.createHash(password));
}
if (userRepository.ids().isEmpty()) {
return authenticateFirstUser(username, password);
}

try {
de.ii.xtraplatform.auth.app.User.UserData firstUser =
userRepository.put(SUPER_ADMIN.getId(), SUPER_ADMIN).get();
return Optional.empty();
}

return Optional.of(
ImmutableUser.builder()
.name(firstUser.getId())
.role(firstUser.getRole())
.forceChangePassword(true)
.build());
private Optional<User> authenticateExistingUser(String username, String password) {
de.ii.xtraplatform.auth.app.User.UserData userData = userRepository.get(username);
if (!PasswordHash.validatePassword(password, userData.getPassword())) {
return Optional.empty();
}
logAuthenticated(SUPER_ADMIN.getId(), SUPER_ADMIN.getRole().toString(), password);
long now = Instant.now().toEpochMilli();
return Optional.of(
ImmutableUser.builder()
.name(userData.getId())
.role(userData.getRole())
.forceChangePassword(userData.getPasswordExpiresAt().orElse(now) < now)
.build());
}

} catch (InterruptedException | ExecutionException e) {
// ignore
}
private Optional<User> authenticateFirstUser(String username, String password) {
if (!isAccessRestricted) {
return Optional.of(
ImmutableUser.builder().name(SUPER_ADMIN.getId()).role(SUPER_ADMIN.getRole()).build());
}
if (Objects.equals(username, SUPER_ADMIN.getId())
&& PasswordHash.validatePassword(password, SUPER_ADMIN.getPassword())) {
logAuthenticated(SUPER_ADMIN.getId(), SUPER_ADMIN.getRole().toString(), password);
try {
de.ii.xtraplatform.auth.app.User.UserData firstUser =
userRepository.put(SUPER_ADMIN.getId(), SUPER_ADMIN).get();
return Optional.of(
ImmutableUser.builder()
.name(firstUser.getId())
.role(firstUser.getRole())
.forceChangePassword(true)
.build());
} catch (InterruptedException | ExecutionException e) {
// ignore
}
}

return Optional.empty();
}

private void logAuthenticated(String id, String role, String password) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Authenticated {} {} {}", id, role, PasswordHash.createHash(password));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@

@Singleton
@AutoBind
@SuppressWarnings({"PMD.GodClass", "PMD.TooManyMethods"})
public class JwtTokenHandler implements TokenHandler, AppLifeCycle {

private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenHandler.class);
Expand Down Expand Up @@ -162,7 +163,7 @@ private static boolean isComplex(String claim) {
}

private static String baseKey(String claim) {
return isComplex(claim) ? claim.substring(0, claim.indexOf(".")) : claim;
return isComplex(claim) ? claim.substring(0, claim.indexOf('.')) : claim;
}

private static Map<String, Class<?>> listType(String claim) {
Expand All @@ -173,6 +174,7 @@ private String read(Claims claims, String claim) {
return claims.get(claim, String.class);
}

@SuppressWarnings("PMD.CognitiveComplexity")
private List<String> readList(Claims claims, String claim) {
boolean isComplex = isComplex(claim);
String baseKey = baseKey(claim);
Expand Down Expand Up @@ -230,6 +232,7 @@ private Map<String, Set<String>> readListPerApi(Claims claims, String claim) {
return lists;
}

@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
private List<String> getClaimNames(Map<?, ?> claims) {
List<String> keys = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
* Author: havoc AT defuse.ca
* www: http://crackstation.net/hashing-security.htm
*/
public class PasswordHash {
public final class PasswordHash {

public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";

// The following constants may be changed without breaking existing hashes.
Expand All @@ -59,6 +60,8 @@ public class PasswordHash {
public static final int SALT_INDEX = 1;
public static final int PBKDF2_INDEX = 2;

private PasswordHash() {}

/**
* Returns a salted PBKDF2 hash of the password.
*
Expand All @@ -79,6 +82,7 @@ public static String createHash(String password) {
* @param password the password to hash
* @return a salted PBKDF2 hash of the password
*/
@SuppressWarnings("PMD.UseVarargs")
public static String createHash(char[] password)
throws NoSuchAlgorithmException, InvalidKeySpecException {
// Generate a random salt
Expand Down Expand Up @@ -140,7 +144,9 @@ public static boolean validatePassword(char[] password, String correctHash)
*/
private static boolean slowEquals(byte[] a, byte[] b) {
int diff = a.length ^ b.length;
for (int i = 0; i < a.length && i < b.length; i++) diff |= a[i] ^ b[i];
for (int i = 0; i < a.length && i < b.length; i++) {
diff |= a[i] ^ b[i];
}
return diff == 0;
}

Expand Down Expand Up @@ -183,9 +189,12 @@ private static byte[] fromHex(String hex) {
private static String toHex(byte[] array) {
BigInteger bi = new BigInteger(1, array);
String hex = bi.toString(16);
int paddingLength = (array.length * 2) - hex.length();
if (paddingLength > 0) return String.format("%0" + paddingLength + "d", 0) + hex;
else return hex;
int paddingLength = array.length * 2 - hex.length();
if (paddingLength > 0) {
return String.format("%0" + paddingLength + "d", 0) + hex;
} else {
return hex;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("PMD.MissingStaticMethodInNonInstantiatableClass")
@Priority(Priorities.AUTHENTICATION)
public class SplitCookieCredentialAuthFilter<P extends Principal> extends AuthFilter<String, P> {
public final class SplitCookieCredentialAuthFilter<P extends Principal>
extends AuthFilter<String, P> {

private static final Logger LOGGER =
LoggerFactory.getLogger(SplitCookieCredentialAuthFilter.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,11 @@ public SplitCookieResponseFilter(
EntityDataStore<?> entityRepository) {
this.servicesUri = servicesContext.getUri();
this.tokenHandler = tokenHandler;
this.userRepository =
((EntityDataStore<EntityData>) entityRepository)
.forType(de.ii.xtraplatform.auth.app.User.UserData.class);
this.userRepository = ((EntityDataStore<EntityData>) entityRepository).forType(UserData.class);
}

@Override
@SuppressWarnings("PMD.AvoidDeeplyNestedIfStmts")
public void filter(
ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ abstract class Builder implements EntityDataBuilder<UserData> {

public abstract Builder role(Role role);

@Override
public ImmutableUserData.Builder fillRequiredFieldsWithPlaceholders() {
return ((ImmutableUserData.Builder)
this.id("__DEFAULT__").password("__DEFAULT__").role(Role.NONE));
return (ImmutableUserData.Builder)
this.id("__DEFAULT__").password("__DEFAULT__").role(Role.NONE);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public AuthFilter<String, User> getAuthFilter() {
TokenAuthenticator tokenAuthenticator = new TokenAuthenticator(authConfig, httpClient);

CachingAuthenticator<String, User> cachingAuthenticator =
new CachingAuthenticator<String, User>(
new CachingAuthenticator<>(
metricRegistry,
tokenAuthenticator,
CaffeineSpec.parse("maximumSize=10000, expireAfterAccess=10m"));
Expand Down
Loading