Skip to content
Permalink
Browse files Browse the repository at this point in the history
Prevent authentication with inactive identifiers
  • Loading branch information
kmehrunes committed Oct 6, 2021
1 parent 87611fb commit 9783b11
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 5 deletions.
Expand Up @@ -7,10 +7,7 @@
import com.nexblocks.authguard.service.exceptions.ServiceAuthorizationException;
import com.nexblocks.authguard.service.exceptions.ServiceException;
import com.nexblocks.authguard.service.exceptions.codes.ErrorCode;
import com.nexblocks.authguard.service.model.AccountBO;
import com.nexblocks.authguard.service.model.AuthRequestBO;
import com.nexblocks.authguard.service.model.CredentialsBO;
import com.nexblocks.authguard.service.model.EntityType;
import com.nexblocks.authguard.service.model.*;
import com.google.inject.Inject;
import io.vavr.control.Either;
import org.slf4j.Logger;
Expand Down Expand Up @@ -86,7 +83,14 @@ private Either<Exception, AccountBO> handleBasicAuthenticationNoPassword(final S
private Either<Exception, AccountBO> verifyCredentialsAndGetAccount(final String username, final String password) {
final Optional<CredentialsBO> credentials = credentialsService.getByUsernameUnsafe(username);

// TODO replace this with Either mapping
if (credentials.isPresent()) {
final Optional<Exception> validationError = checkIdentifier(credentials.get(), username);

if (validationError.isPresent()) {
return Either.left(validationError.get());
}

if (securePassword.verify(password, credentials.get().getHashedPassword())) {
return getAccountById(credentials.get().getAccountId());
} else {
Expand All @@ -103,13 +107,38 @@ private Either<Exception, AccountBO> verifyCredentialsAndGetAccount(final String
final Optional<CredentialsBO> credentials = credentialsService.getByUsernameUnsafe(username);

if (credentials.isPresent()) {
final Optional<Exception> validationError = checkIdentifier(credentials.get(), username);

if (validationError.isPresent()) {
return Either.left(validationError.get());
}

return getAccountById(credentials.get().getAccountId());
} else {
return Either.left(new ServiceAuthorizationException(ErrorCode.CREDENTIALS_DOES_NOT_EXIST,
"Identifier " + username + " does not exist"));
}
}

private Optional<Exception> checkIdentifier(final CredentialsBO credentials,
final String identifier) {
final Optional<UserIdentifierBO> matchedIdentifier = credentials.getIdentifiers()
.stream()
.filter(existing -> identifier.equals(existing.getIdentifier()))
.findFirst();

if (matchedIdentifier.isEmpty()) {
return Optional.of(new IllegalStateException("No identifier matched but credentials were returned"));
}

if (!matchedIdentifier.get().isActive()) {
return Optional.of(new ServiceAuthorizationException(ErrorCode.INACTIVE_IDENTIFIER,
"Identifier is not active", EntityType.ACCOUNT, credentials.getAccountId()));
}

return Optional.empty();
}

private Either<Exception, AccountBO> getAccountById(final String accountId) {
final Optional<AccountBO> account = accountsService.getById(accountId);

Expand Down
Expand Up @@ -64,6 +64,7 @@ void authenticate() {
.withIdentifiers(UserIdentifierBO.builder()
.identifier(username)
.type(UserIdentifier.Type.USERNAME)
.active(true)
.build());
final HashedPasswordBO hashedPasswordBO = HashedPasswordBO.builder()
.password(credentials.getHashedPassword().getPassword())
Expand All @@ -79,6 +80,27 @@ void authenticate() {
assertThat(result.get()).isEqualTo(account);
}

@Test
void authenticateInactiveIdentifier() {
final String username = "username";
final String password = "password";
final String authorization = Base64.getEncoder().encodeToString((username + ":" + password).getBytes());

final CredentialsBO credentials = RANDOM.nextObject(CredentialsBO.class)
.withIdentifiers(UserIdentifierBO.builder()
.identifier(username)
.type(UserIdentifier.Type.USERNAME)
.active(false)
.build());

Mockito.when(credentialsService.getByUsernameUnsafe(username)).thenReturn(Optional.of(credentials));

final Either<Exception, AccountBO> result = basicAuth.authenticateAndGetAccount(authorization);

assertThat(result.isLeft()).isTrue();
assertThat(result.getLeft()).isInstanceOf(ServiceAuthorizationException.class);
}

@Test
void authenticateNotFound() {
final String username = "username";
Expand Down
Expand Up @@ -33,6 +33,7 @@ public enum ErrorCode {
TOKEN_EXPIRED_OR_DOES_NOT_EXIST("AT.025"),
TOKEN_GENERATION_FAILED("AT.031"),
ACCOUNT_IS_LOCKED("AT.032"),
INACTIVE_IDENTIFIER("AT.033"),
GENERIC_AUTH_FAILURE("AT.039"),

UNSUPPORTED_JWT_ALGORITHM("JT.021"),
Expand Down
Expand Up @@ -8,7 +8,11 @@ public interface UserIdentifier {
Long getId(); // only useful for relational DBs
Type getType();
String getIdentifier();
boolean isActive();

@Value.Default
default boolean isActive() {
return true;
}

enum Type {
USERNAME,
Expand Down

0 comments on commit 9783b11

Please sign in to comment.