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

io.getlime.security.powerauth.rest.api.spring.provider.PowerAuthAuthenticationProviderBase Maven / Gradle / Ivy

/*
 * PowerAuth integration libraries for RESTful API applications, examples and
 * related software components
 *
 * Copyright (C) 2018 Wultra s.r.o.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */
package io.getlime.security.powerauth.rest.api.spring.provider;

import io.getlime.security.powerauth.crypto.lib.enums.PowerAuthSignatureTypes;
import io.getlime.security.powerauth.rest.api.spring.authentication.PowerAuthApiAuthentication;
import io.getlime.security.powerauth.rest.api.spring.encryption.PowerAuthEciesEncryption;
import io.getlime.security.powerauth.rest.api.spring.exception.PowerAuthAuthenticationException;
import io.getlime.security.powerauth.rest.api.spring.exception.authentication.PowerAuthRequestFilterException;
import io.getlime.security.powerauth.rest.api.spring.model.PowerAuthRequestBody;
import io.getlime.security.powerauth.rest.api.spring.model.PowerAuthRequestObjects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * Abstract class for PowerAuth authentication provider.
 *
 * @author Petr Dvorak, [email protected]
 *
 */
public abstract class PowerAuthAuthenticationProviderBase {

    private static final Logger logger = LoggerFactory.getLogger(PowerAuthAuthenticationProviderBase.class);

