All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mangoo.routing.bindings.Authentication Maven / Gradle / Ivy

The newest version!
package io.mangoo.routing.bindings;

import io.mangoo.cache.CacheProvider;
import io.mangoo.constants.CacheName;
import io.mangoo.constants.NotNull;
import io.mangoo.core.Application;
import io.mangoo.core.Config;
import io.mangoo.utils.CodecUtils;
import io.mangoo.utils.totp.TotpUtils;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

public class Authentication {
    private LocalDateTime expires;
    private String subject;
    private boolean twoFactor;
    private boolean remember;
    private boolean loggedOut;
    private boolean invalid;
    
    public static Authentication create() {
        return new Authentication();
    }
    
    public Authentication withExpires(LocalDateTime expires) {
        Objects.requireNonNull(expires, NotNull.EXPIRES);
        if (this.expires == null) {
            this.expires = expires;            
        }
        
        return this;
    }
    
    public Authentication withSubject(String subject) {
        if (StringUtils.isBlank(this.subject)) {
            this.subject = subject;            
        }
        
        return this;
    }

    /**
     * Retrieves the current subject
     *
     * @return The subject of the current authentication or null if not set
     */
    public String getSubject() {
        return subject;
    }
    
    /**
     * Invalidates the authentication by sending expiring the client cookie
     */
    public void invalidate() {
        invalid = true;
    }

    /**
     * Returns the LocalDateTime when the authentication expires
     *
     * @return A LocalDateTime object or null if not set
     */
    public LocalDateTime getExpires() {
        return expires;
    }

    /**
     * @return True if the user wants to log out, false otherwise
     */
    public boolean isLogout() {
        return loggedOut;
    }

    /**
     *
     * @return True if the user wants to stay logged in, false otherwise
     */
    public boolean isRememberMe() {
        return remember;
    }
    
    /**
     * @return True if two-factor authentication is enabled for this user
     */
    public boolean isTwoFactor() {
        return twoFactor;
    }
    
    /**
     * Creates a hashed value of a given clear text password and checks if the
     * value matches a given, already hashed password
     *
     * @param identifier The identifier to authenticate
     * @param password The clear text password
     * @param salt The salt to use for hashing
     * @param hash The previously hashed password to check
     * @return True if the new hashed password matches the hash, false otherwise
     */
    public boolean validLogin(String identifier, String password, String salt, String hash) {
        Objects.requireNonNull(identifier, NotNull.USERNAME);
        Objects.requireNonNull(password, NotNull.PASSWORD);
        Objects.requireNonNull(password, NotNull.SALT);
        Objects.requireNonNull(hash, NotNull.HASH);

        var cache = Application.getInstance(CacheProvider.class).getCache(CacheName.AUTH);
        var authenticated = false;
        if (!userHasLock(identifier) && CodecUtils.matchArgon2(password, salt, hash)) {
            authenticated = true;
        } else {
            cache.getAndIncrementCounter(identifier);
        }

        return authenticated;
    }
    
    /**
     * Performs a login by setting the authentication to the given identifier
     * Please note, that calling validLogin is mandatory before this call!
     * 
     * @param subject The subject to login
     * @return Authentication object
     */
    public Authentication login(String subject) {
        this.subject = subject;
        return this;
    }
    
    /**
     * Sets remember me functionality, default is false
     * 
     * @param remember The state of remember to set
     * @return Authentication object
     */
    public Authentication rememberMe(boolean remember) {
        this.remember = remember;
        return this;
    }
    
    /**
     * Sets remember me functionality to true, default is false
     * @return Authentication object
     */
    public Authentication rememberMe() {
        this.remember = true;
        return this;
    }
    
    /**
     * Sets the requirement of the two-factor authentication, default is false
     * 
     * @param twoFactor True for enabling two-factor authentication, false otherwise
     * @return Authentication object
     */
    public Authentication twoFactorAuthentication(boolean twoFactor) {
        this.twoFactor = twoFactor;
        return this;
    }
 
    /**
     * Checks if a username is locked because of to many failed login attempts
     * 
     * @param username The username to check
     * @return true if the user has a lock, false otherwise
     */
    public boolean userHasLock(String username) {
        Objects.requireNonNull(username, NotNull.USERNAME);
        var lock = false;
        
        var config = Application.getInstance(Config.class);
        var cache = Application.getInstance(CacheProvider.class).getCache(CacheName.AUTH);
        AtomicInteger counter = cache.getCounter(username);
        if (counter != null && counter.get() > config.getAuthenticationLock()) {
            lock = true;
        }
        
        return lock;
    }
    
    /**
     * Checks if a given number for 2FA is valid for the given secret
     * 
     * @param secret The plaintext secret to use for checking
     * @param number The number entered by the user
     * @return True if number is valid, false otherwise
     */
    public boolean validSecondFactor(String secret, String number) {
        Objects.requireNonNull(secret, NotNull.SECRET);
        Objects.requireNonNull(number, NotNull.TOTP);
        
        return TotpUtils.verifiedTotp(secret, number);
    }

    /**
     * Performs a logout of the currently authenticated user
     */
    public void logout() {
        loggedOut = true;
    }
    
    /**
     * Checks if the authentication class contains an authentication
     *
     * @return True if authentication contains an authentication, false otherwise
     */
    public boolean isValid() {
        return StringUtils.isNotBlank(subject);
    }
    
    public boolean isInvalid() {
        return invalid;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy