Package ch.rswk.meta.engine
Class UserService
java.lang.Object
com.google.common.util.concurrent.AbstractIdleService
ch.rswk.meta.engine.AbstractEngineIdleService<UserService.UserServiceConfig>
ch.rswk.meta.engine.UserService
- All Implemented Interfaces:
EngineServices.ConfigurableService<UserService.UserServiceConfig>
,EngineServices.InfoProvidingService
,com.google.common.util.concurrent.Service
,com.yubico.webauthn.CredentialRepository
@Singleton
public class UserService
extends AbstractEngineIdleService<UserService.UserServiceConfig>
implements com.yubico.webauthn.CredentialRepository
UserService provides CRUD functionality for all user entities. Uses a
LuceneService
to store the user entities.
Provides authentication, authorization, verification and other access control functionality.
Passwords are stored using SCrypt (implemented by
wg/scrypt). Passwords are optional, since it's possible to use
OTP or WebAuthn. OTPs are 6 digit
strings like 123 456
and can use SMS, e-mail, webhook or
TOTP. OTPs can also be used as a second factor.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate class
static final record
private class
static final record
private static final record
private static enum
private static final record
private static final record
private static final record
static final record
static final record
private class
private static final record
static final record
static final record
static final record
static final record
static final record
static final record
static final record
static final record
static final record
private static final record
static final record
static final record
static enum
Nested classes/interfaces inherited from interface com.google.common.util.concurrent.Service
com.google.common.util.concurrent.Service.Listener, com.google.common.util.concurrent.Service.State
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
private static final int
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private SecretKey
private com.codahale.metrics.Meter
private final BackupService
private static final Duration
private static final com.google.common.base.CharMatcher
private com.codahale.metrics.Meter
private final Map
<String, ClientListEntry> private static final Protocol.ErrorReplyFactory
private static final com.fasterxml.jackson.databind.ObjectReader
private com.github.benmanes.caffeine.cache.AsyncLoadingCache
<String, Optional<MetaUserConfig>> private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private static final Protocol.ErrorReplyFactory
private com.codahale.metrics.Meter
private final com.google.common.collect.Multiset
<String> private com.codahale.metrics.Meter
private final GatewayService
private static final Protocol.ErrorReplyFactory
private static final com.fasterxml.jackson.databind.ObjectReader
private com.github.benmanes.caffeine.cache.AsyncLoadingCache
<String, Optional<MetaUserGroup>> private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
private static final org.slf4j.Logger
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private final LuceneService
private static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
private static final int
private static final Protocol.ErrorReplyFactory
private static final String
private static final Protocol.ErrorReplyFactory
private com.github.benmanes.caffeine.cache.Cache
<String, UserService.OtpChallenge> private com.codahale.metrics.Meter
private com.codahale.metrics.Timer
private Pattern
private static final SecureRandom
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private static final Protocol.ErrorReplyFactory
private static final String
private com.github.benmanes.caffeine.cache.Cache
<String, OffsetDateTime> private SecretKey
private com.codahale.metrics.Meter
private static final int
private static final String
static final long
private com.codahale.metrics.Meter
private static final Protocol.ErrorReplyFactory
private static final Protocol.ErrorReplyFactory
static final String
private static final String
static final String
private static final String
private static final String
private static final com.fasterxml.jackson.databind.ObjectReader
private com.github.benmanes.caffeine.cache.AsyncLoadingCache
<String, Optional<UserService.UserCacheEntry>> private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private com.github.benmanes.caffeine.cache.Cache
<String, UserService.PendingUserValidation> private com.codahale.metrics.Meter
private com.github.benmanes.caffeine.cache.Cache
<String, com.google.common.util.concurrent.SettableFuture<Void>> private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private com.codahale.metrics.Meter
private static final Protocol.ErrorReplyFactory
private static final com.fasterxml.jackson.core.type.TypeReference
<com.yubico.webauthn.data.PublicKeyCredential<com.yubico.webauthn.data.AuthenticatorAssertionResponse, com.yubico.webauthn.data.ClientAssertionExtensionOutputs>> private static final String
private static final com.google.common.base.CharMatcher
private static final com.fasterxml.jackson.databind.ObjectMapper
private static final Protocol.ErrorReplyFactory
private static final com.fasterxml.jackson.core.type.TypeReference
<com.yubico.webauthn.data.PublicKeyCredential<com.yubico.webauthn.data.AuthenticatorAttestationResponse, com.yubico.webauthn.data.ClientRegistrationExtensionOutputs>> private static final String
private com.github.benmanes.caffeine.cache.Cache
<String, com.yubico.webauthn.AssertionRequest> private com.github.benmanes.caffeine.cache.Cache
<String, com.yubico.webauthn.data.PublicKeyCredentialCreationOptions> private com.yubico.webauthn.RelyingParty
private static final Protocol.ErrorReplyFactory
private final com.google.common.util.concurrent.Monitor
private com.codahale.metrics.Meter
private static final Protocol.ErrorReplyFactory
private com.codahale.metrics.Meter
Fields inherited from class ch.rswk.meta.engine.AbstractEngineIdleService
runtime
-
Constructor Summary
ConstructorsConstructorDescriptionUserService
(BackupService backupService, UserService.UserServiceConfig config, GatewayService gatewayService, LuceneService luceneService, EngineRuntime runtime) -
Method Summary
Modifier and TypeMethodDescriptioncom.google.common.util.concurrent.ListenableFuture
<AuthReply> auth
(String clientId, String ipAddress, AuthRequest request, String user) com.google.common.util.concurrent.ListenableFuture
<AuthTokenReply> authToken
(String clientId, String ipAddress, AuthTokenRequest request, String user) private Optional
<ErrorReplyException> checkAttempts
(int attempts, String identifier) checkAttempts
(String... identifiers) com.google.common.util.concurrent.ListenableFuture
<UserConfigSearchReply> configSearch
(UserConfigSearchRequest request) static com.google.common.util.concurrent.ListenableFuture
<Void> configSearchRecursive
(Executor executor, Function<UserConfigSearchReply, com.google.common.util.concurrent.ListenableFuture<?>> replyConsumer, UserConfigSearchRequest request, Function<UserConfigSearchRequest, com.google.common.util.concurrent.ListenableFuture<UserConfigSearchReply>> service) com.google.common.util.concurrent.ListenableFuture
<UserConfigWriteReply> configWrite
(UserConfigWriteRequest request) private void
private com.google.common.util.concurrent.ListenableFuture
<Void> deleteConfigs
(String query) private void
private LuceneService.SearchResult
executeLuceneGroupSearch
(LuceneService.LuceneContext context, UserGroupSearchRequest request) private LuceneService.SearchResult
executeLuceneUserSearch
(LuceneService.LuceneContext context, UserSearchRequest request) findUserForHandle
(com.yubico.webauthn.data.ByteArray userHandle) private Optional
<ErrorReply> finishWebAuthnAssertion
(AuthRequest.AuthRequestWebAuthnAssertionReply assertionReply, String clientId, @Nullable String ipAddress, String user) private Optional
<MetaUser.MetaUserWebAuthn> finishWebAuthnRegistration
(UserWriteRequest.UserWriteRequestWebAuthnReply createReply, String user) private String
forgeEmailAndPhoneQuery
(@Nullable String email, String emailField, @Nullable String phone, String phoneField) static String
generateScryptHash
(int cpu, int memory, String secret) static UserService.GeneratedOtp
generateScryptOtp
(int scryptCpu, int scryptMemory) generateToken
(UserService.TokenRequest request) static String
generateTotp
(long offset, String totpKey) generateTotp generates a totp from the given key based on the current time plus offset.static String
com.google.common.util.concurrent.ListenableFuture
<UserService.UserTokenReply> generateUserToken
(@Nullable String clientId, String ipAddress, UserService.UserTokenRequest request) generateUserToken authenticates the given user/password and generates a token containing all grants for user and its groups.com.google.common.util.concurrent.ListenableFuture
<Optional<MetaUserConfig>> getCachedConfig
(String configId) com.google.common.util.concurrent.ListenableFuture
<Optional<MetaUserGroup>> getCachedGroup
(String group) com.google.common.util.concurrent.ListenableFuture
<Optional<UserService.UserCacheEntry>> getCachedUser
(String user) com.google.common.util.concurrent.ListenableFuture
<ClientListReply> getClientList
(ClientListRequest request) Set
<com.yubico.webauthn.data.PublicKeyCredentialDescriptor> getCredentialIdsForUsername
(String username) Optional
<com.yubico.webauthn.data.ByteArray> getUserHandleForUsername
(String username) getUsernameForUserHandle
(com.yubico.webauthn.data.ByteArray userHandle) private static MetaUser
getUserWithAddedAndRemovedGrants
(UserWriteUpdateRequest request, UserSearchReply searchReply) com.google.common.util.concurrent.ListenableFuture
<UserGroupSearchReply> groupSearch
(UserGroupSearchRequest request) static com.google.common.util.concurrent.ListenableFuture
<Void> groupSearchRecursive
(Executor executor, Function<UserGroupSearchReply, com.google.common.util.concurrent.ListenableFuture<?>> replyConsumer, UserGroupSearchRequest request, Function<UserGroupSearchRequest, com.google.common.util.concurrent.ListenableFuture<UserGroupSearchReply>> service) com.google.common.util.concurrent.ListenableFuture
<UserGroupWriteReply> groupWrite
(UserGroupWriteRequest request) com.google.common.util.concurrent.ListenableFuture
<UserGroupWriteUpdateReply> private static boolean
hasRequiredGrants
(io.jsonwebtoken.Claims claims, @Nullable Map<String, Integer> requiredGrants) com.google.common.util.concurrent.ListenableFuture
<Boolean> hasUserPermission
(int permission, String userName, String... keys) hasUserPermission checks if user has required permission for at least onf of keys.com.google.common.util.concurrent.ListenableFuture
<Boolean> private com.google.common.util.concurrent.ListenableFuture
<UserService.UserConfigResult> loadUserConfigs
(Set<String> groups, String user) com.google.common.util.concurrent.ListenableFuture
<LoginReply> login
(String clientId, String ipAddress, LoginRequest request) private com.google.common.util.concurrent.ListenableFuture
<LoginReply> loginWithPassword
(String clientId, String ipAddress, @Nullable String locale, @Nullable String password, @Nullable String login) private com.google.common.util.concurrent.ListenableFuture
<LoginReply> loginWithToken
(String clientId, String ipAddress, String token) com.google.common.util.concurrent.ListenableFuture
<LogoutReply> logout
(String clientId, LogoutRequest request) Optional
<com.yubico.webauthn.RegisteredCredential> lookup
(com.yubico.webauthn.data.ByteArray credentialId, com.yubico.webauthn.data.ByteArray userHandle) Set
<com.yubico.webauthn.RegisteredCredential> lookupAll
(com.yubico.webauthn.data.ByteArray credentialId) lookupUserByPhoneAndEmail
(String email, String phone) private UserGroupSearchReply
private static @Nullable MetaUser
newMaskedUser
(@Nullable MetaUser user) private static @Nullable MetaUser.MetaUserWebAuthn
newMaskedWebAuthn
(@Nullable MetaUser.MetaUserWebAuthn webAuthn) private UserSearchReply
newUserSearchReply
(boolean mask, LuceneService.SearchResult result) private com.google.common.util.concurrent.ListenableFuture
<UserConfigWriteReply> processConfigWrite
(UserConfigWriteRequest request) private com.google.common.util.concurrent.ListenableFuture
<UserGroupWriteReply> processGroupWrite
(UserGroupWriteRequest request) private com.google.common.util.concurrent.ListenableFuture
<UserGroupWriteUpdateReply> private com.google.common.util.concurrent.ListenableFuture
<UserWriteReply> processUserWrite
(UserWriteRequest request) private com.google.common.util.concurrent.ListenableFuture
<UserWriteUpdateReply> void
recordFailedAttempt
(@Nullable String clientId, @Nullable String ipAddress, String source, @Nullable String user) com.google.common.util.concurrent.ListenableFuture
<RecoverUserReply> recoverUser
(String clientId, String ipAddress, RecoverUserRequest request) com.google.common.util.concurrent.ListenableFuture
<ResetPasswordReply> resetPassword
(String clientId, String ipAddress, ResetPasswordRequest request) private static String
private static String
sanitizeOtp
(String otp) private static @Nullable String
sanitizeWebAuthnDisplayName
(String displayName) protected void
shutDown()
private com.google.common.util.concurrent.ListenableFuture
<Void> startOtpChallenge
(String clientId, UserService.UserServiceContactConfig contact, String ipAddress, @Nullable String locale, UserService.OtpChallengeType type, String user, MetaUser.MetaUserOtp userOtp) protected void
startUp()
com.google.common.util.concurrent.ListenableFuture
<Void> startVerifyOtp
(String clientId, @Nullable UserService.UserServiceContactConfig contact, String ipAddress, @Nullable String locale, String user, MetaUser.MetaUserOtp userOtp) startWebAuthnAssertion
(String clientId, String user) startWebAuthnRegistration
(String displayName, @Nullable String existingUserHandle, String user) com.google.common.util.concurrent.ListenableFuture
<String> startWebhookAuth
(String authRef) void
updateClientList
(ClientListEntry entry) private void
updateUserCache
(String user) com.google.common.util.concurrent.ListenableFuture
<UserSearchReply> userSearch
(UserSearchRequest request) protected com.google.common.util.concurrent.ListenableFuture
<UserSearchReply> userSearchInternal
(boolean mask, UserSearchRequest request) static com.google.common.util.concurrent.ListenableFuture
<Void> userSearchRecursive
(Executor executor, Function<UserSearchReply, com.google.common.util.concurrent.ListenableFuture<?>> replyConsumer, UserSearchRequest request, Function<UserSearchRequest, com.google.common.util.concurrent.ListenableFuture<UserSearchReply>> service) com.google.common.util.concurrent.ListenableFuture
<UserWriteReply> userWrite
(@Nullable String clientId, boolean enforce, @Nullable String ipAddress, UserWriteRequest request) userWrite processesUserWriteRequest
.protected com.google.common.util.concurrent.ListenableFuture
<UserWriteReply> userWriteInternal
(@Nullable String clientId, boolean enforce, boolean hashed, @Nullable String ipAddress, boolean mask, UserWriteRequest request) com.google.common.util.concurrent.ListenableFuture
<UserWriteUpdateReply> userWriteUpdate
(UserWriteUpdateRequest request) private static UserService.PasswordValidation
validatePassword
(String existingPassword, boolean hashed, String password, @Nullable Pattern passwordRegex, int scryptCpu, int scryptMemory) private static UserService.OtpValidation
validateUserOtp
(@Nullable UserService.UserServiceEnforceConfig enforceConfig, @Nullable MetaUser.MetaUserOtp existingUserOtp, boolean hashed, @Nullable UserService.PendingUserValidation pendingUserValidation, @Nullable MetaUser.MetaUserOtp userOtp) validateUserWrite
(@Nullable String clientId, boolean enforce, boolean hashed, @Nullable String ipAddress, UserWriteRequest request, MetaUser user, @Nullable UserService.UserCacheEntry cacheEntry, String userName) private Optional
<ErrorReply> verifyOtpChallenge
(String clientId, String ipAddress, String otp, UserService.OtpChallengeType type, String user) private boolean
verifyPassword
(@Nullable String password, MetaUser user) boolean
verifyScryptHash
(@Nullable String hash, @Nullable String secret) boolean
verifyScryptOtp
(@Nullable String hash, @Nullable String otp) verifyToken
(@Nullable String clientId, String ipAddress, UserService.VerifyTokenRequest request) static boolean
verifyTotp
(int acceptedCodes, String totpKey, @Nullable String totp) verifyTotp generates codes from the given key and compares them to the given totp.boolean
verifyTotp
(String totpKey, @Nullable String totp) void
verifyWebhookAuth
(String authRef, String otp) private void
writeGroup
(WriteAction action, @Nullable MetaUserGroup existingGroup, MetaUserGroup group, org.apache.lucene.index.IndexWriter writer) private void
writeUser
(WriteAction action, @Nullable org.apache.lucene.document.Document document, String userName, org.apache.lucene.index.IndexWriter writer) Methods inherited from class ch.rswk.meta.engine.AbstractEngineIdleService
configClass, configReference, onConfigWatcherNotification, serviceId, serviceName
Methods inherited from class com.google.common.util.concurrent.AbstractIdleService
addListener, awaitRunning, awaitRunning, awaitRunning, awaitTerminated, awaitTerminated, awaitTerminated, executor, failureCause, isRunning, startAsync, state, stopAsync, toString
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Methods inherited from interface ch.rswk.meta.engine.EngineServices.ConfigurableService
config, handleConfigWatcherNotification, onConfigChanged
Methods inherited from interface ch.rswk.meta.engine.EngineServices.InfoProvidingService
getServiceInfo
-
Field Details
-
LOG
private static final org.slf4j.Logger LOG -
TOTP_VALIDITY
public static final long TOTP_VALIDITY- See Also:
-
USER_CONFIG_EMAIL
- See Also:
-
USER_CONFIG_PHONE
- See Also:
-
ATTEMPTS_EXCEEDED_ERROR
-
AUTH_ERROR
-
AUTH_TOKEN_EXPIRATION
private static final int AUTH_TOKEN_EXPIRATION- See Also:
-
CLEANUP_SCHEDULE
-
CLIENT_NAME_OR_VERSION_MATCHER
private static final com.google.common.base.CharMatcher CLIENT_NAME_OR_VERSION_MATCHER -
CONFIG_ALREADY_EXISTS_ERROR
-
CONFIG_READER
private static final com.fasterxml.jackson.databind.ObjectReader CONFIG_READER -
DELETE_ADMIN_GROUP_ERROR
-
GROUP_ALREADY_EXISTS_ERROR
-
GROUP_READER
private static final com.fasterxml.jackson.databind.ObjectReader GROUP_READER -
INVALID_CONFIG_ERROR
-
INVALID_GROUP_ERROR
-
INVALID_OTP_ERROR
-
INVALID_PASSWORD_ERROR
-
INVALID_USER_ERROR
-
MISSING_SUBJECT_ERROR
-
NO_GROUP_FOR_UPDATE_ERROR
-
NO_USER_FOR_UPDATE_ERROR
-
NO_VERIFY_REQUEST_ERROR
-
OTP_BOUND
private static final int OTP_BOUND- See Also:
-
OTP_DELIVERY_FAILED_ERROR
-
OTP_SEPARATOR
- See Also:
-
OTP_VERIFICATION_ERROR
-
RANDOM
-
SEARCH_ERROR
-
TOKEN_DESERIALIZER
-
TOKEN_ISSUER
-
TOKEN_SERIALIZER
-
TOTP_ACCEPTED_CODES
private static final int TOTP_ACCEPTED_CODES- See Also:
-
TOTP_RETURN_DIGITS
- See Also:
-
UPDATE_ERROR
-
USER_ALREADY_EXISTS_ERROR
-
USER_CONFIG_GROUP_QUERY_FORMAT
- See Also:
-
USER_CONFIG_QUERY_FORMAT
- See Also:
-
USER_GROUP_MEMBER_QUERY_FORMAT
- See Also:
-
USER_READER
private static final com.fasterxml.jackson.databind.ObjectReader USER_READER -
WEBAUTHN_ASSERTION_ERROR
-
WEBAUTHN_ASSERTION_TYPE
private static final com.fasterxml.jackson.core.type.TypeReference<com.yubico.webauthn.data.PublicKeyCredential<com.yubico.webauthn.data.AuthenticatorAssertionResponse,com.yubico.webauthn.data.ClientAssertionExtensionOutputs>> WEBAUTHN_ASSERTION_TYPE -
WEBAUTHN_CREDENTIAL_QUERY_FORMAT
- See Also:
-
WEBAUTHN_DISPLAY_NAME_MATCHER
private static final com.google.common.base.CharMatcher WEBAUTHN_DISPLAY_NAME_MATCHER -
WEBAUTHN_MAPPER
private static final com.fasterxml.jackson.databind.ObjectMapper WEBAUTHN_MAPPER -
WEBAUTHN_REGISTRATION_ERROR
-
WEBAUTHN_REGISTRATION_TYPE
private static final com.fasterxml.jackson.core.type.TypeReference<com.yubico.webauthn.data.PublicKeyCredential<com.yubico.webauthn.data.AuthenticatorAttestationResponse,com.yubico.webauthn.data.ClientRegistrationExtensionOutputs>> WEBAUTHN_REGISTRATION_TYPE -
WEBAUTHN_USER_HANDLE_QUERY_FORMAT
- See Also:
-
WEBHOOK_ERROR
-
WRITE_ERROR
-
backupService
-
clients
-
disconnectedClientIds
-
failedAttempts
-
gatewayService
-
luceneService
-
webhookAuthFutures
-
webhookAuthMonitor
private final com.google.common.util.concurrent.Monitor webhookAuthMonitor -
authContact
-
authErrorMeter
private com.codahale.metrics.Meter authErrorMeter -
authMeter
private com.codahale.metrics.Meter authMeter -
authTokenKey
-
authTokenMeter
private com.codahale.metrics.Meter authTokenMeter -
clientListMeter
private com.codahale.metrics.Meter clientListMeter -
configCache
private com.github.benmanes.caffeine.cache.AsyncLoadingCache<String,Optional<MetaUserConfig>> configCache -
configSearchMeter
private com.codahale.metrics.Meter configSearchMeter -
configWriteMeter
private com.codahale.metrics.Meter configWriteMeter -
failedAttemptMeter
private com.codahale.metrics.Meter failedAttemptMeter -
failedTokenMeter
private com.codahale.metrics.Meter failedTokenMeter -
groupCache
private com.github.benmanes.caffeine.cache.AsyncLoadingCache<String,Optional<MetaUserGroup>> groupCache -
groupSearchMeter
private com.codahale.metrics.Meter groupSearchMeter -
groupUpdateMeter
private com.codahale.metrics.Meter groupUpdateMeter -
groupWriteMeter
private com.codahale.metrics.Meter groupWriteMeter -
loginMeter
private com.codahale.metrics.Meter loginMeter -
logoutMeter
private com.codahale.metrics.Meter logoutMeter -
otpCache
-
otpExpiredMeter
private com.codahale.metrics.Meter otpExpiredMeter -
otpTimer
private com.codahale.metrics.Timer otpTimer -
passwordRegex
-
recoverContact
-
recoverErrorMeter
private com.codahale.metrics.Meter recoverErrorMeter -
recoverMeter
private com.codahale.metrics.Meter recoverMeter -
resetContact
-
resetPasswordErrorMeter
private com.codahale.metrics.Meter resetPasswordErrorMeter -
resetPasswordMeter
private com.codahale.metrics.Meter resetPasswordMeter -
scryptMeter
private com.codahale.metrics.Meter scryptMeter -
tokenInvalidationCache
-
tokenKey
-
tokenMeter
private com.codahale.metrics.Meter tokenMeter -
totpMeter
private com.codahale.metrics.Meter totpMeter -
userCache
private com.github.benmanes.caffeine.cache.AsyncLoadingCache<String,Optional<UserService.UserCacheEntry>> userCache -
userSearchMeter
private com.codahale.metrics.Meter userSearchMeter -
userUpdateMeter
private com.codahale.metrics.Meter userUpdateMeter -
userValidationCache
private com.github.benmanes.caffeine.cache.Cache<String,UserService.PendingUserValidation> userValidationCache -
userWriteMeter
private com.codahale.metrics.Meter userWriteMeter -
verifyContact
-
verifyOtpCache
-
verifyOtpErrorMeter
private com.codahale.metrics.Meter verifyOtpErrorMeter -
verifyOtpMeter
private com.codahale.metrics.Meter verifyOtpMeter -
verifyTokenErrorMeter
private com.codahale.metrics.Meter verifyTokenErrorMeter -
verifyTokenMeter
private com.codahale.metrics.Meter verifyTokenMeter -
webAuthnAssertionCache
private com.github.benmanes.caffeine.cache.Cache<String,com.yubico.webauthn.AssertionRequest> webAuthnAssertionCache -
webAuthnRegistrationCache
private com.github.benmanes.caffeine.cache.Cache<String,com.yubico.webauthn.data.PublicKeyCredentialCreationOptions> webAuthnRegistrationCache -
webAuthnRelyingParty
private com.yubico.webauthn.RelyingParty webAuthnRelyingParty -
webhookAuthReceived
-
webhookMeter
private com.codahale.metrics.Meter webhookMeter -
writeErrorMeter
private com.codahale.metrics.Meter writeErrorMeter
-
-
Constructor Details
-
UserService
@Inject public UserService(BackupService backupService, UserService.UserServiceConfig config, GatewayService gatewayService, @Named("User") LuceneService luceneService, EngineRuntime runtime)
-
-
Method Details
-
auth
public com.google.common.util.concurrent.ListenableFuture<AuthReply> auth(String clientId, String ipAddress, AuthRequest request, String user) -
checkAttempts
-
checkAttempts
-
finishWebAuthnAssertion
private Optional<ErrorReply> finishWebAuthnAssertion(AuthRequest.AuthRequestWebAuthnAssertionReply assertionReply, String clientId, @Nullable String ipAddress, String user) -
recordFailedAttempt
-
verifyOtpChallenge
private Optional<ErrorReply> verifyOtpChallenge(String clientId, String ipAddress, String otp, UserService.OtpChallengeType type, String user) -
verifyTotp
verifyTotp generates codes from the given key and compares them to the given totp.- Parameters:
acceptedCodes
- number of accepted codes. 1 = only the current code is accepted, 2 = current and one past code is accepted, and so on. One future code is always accepted
-
sanitizeOtp
-
generateTotp
generateTotp generates a totp from the given key based on the current time plus offset.- Parameters:
offset
- positive or negative time step offset. 0 = current time step, 1 = future time step, and so on. Time step is based onTOTP_VALIDITY
- See Also:
-
verifyScryptOtp
-
verifyScryptHash
-
getCachedUser
public com.google.common.util.concurrent.ListenableFuture<Optional<UserService.UserCacheEntry>> getCachedUser(String user) -
loadUserConfigs
private com.google.common.util.concurrent.ListenableFuture<UserService.UserConfigResult> loadUserConfigs(Set<String> groups, String user) -
configSearch
public com.google.common.util.concurrent.ListenableFuture<UserConfigSearchReply> configSearch(UserConfigSearchRequest request) -
updateClientList
-
authToken
public com.google.common.util.concurrent.ListenableFuture<AuthTokenReply> authToken(String clientId, String ipAddress, AuthTokenRequest request, String user) throws ErrorReplyException - Throws:
ErrorReplyException
-
generateToken
- Throws:
ErrorReplyException
-
configSearchRecursive
public static com.google.common.util.concurrent.ListenableFuture<Void> configSearchRecursive(Executor executor, Function<UserConfigSearchReply, com.google.common.util.concurrent.ListenableFuture<?>> replyConsumer, UserConfigSearchRequest request, Function<UserConfigSearchRequest, com.google.common.util.concurrent.ListenableFuture<UserConfigSearchReply>> service) -
configWrite
public com.google.common.util.concurrent.ListenableFuture<UserConfigWriteReply> configWrite(UserConfigWriteRequest request) -
getCachedConfig
public com.google.common.util.concurrent.ListenableFuture<Optional<MetaUserConfig>> getCachedConfig(String configId) -
processConfigWrite
private com.google.common.util.concurrent.ListenableFuture<UserConfigWriteReply> processConfigWrite(UserConfigWriteRequest request) -
finishWebAuthnRegistration
private Optional<MetaUser.MetaUserWebAuthn> finishWebAuthnRegistration(UserWriteRequest.UserWriteRequestWebAuthnReply createReply, String user) -
generateTotpKey
-
generateUserToken
public com.google.common.util.concurrent.ListenableFuture<UserService.UserTokenReply> generateUserToken(@Nullable String clientId, String ipAddress, UserService.UserTokenRequest request) throws ErrorReplyException generateUserToken authenticates the given user/password and generates a token containing all grants for user and its groups. Use this for system/technical users with limited permissions.- Throws:
ErrorReplyException
- missing user name, user has OTP/WebAuthn or authentication fails
-
verifyPassword
-
groupSearch
public com.google.common.util.concurrent.ListenableFuture<UserGroupSearchReply> groupSearch(UserGroupSearchRequest request) -
executeLuceneGroupSearch
private LuceneService.SearchResult executeLuceneGroupSearch(LuceneService.LuceneContext context, UserGroupSearchRequest request) throws org.apache.lucene.queryparser.flexible.core.QueryNodeException, IOException - Throws:
org.apache.lucene.queryparser.flexible.core.QueryNodeException
IOException
-
newGroupSearchReply
-
getClientList
public com.google.common.util.concurrent.ListenableFuture<ClientListReply> getClientList(ClientListRequest request) -
getCredentialIdsForUsername
-
getUserHandleForUsername
-
getUsernameForUserHandle
-
lookup
public Optional<com.yubico.webauthn.RegisteredCredential> lookup(com.yubico.webauthn.data.ByteArray credentialId, com.yubico.webauthn.data.ByteArray userHandle) - Specified by:
lookup
in interfacecom.yubico.webauthn.CredentialRepository
-
lookupAll
public Set<com.yubico.webauthn.RegisteredCredential> lookupAll(com.yubico.webauthn.data.ByteArray credentialId) - Specified by:
lookupAll
in interfacecom.yubico.webauthn.CredentialRepository
-
findUserForHandle
-
userSearchInternal
protected com.google.common.util.concurrent.ListenableFuture<UserSearchReply> userSearchInternal(boolean mask, UserSearchRequest request) -
executeLuceneUserSearch
private LuceneService.SearchResult executeLuceneUserSearch(LuceneService.LuceneContext context, UserSearchRequest request) throws org.apache.lucene.queryparser.flexible.core.QueryNodeException, IOException - Throws:
org.apache.lucene.queryparser.flexible.core.QueryNodeException
IOException
-
newUserSearchReply
-
newMaskedUser
-
newMaskedWebAuthn
private static @Nullable MetaUser.MetaUserWebAuthn newMaskedWebAuthn(@Nullable MetaUser.MetaUserWebAuthn webAuthn) -
groupSearchRecursive
public static com.google.common.util.concurrent.ListenableFuture<Void> groupSearchRecursive(Executor executor, Function<UserGroupSearchReply, com.google.common.util.concurrent.ListenableFuture<?>> replyConsumer, UserGroupSearchRequest request, Function<UserGroupSearchRequest, com.google.common.util.concurrent.ListenableFuture<UserGroupSearchReply>> service) -
groupWrite
public com.google.common.util.concurrent.ListenableFuture<UserGroupWriteReply> groupWrite(UserGroupWriteRequest request) -
getCachedGroup
public com.google.common.util.concurrent.ListenableFuture<Optional<MetaUserGroup>> getCachedGroup(String group) -
processGroupWrite
private com.google.common.util.concurrent.ListenableFuture<UserGroupWriteReply> processGroupWrite(UserGroupWriteRequest request) -
deleteConfigs
-
writeGroup
private void writeGroup(WriteAction action, @Nullable MetaUserGroup existingGroup, MetaUserGroup group, org.apache.lucene.index.IndexWriter writer) -
updateUserCache
-
groupWriteUpdate
public com.google.common.util.concurrent.ListenableFuture<UserGroupWriteUpdateReply> groupWriteUpdate(UserGroupWriteUpdateRequest request) -
processGroupWriteUpdate
private com.google.common.util.concurrent.ListenableFuture<UserGroupWriteUpdateReply> processGroupWriteUpdate(UserGroupWriteUpdateRequest request) -
hasRequiredGrants
-
hasUserPermission
-
isMember
-
login
public com.google.common.util.concurrent.ListenableFuture<LoginReply> login(String clientId, String ipAddress, LoginRequest request) -
loginWithPassword
-
loginWithToken
private com.google.common.util.concurrent.ListenableFuture<LoginReply> loginWithToken(String clientId, String ipAddress, String token) -
logout
public com.google.common.util.concurrent.ListenableFuture<LogoutReply> logout(String clientId, LogoutRequest request) -
processUserWrite
private com.google.common.util.concurrent.ListenableFuture<UserWriteReply> processUserWrite(UserWriteRequest request) -
recoverUser
public com.google.common.util.concurrent.ListenableFuture<RecoverUserReply> recoverUser(String clientId, String ipAddress, RecoverUserRequest request) -
lookupUserByPhoneAndEmail
-
forgeEmailAndPhoneQuery
-
resetPassword
public com.google.common.util.concurrent.ListenableFuture<ResetPasswordReply> resetPassword(String clientId, String ipAddress, ResetPasswordRequest request) -
sanitizeClientNameOrVersion
-
sanitizeWebAuthnDisplayName
-
startUp
- Overrides:
startUp
in classAbstractEngineIdleService<UserService.UserServiceConfig>
- Throws:
Exception
-
deleteDisconnectedClientIds
private void deleteDisconnectedClientIds() -
decrementFailedAttempts
private void decrementFailedAttempts() -
shutDown
- Overrides:
shutDown
in classAbstractEngineIdleService<UserService.UserServiceConfig>
- Throws:
Exception
-
startVerifyOtp
public com.google.common.util.concurrent.ListenableFuture<Void> startVerifyOtp(String clientId, @Nullable UserService.UserServiceContactConfig contact, String ipAddress, @Nullable String locale, String user, MetaUser.MetaUserOtp userOtp) -
startOtpChallenge
private com.google.common.util.concurrent.ListenableFuture<Void> startOtpChallenge(String clientId, UserService.UserServiceContactConfig contact, String ipAddress, @Nullable String locale, UserService.OtpChallengeType type, String user, MetaUser.MetaUserOtp userOtp) -
generateScryptOtp
-
generateScryptHash
-
startWebAuthnAssertion
private LoginReply.LoginReplyWebAuthnAssertionRequest startWebAuthnAssertion(String clientId, String user) -
startWebAuthnRegistration
private UserWriteReply.UserWriteReplyWebAuthnRequest startWebAuthnRegistration(String displayName, @Nullable String existingUserHandle, String user) -
startWebhookAuth
public com.google.common.util.concurrent.ListenableFuture<String> startWebhookAuth(String authRef) throws ErrorReplyException - Throws:
ErrorReplyException
-
userSearch
public com.google.common.util.concurrent.ListenableFuture<UserSearchReply> userSearch(UserSearchRequest request) -
userSearchRecursive
public static com.google.common.util.concurrent.ListenableFuture<Void> userSearchRecursive(Executor executor, Function<UserSearchReply, com.google.common.util.concurrent.ListenableFuture<?>> replyConsumer, UserSearchRequest request, Function<UserSearchRequest, com.google.common.util.concurrent.ListenableFuture<UserSearchReply>> service) -
userWrite
public com.google.common.util.concurrent.ListenableFuture<UserWriteReply> userWrite(@Nullable String clientId, boolean enforce, @Nullable String ipAddress, UserWriteRequest request) userWrite processesUserWriteRequest
. Some write operations require a second call to userWrite with additional parameters.For WebAuthn, a second request is required with a valid
UserWriteRequest.UserWriteRequestWebAuthnReply
.- Parameters:
clientId
- optional, if provided andMetaUser.MetaUserOtp
has changed, a second request for OTP verification is requiredenforce
- if true, then anyUserService.UserServiceEnforceConfig
options are going to be enforcedipAddress
- optional, must be provied together with clientId for OTP verification
-
userWriteInternal
protected com.google.common.util.concurrent.ListenableFuture<UserWriteReply> userWriteInternal(@Nullable String clientId, boolean enforce, boolean hashed, @Nullable String ipAddress, boolean mask, UserWriteRequest request) -
userWriteUpdate
public com.google.common.util.concurrent.ListenableFuture<UserWriteUpdateReply> userWriteUpdate(UserWriteUpdateRequest request) -
processUserWriteUpdate
private com.google.common.util.concurrent.ListenableFuture<UserWriteUpdateReply> processUserWriteUpdate(UserWriteUpdateRequest request) -
getUserWithAddedAndRemovedGrants
private static MetaUser getUserWithAddedAndRemovedGrants(UserWriteUpdateRequest request, UserSearchReply searchReply) -
writeUser
private void writeUser(WriteAction action, @Nullable org.apache.lucene.document.Document document, String userName, org.apache.lucene.index.IndexWriter writer) -
validatePassword
private static UserService.PasswordValidation validatePassword(String existingPassword, boolean hashed, String password, @Nullable Pattern passwordRegex, int scryptCpu, int scryptMemory) -
validateUserOtp
private static UserService.OtpValidation validateUserOtp(@Nullable UserService.UserServiceEnforceConfig enforceConfig, @Nullable MetaUser.MetaUserOtp existingUserOtp, boolean hashed, @Nullable UserService.PendingUserValidation pendingUserValidation, @Nullable MetaUser.MetaUserOtp userOtp) -
validateUserWrite
private UserService.UserWriteValidationResult validateUserWrite(@Nullable String clientId, boolean enforce, boolean hashed, @Nullable String ipAddress, UserWriteRequest request, MetaUser user, @Nullable UserService.UserCacheEntry cacheEntry, String userName) -
verifyOtp
-
verifyToken
public UserService.VerifyTokenReply verifyToken(@Nullable String clientId, String ipAddress, UserService.VerifyTokenRequest request) -
verifyTotp
-
verifyWebhookAuth
- Throws:
ErrorReplyException
-