    /**
     * Validate the signature from the PowerAuth HTTP header against the provided HTTP method, request body and URI identifier.
     * Make sure to accept only allowed signatures. Return an instance of PowerAuthApiAuthentication on successful authorization,
     * null value is returned on failed authorization. A check of null return value is used to determine the authorization result.
     * @param httpMethod HTTP method (GET, POST, ...)
     * @param httpBody Body of the HTTP request.
     * @param requestUriIdentifier Request URI identifier.
     * @param httpAuthorizationHeader PowerAuth HTTP authorization header.
     * @param allowedSignatureTypes Allowed types of the signature.
     * @param forcedSignatureVersion Forced signature version during upgrade.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization, null value on failed authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public abstract @Nullable PowerAuthApiAuthentication validateRequestSignature(@Nonnull String httpMethod, @Nullable byte[] httpBody, @Nonnull String requestUriIdentifier, @Nonnull String httpAuthorizationHeader, @Nonnull List allowedSignatureTypes, @Nullable Integer forcedSignatureVersion) throws PowerAuthAuthenticationException;

    /**
     * Validate the signature from the PowerAuth HTTP header against the provided HTTP method, request body and URI identifier.
     * Make sure to accept only allowed signatures. Return an instance of PowerAuthApiAuthentication on both successful and
     * failed authorization. A check of null return value cannot be used to determine the authorization result, the actual
     * result is available in the authorization context.
     * @param httpMethod HTTP method (GET, POST, ...)
     * @param httpBody Body of the HTTP request.
     * @param requestUriIdentifier Request URI identifier.
     * @param httpAuthorizationHeader PowerAuth HTTP authorization header.
     * @param allowedSignatureTypes Allowed types of the signature.
     * @param forcedSignatureVersion Forced signature version during upgrade.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public abstract @Nonnull PowerAuthApiAuthentication validateRequestSignatureWithActivationDetails(@Nonnull String httpMethod, @Nullable byte[] httpBody, @Nonnull String requestUriIdentifier, @Nonnull String httpAuthorizationHeader, @Nonnull List allowedSignatureTypes, @Nullable Integer forcedSignatureVersion) throws PowerAuthAuthenticationException;

    /**
     * Validate the token digest from PowerAuth authentication header.
     * @param httpAuthorizationHeader HTTP header with token digest.
     * @param allowedSignatureTypes Allowed types of the signature.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public abstract @Nullable PowerAuthApiAuthentication validateToken(@Nonnull String httpAuthorizationHeader, @Nonnull List allowedSignatureTypes) throws PowerAuthAuthenticationException;

    /**
     * Validate the token digest from PowerAuth authentication header.
     * @param httpAuthorizationHeader HTTP header with token digest.
     * @param allowedSignatureTypes Allowed types of the signature.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public abstract @Nonnull PowerAuthApiAuthentication validateTokenWithActivationDetails(@Nonnull String httpAuthorizationHeader, @Nonnull List allowedSignatureTypes) throws PowerAuthAuthenticationException;

    /**
     * The same as {{@link #validateRequestSignature(String, byte[], String, String, List, Integer)} but uses default accepted signature type (2FA or 3FA) and does not specify forced signature version.
     * @param httpMethod HTTP method (GET, POST, ...)
     * @param httpBody Request body
     * @param requestUriIdentifier Request URI identifier.
     * @param httpAuthorizationHeader PowerAuth HTTP authorization header.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public @Nullable PowerAuthApiAuthentication validateRequestSignature(@Nonnull String httpMethod, @Nullable byte[] httpBody, @Nonnull String requestUriIdentifier, @Nonnull String httpAuthorizationHeader) throws PowerAuthAuthenticationException {
        List defaultAllowedSignatureTypes = new ArrayList<>();
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_KNOWLEDGE);
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_BIOMETRY);
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_KNOWLEDGE_BIOMETRY);
        return this.validateRequestSignature(httpMethod, httpBody, requestUriIdentifier, httpAuthorizationHeader, defaultAllowedSignatureTypes, null);
    }

    /**
     * Validate a request signature, make sure only supported signature types are used, do not use forced signature version during upgrade.
     * @param servletRequest HTTPServletRequest with signed data.
     * @param requestUriIdentifier Request URI identifier.
     * @param httpAuthorizationHeader PowerAuth HTTP authorization header.
     * @param allowedSignatureTypes Allowed types of signatures.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public @Nullable PowerAuthApiAuthentication validateRequestSignature(@Nonnull HttpServletRequest servletRequest, @Nonnull String requestUriIdentifier, @Nonnull String httpAuthorizationHeader, @Nonnull List allowedSignatureTypes) throws PowerAuthAuthenticationException {
        // Get HTTP method and body bytes
        String requestMethod = servletRequest.getMethod().toUpperCase();
        byte[] requestBodyBytes = extractRequestBodyBytes(servletRequest);
        return this.validateRequestSignature(requestMethod, requestBodyBytes, requestUriIdentifier, httpAuthorizationHeader, allowedSignatureTypes, null);
    }

    /**
     * Validate a request signature, make sure only supported signature types are used, do not use forced signature version during upgrade.
     * @param servletRequest HTTPServletRequest with signed data.
     * @param requestUriIdentifier Request URI identifier.
     * @param httpAuthorizationHeader PowerAuth HTTP authorization header.
     * @param allowedSignatureTypes Allowed types of signatures.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public @Nonnull PowerAuthApiAuthentication validateRequestSignatureWithActivationDetails(@Nonnull HttpServletRequest servletRequest, @Nonnull String requestUriIdentifier, @Nonnull String httpAuthorizationHeader, @Nonnull List allowedSignatureTypes) throws PowerAuthAuthenticationException {
        // Get HTTP method and body bytes
        String requestMethod = servletRequest.getMethod().toUpperCase();
        byte[] requestBodyBytes = extractRequestBodyBytes(servletRequest);
        return this.validateRequestSignatureWithActivationDetails(requestMethod, requestBodyBytes, requestUriIdentifier, httpAuthorizationHeader, allowedSignatureTypes, null);
    }

    /**
     * Validate a request signature, make sure only supported signature types are used and allow specification of forced signature version.
     * @param servletRequest HTTPServletRequest with signed data.
     * @param requestUriIdentifier Request URI identifier.
     * @param httpAuthorizationHeader PowerAuth HTTP authorization header.
     * @param allowedSignatureTypes Allowed types of signatures.
     * @param forcedSignatureVersion Forced signature version during upgrade.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public @Nullable PowerAuthApiAuthentication validateRequestSignature(@Nonnull HttpServletRequest servletRequest, @Nonnull String requestUriIdentifier, @Nonnull String httpAuthorizationHeader, @Nonnull List allowedSignatureTypes, @Nullable Integer forcedSignatureVersion) throws PowerAuthAuthenticationException {
        // Get HTTP method and body bytes
        String requestMethod = servletRequest.getMethod().toUpperCase();
        byte[] requestBodyBytes = extractRequestBodyBytes(servletRequest);
        return this.validateRequestSignature(requestMethod, requestBodyBytes, requestUriIdentifier, httpAuthorizationHeader, allowedSignatureTypes, forcedSignatureVersion);
    }

    /**
     * The same as {{@link #validateRequestSignature(HttpServletRequest, String, String, List, Integer)} but uses default accepted signature type (2FA or 3FA) and does not specify forced signature version.
     * @param servletRequest HTTPServletRequest with signed data.
     * @param requestUriIdentifier Request URI identifier.
     * @param httpAuthorizationHeader PowerAuth HTTP authorization header.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public @Nullable PowerAuthApiAuthentication validateRequestSignature(@Nonnull HttpServletRequest servletRequest, @Nonnull String requestUriIdentifier, @Nonnull String httpAuthorizationHeader) throws PowerAuthAuthenticationException {
        List defaultAllowedSignatureTypes = new ArrayList<>();
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_KNOWLEDGE);
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_BIOMETRY);
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_KNOWLEDGE_BIOMETRY);
        return this.validateRequestSignature(servletRequest, requestUriIdentifier, httpAuthorizationHeader, defaultAllowedSignatureTypes, null);
    }

    /**
     * Validate the token digest from PowerAuth authentication header.
     * @param tokenHeader HTTP header with token digest.
     * @return Instance of a PowerAuthApiAuthentication on successful authorization.
     * @throws PowerAuthAuthenticationException In case authorization fails, exception is raised.
     */
    public @Nullable PowerAuthApiAuthentication validateToken(@Nonnull String tokenHeader) throws PowerAuthAuthenticationException {
        List defaultAllowedSignatureTypes = new ArrayList<>();
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_KNOWLEDGE);
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_BIOMETRY);
        defaultAllowedSignatureTypes.add(PowerAuthSignatureTypes.POSSESSION_KNOWLEDGE_BIOMETRY);
        return this.validateToken(tokenHeader, defaultAllowedSignatureTypes);
    }

    /**
     * Extract request body bytes from HTTP servlet request. In case the data was transparently decrypted, use the decrypted request data.
     * @param servletRequest HTTP servlet request.
     * @return Request body bytes.
     * @throws PowerAuthAuthenticationException In case request body is invalid.
     */
    public @Nullable byte[] extractRequestBodyBytes(@Nonnull HttpServletRequest servletRequest) throws PowerAuthAuthenticationException {
        if (servletRequest.getAttribute(PowerAuthRequestObjects.ENCRYPTION_OBJECT) != null) {
            // Implementation of sign-then-encrypt - in case the encryption object is present and signature is validate, use decrypted request data
            PowerAuthEciesEncryption eciesEncryption = (PowerAuthEciesEncryption) servletRequest.getAttribute(PowerAuthRequestObjects.ENCRYPTION_OBJECT);
            return eciesEncryption.getDecryptedRequest();
        } else {
            // Request data was not encrypted - use regular PowerAuth request body for signature validation
            PowerAuthRequestBody requestBody = ((PowerAuthRequestBody) servletRequest.getAttribute(PowerAuthRequestObjects.REQUEST_BODY));
            if (requestBody == null) {
                logger.warn("The X-PowerAuth-Request-Body request attribute is missing. Register the PowerAuthRequestFilter to fix this error.");
                throw new PowerAuthRequestFilterException();
            }
            return requestBody.getRequestBytes();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy