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

com.accyourate.utilities.acySecurity.SecurityUtils Maven / Gradle / Ivy

package com.accyourate.utilities.acySecurity;

import com.accyourate.utilities.StaticParams;
import com.accyourate.utilities.encrypter.StringEncrypter;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.Unirest;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.spec.RSAPublicKeySpec;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 *  security utils
 *
 */
public class SecurityUtils {

    private static final int MAX_RETRIES = 9;
    private static final int RETRY_DELAY = 2000;

    /**
     *  token authenticate:
     *  takes the url of the API to get the authentication token using access keys
     *
     * @param getTokenUrl getTokenUrl
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param projectId projectId
     * @return {@link String}
     * @see String
     */
    public static String TokenAuthenticate(String getTokenUrl, String acyAccessKey, String acySecretKey, String projectId){
        // Java method to return the access token for Accyourate's API
        String token = null;
        int attempt = 0;
        while (attempt < MAX_RETRIES) {
            try{
                String base64Credentials = java.util.Base64.getEncoder().encodeToString(("accyourate" + ":" + "accyourate").getBytes());
                HttpResponse response = Unirest.get(getTokenUrl)
                        .header("acy_accesskey", acyAccessKey)
                        .header("acy_secretkey", acySecretKey)
                        .header("acy_project", projectId)
                        .header("Authorization", "Basic " + base64Credentials)
                        .asJson();

                if (response.getStatus() == 200) {
                    return response.getBody().getObject().getString("WM_AUTH_TOKEN");
                }

            } catch (Exception e){
                throw new RuntimeException(e);
            }

            attempt++;

            try {
                Thread.sleep(RETRY_DELAY);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    /**
     * get user from email and password:
     * returns the user from email and password using a call to an API
     *
     * @param getTokenUrl getTokenUrl
     * @param getCheckUserEmailValidityUrl getCheckUserEmailValidityUrl
     * @param username username
     * @param password password
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     * @return {@link JsonNode}
     * @see JsonNode
     */
    public static JsonNode getUserFromEmailAndPassword(String getTokenUrl, String getCheckUserEmailValidityUrl, String username, String password, String acyAccessKey, String acySecretKey, String acyProject){
        // Java method to return USER from Accyourate API

        JsonNode userObject = null;
        try {
            String token = TokenAuthenticate(getTokenUrl, acyAccessKey, acySecretKey, acyProject);
            HttpResponse response = Unirest.get(getCheckUserEmailValidityUrl + username)
                    .header("acy_accesskey", acyAccessKey)
                    .header("acy_secretkey", acySecretKey)
                    .header("acy_project", acyProject)
                    .header("wm_auth_token", token)
                    .queryString("EMAIL", username)
                    .queryString("PASSWORD", password)
                    .asJson();

            userObject = response.getBody();

            return userObject;
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * get user from email
     *
     * @param getTokenUrl getTokenUrl
     * @param getUserUrl getUserUrl
     * @param username username
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     * @return {@link JsonNode}
     * @see JsonNode
     */
    public static JSONObject getUserFromUsername(String getTokenUrl, String getUserUrl, String username, String acyAccessKey, String acySecretKey, String acyProject){
        // Java method to return USER from Accyourate API

        JsonNode responseObject = null;
        JSONObject userObject = new JSONObject();

        try {
            BuildUserObject(getTokenUrl, getUserUrl, username, acyAccessKey, acySecretKey, acyProject, userObject);

            return userObject;

        } catch (Exception e) {

            try {
                BuildUserObject(getTokenUrl, getUserUrl, StringEncrypter.encryptMD5(username), acyAccessKey, acySecretKey, acyProject, userObject);

                return userObject;
            } catch (Exception exc) {
                String mailUrl = getUserUrl.replace("username", "email");
                String mail = username.toLowerCase();
                try {
                    BuildUserObject(getTokenUrl, mailUrl, mail, acyAccessKey, acySecretKey, acyProject, userObject);

                    return userObject;

                } catch (Exception e2) {

                    try {
                        String[] mails = mail.split("@");
                        mail = StringEncrypter.encryptMD5(mails[0]).replaceAll("[$\\\\/]", "") + "@" + mails[1];
                        BuildUserObject(getTokenUrl, mailUrl, mail, acyAccessKey, acySecretKey, acyProject, userObject);

                        return userObject;
                    } catch (Exception exc2) {
                        throw new RuntimeException("Username or password are incorrect");
                    }
                }
            }
        }
    }

    private static void BuildUserObject(String getTokenUrl, String getUserUrl, String field, String acyAccessKey, String acySecretKey, String acyProject, JSONObject userObject) {
        JsonNode responseObject;
        String token = TokenAuthenticate(getTokenUrl, acyAccessKey, acySecretKey, acyProject);

        HttpResponse response = Unirest.get(getUserUrl + field)
                .header("acy_accesskey", acyAccessKey)
                .header("acy_secretkey", acySecretKey)
                .header("acy_project", acyProject)
                .header("wm_auth_token", token)
                .asJson();

        responseObject = response.getBody();

        userObject.put("access_token", token);
        userObject.put("id", responseObject.getObject().getString("id"));
        userObject.put("email", responseObject.getObject().getString("username"));
        userObject.put("username", responseObject.getObject().getString("username"));
        userObject.put("status", responseObject.getObject().getString("status"));

        try{
            userObject.put("password", responseObject.getObject().getString("password"));
        } catch (Exception exc){
            // user probably from Google login does not have a psw, return empty psw
            userObject.put("password","");
        }
    }

    /**
     * Get the Project User using the phone number
     *
     * @param getTokenUrl getTokenUrl
     * @param getUserUrl getUserUrl
     * @param phone phone
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     * @return {@link JSONObject}
     * @see JSONObject
     */
    public static JSONObject getUserFromPhone(String getTokenUrl, String getUserUrl, String phone, String acyAccessKey, String acySecretKey, String acyProject){
        JsonNode responseObject = null;
        JSONObject userObject = new JSONObject();

        try {
            BuildUserObject(getTokenUrl, getUserUrl, phone, acyAccessKey, acySecretKey, acyProject, userObject);

            return userObject;

        } catch (Exception e) {

            try {
                BuildUserObject(getTokenUrl, getUserUrl, StringEncrypter.encryptMD5(phone), acyAccessKey, acySecretKey, acyProject, userObject);

                return userObject;
            } catch (Exception exc) {
                throw new RuntimeException("Invalid code or phone received");
            }
        }
    }

    /**
     * get user from provider and uuid
     *
     * @param getTokenUrl getTokenUrl
     * @param getGoogleAccessUrl getGoogleAccessUrl
     * @param provider provider
     * @param uuid uuid
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     * @return {@link JsonNode}
     * @see JsonNode
     */
    public static JSONObject getUserFromProviderAndUuid(String getTokenUrl, String getGoogleAccessUrl, String provider, String uuid, String acyAccessKey, String acySecretKey, String acyProject){
        // Java method to return USER from Accyourate API
        JsonNode responseObject = null;
        JSONObject userObject = new JSONObject();
        try {
            String token = TokenAuthenticate(getTokenUrl, acyAccessKey, acySecretKey, acyProject);

            HttpResponse response = Unirest.get(getGoogleAccessUrl)
                    .header("acy_accesskey", acyAccessKey)
                    .header("acy_secretkey", acySecretKey)
                    .header("acy_project", acyProject)
                    .header("wm_auth_token", token)
                    .queryString("provider", provider)
                    .queryString("uuid", uuid)
                    .asJson();
            responseObject = response.getBody();

            userObject.put("access_token", token);
            userObject.put("id", responseObject.getObject().getString("id"));
            userObject.put("email", responseObject.getObject().getString("username"));

            return userObject;
        } catch (Exception e){
            userObject = null;
            return  userObject;
        }
    }

    /**
     * get google token info
     *
     * @param googleToken googleToken
     * @return {@link JsonNode}
     * @see JsonNode
     */
    public static JsonNode getGoogleTokenInfo(String googleToken){
    // Java method to return USER from Accyourate API

        JsonNode tokenInfo = null;

        try {
            HttpResponse response = Unirest.get("https://oauth2.googleapis.com/tokeninfo")
                    .queryString("id_token", googleToken)
                    .asJson();
            tokenInfo = response.getBody();

            return tokenInfo;
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * get user roles
     *
     * @param token token
     * @param getCheckMandatorySurveysLink getCheckMandatorySurveysLink
     * @param getUserRoleUrl getUserRoleUrl
     * @param userId user ID
     * @param email user email
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     * @return {@link JsonNode}
     * @see JsonNode
     */
    public static List getUserRoles(String token, String getCheckMandatorySurveysLink, String getUserRoleUrl, Integer userId, String email, String acyAccessKey, String acySecretKey, String acyProject){
        // Java method to return all USER roles from Accyourate API
        try {

            // First check if user has signed all consensus
            // Boolean hasSignedConsensus = SecurityUtils.getIfUserHasAgreedMandatorySurveys(getCheckMandatorySurveysLink, userId, email, acyAccessKey,acySecretKey,acyProject);

            List roleList = new ArrayList<>();

                JsonNode responseObject = null;
                    HttpResponse response = Unirest.get(getUserRoleUrl)
                            .header("acy_accesskey", acyAccessKey)
                            .header("acy_secretkey", acySecretKey)
                            .header("acy_project", acyProject)
                            .header("wm_auth_token", token)
                            .queryString("USER_ID", userId)
                            .asJson();
                responseObject = response.getBody();

                JSONArray rolesObjectContent = responseObject.getObject().getJSONArray("content");

                for (int i = 0; i < rolesObjectContent.length(); i++) {
                    roleList.add(rolesObjectContent.getJSONObject(i).getString("role"));
                }

                /*
            if (!hasSignedConsensus) {
                 if(!roleList.contains("tester") && !roleList.contains("admin") && !roleList.contains("projects_admin")){
                     roleList.clear();
                 }
                 roleList.add("notInformed");
            }
            */

            return roleList;
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * @param token token
     * @param urlGetAcyKeys urlGetAcyKeys
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     * @return {@link JsonNode}
     * @see JsonNode
     */
    public static  JSONObject readAcyPrivateAndPublicKey(String token, String urlGetAcyKeys, String acyAccessKey, String acySecretKey, String acyProject){
        // Java method to get acy private and public key to sign the certificates
        JSONObject certs = new JSONObject();
        JsonNode responsePublicKeyObject;
        JsonNode responsePrivateKeyObject;

        try {
            // Get ACY Token
            // String token = TokenAuthenticate(getTokenUrl, acyAccessKey, acySecretKey, acyProject);

            // Get the private key
            HttpResponse responseProvateKey = Unirest.get(urlGetAcyKeys)
                    .header("acy_accesskey", acyAccessKey)
                    .header("acy_secretkey", acySecretKey)
                    .header("acy_project", acyProject)
                    .header("wm_auth_token", token)
                    .queryString("q", "key='ACY_PRIVATE_KEY'")
                    .asJson();

            responsePrivateKeyObject = responseProvateKey.getBody();

            String privateKey  = responsePrivateKeyObject.getObject().getJSONArray("content").getJSONObject(0).getString("value");
            certs.put("ACY_PRIVATE_KEY", privateKey);

            // Get the public key
            HttpResponse responsePublicKey = Unirest.get(urlGetAcyKeys)
                    .header("acy_accesskey", acyAccessKey)
                    .header("acy_secretkey", acySecretKey)
                    .header("acy_project", acyProject)
                    .header("wm_auth_token", token)
                    .queryString("q", "key='ACY_PUBLIC_KEY'")
                    .asJson();
            responsePublicKeyObject = responsePublicKey.getBody();
            String publicKey  = responsePublicKeyObject.getObject().getJSONArray("content").getJSONObject(0).getString("value");
            certs.put("ACY_PUBLIC_KEY", publicKey);

            return certs;
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * update user private certificate
     *
     * @param token token
     * @param token token
     * @param getUpdateUserCertUrl getUpdateUserCertUrl
     * @param privateCertificate privateCertificate
     * @param userId userId
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     */
    public static void updateUserPrivateCertificate(String token, String getUpdateUserCertUrl, String privateCertificate, Integer userId, String acyAccessKey, String acySecretKey, String acyProject){
        // Java method to return all USER roles from Accyourate API

        // Get ACY Token
        // String token = TokenAuthenticate(getTokenUrl, acyAccessKey, acySecretKey, acyProject);

        JsonNode userObject = null;
        try {
            // Create JSON object which will be sent in the request's body
            JSONObject object = new JSONObject();

            HttpResponse response = Unirest.put(getUpdateUserCertUrl)
                    .header("Content-Type", "application/json")
                    .header("acy_accesskey", acyAccessKey)
                    .header("acy_secretkey", acySecretKey)
                    .header("acy_project", acyProject)
                    .header("wm_auth_token", token)
                    .body(object)
                    .asJson();

        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * create google user
     *
     * @param googleUserObject googleUserObject
     * @param getTokenUrl getTokenUrl
     * @param getCreateUserUrl getCreateUserUrl
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     */
    public static void createGoogleUser(JSONObject googleUserObject, String getTokenUrl, String addStandardProject, String getCreateUserUrl, String acyAccessKey, String acySecretKey, String acyProject){
        // Java method to return all USER roles from Accyourate API

        // Get ACY Token
        String token = TokenAuthenticate(getTokenUrl, acyAccessKey, acySecretKey, acyProject);

        try {
            HttpResponse response = Unirest.post(getCreateUserUrl)
                    .header("Content-Type", "application/json")
                    .header("acy_accesskey", acyAccessKey)
                    .header("acy_secretkey", acySecretKey)
                    .header("acy_project", acyProject)
                    .header("wm_auth_token", token)
                    .body(googleUserObject)
                    .asJson();

            if (!Objects.equals(addStandardProject, "")) {
                Unirest.post(addStandardProject)
                        .queryString("userId",response.getBody().getObject().get("id"))
                        .asString();
            }

        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }



    /**
     * @deprecated @since 1.1.52
     * create user secret
     * return a secret string
     *
     * @param userId userId
     * @param accessToken accessToken
     * @param getUserSecretUrl getUserSecretUrl
     * @param acyAccessKey acyAccessKey
     * @param acySecretKey acySecretKey
     * @param acyProject acyProject
     * @return {@link String}
     * @see String
     */
    public static String createUserSecret(Integer userId, String accessToken, String getUserSecretUrl, String acyAccessKey, String acySecretKey, String acyProject){
        // Java method to return all USER roles from Accyourate API

        // generare stringa random (segreto da firmare)
        String secret = UUID.randomUUID().toString();

        JSONObject bodyUserSecret = new JSONObject();
        bodyUserSecret.put("userId", userId);
        bodyUserSecret.put("secret", secret);

        try {
            HttpResponse response = Unirest.post(getUserSecretUrl)
                    .header("Content-Type", "application/json")
                    .header("acy_accesskey", acyAccessKey)
                    .header("acy_secretkey", acySecretKey)
                    .header("acy_project", acyProject)
                    .header("wm_auth_token", accessToken)
                    .body(bodyUserSecret)
                    .asJson();

            return secret;
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * Method to check if a user has or not
     *
     * @param getCheckMandatorySurveysLink getCheckMandatorySurveysLink
     * @param userId userId
     * @param email email
     * @param acy_accesskey acy_accesskey
     * @param acy_secretkey acy_secretkey
     * @param acy_project acy_project
     * @return {@link JSONObject} -> UserObject with no access_token, this kind of user does not need any roles
     * @see JSONObject
     */
    public static Boolean getIfUserHasAgreedMandatorySurveys(String getCheckMandatorySurveysLink, Integer userId, String email, String acy_accesskey, String acy_secretkey, String acy_project) {

        JsonNode responseBody;

        Integer status = 0;

        HttpResponse response = Unirest
                .get(getCheckMandatorySurveysLink)
                .header("acy_accesskey", acy_accesskey)
                .header("acy_secretkey", acy_secretkey)
                .header("acy_project", acy_project)
                .basicAuth("accyourate", "accyourate")
                .queryString("USER_ID", userId)
                .queryString("USER_EMAIL", email)
                .asJson();

        responseBody = response.getBody();

        try{
            status = responseBody.getObject().getJSONArray("content").getJSONObject(0).getInt("allPassed");
        } catch (Exception Exc){
        }

        return status !=0;
    }


    /**
     * Method to validate API Keys
     *
     * @param getTokenUrl getTokenUrl
     * @param acy_accesskey acy_accesskey
     * @param acy_secretkey acy_secretkey
     * @param acy_project acy_project
     * @return {@link JSONObject} -> UserObject with no access_token, this kind of user does not need any roles
     * @see JSONObject
     */
    public static JsonNode isAPIKeysValid(String getTokenUrl, String acy_accesskey, String acy_secretkey, String acy_project) {
        HttpResponse response = Unirest
                .get(getTokenUrl.replace("token", "info"))
                .header("acy_accesskey", acy_accesskey)
                .header("acy_secretkey", acy_secretkey)
                .header("acy_project", acy_project)
                .header("Authorization", "Basic YWNjeW91cmF0ZTphY2N5b3VyYXRl")
                .basicAuth("accyourate", "accyourate")
                .asJson();
        // Unirest.config().reset();
        if (response.getStatus() == 200) {
            return response.getBody();
        } else {

            return null;
        }
    }

    /**
     * gets the user from an Apple refresh token
     *
     * @param clientId clientId
     * @param clientSecret clientSecret
     * @param refreshToken refreshToken
     * @return {@link JSONObject}
     * @see JSONObject
     */
    public static JSONObject appleRefreshAuthentication(String clientId, String clientSecret, String refreshToken) {
        // Step 1: Exchange authorization code for access token
        HttpResponse tokenResponse = Unirest.post(StaticParams.APPLE_TOKEN_URL)
                .field("client_id", clientId)
                .field("client_secret", clientSecret)
                .field("refresh_token", refreshToken)
                .field("grant_type", "refresh_token")
                .asJson();

        JSONObject tokenBody = tokenResponse.getBody().getObject();

        try {
            // Extract access token and ID token from response
            String idToken = tokenBody.getString("id_token");
            return checkAppleAuthorization(idToken);
        } catch (Exception e) {
            return null;
        }

    }

    /**
     * gets the user from an Apple authentication code
     *
     * @param clientId clientId
     * @param clientSecret clientSecret
     * @param authCode authCode
     * @return {@link JSONObject}
     * @see JSONObject
     */
    public static JSONObject appleCodeAuthentication(String clientId, String clientSecret, String authCode) {
        // Step 1: Exchange authorization code for access token
        HttpResponse tokenResponse = Unirest.post(StaticParams.APPLE_TOKEN_URL)
                .field("client_id", clientId)
                .field("client_secret", clientSecret)
                .field("code", authCode)
                .field("redirect_uri", StaticParams.REDIRECT_URI)
                .field("grant_type", "authorization_code")
                .asJson();

        JSONObject tokenBody = tokenResponse.getBody().getObject();

        // Extract access token and ID token from response
        String idToken = tokenBody.getString("id_token");

        return checkAppleAuthorization(idToken);
    }

    /**
     * gets the user from a idToken
     *
     * @param idToken idToken
     * @return {@link JSONObject}
     * @see JSONObject
     */
    public static JSONObject checkAppleAuthorization(String idToken) {

        HttpResponse keysResponse = Unirest.get(StaticParams.APPLE_KEYS_URL)
                .asJson();

        try {

            String jwtKid = getJwtKeyId(idToken);

            String correctE = null;
            String correctKey = null;
            for (int i = 0; i < 3; i++) {
                if (keysResponse.getBody().getObject().getJSONArray("keys").getJSONObject(i).getString("kid").equals(jwtKid)) {
                    correctKey = keysResponse.getBody().getObject().getJSONArray("keys").getJSONObject(i).getString("n");
                    correctE = keysResponse.getBody().getObject().getJSONArray("keys").getJSONObject(i).getString("e");
                    break;
                }
            }
            if (correctKey == null) {
                throw new CertificateException("No Apple key found. Invalid token");
            }

            byte[] e = Base64.getUrlDecoder().decode(correctE);
            byte[] n = Base64.getUrlDecoder().decode(correctKey);

            BigInteger exponent = new BigInteger(1, e);
            BigInteger modulus = new BigInteger(1, n);

            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(modulus, exponent);
            PublicKey myPublicKey = keyFactory.generatePublic(publicKeySpec);

            Jws claimsJws = Jwts.parser()
                    .setSigningKey(myPublicKey)
                    .parseClaimsJws(idToken);

            // Extract user information from the JWT claims
            Claims claims = claimsJws.getBody();

            JSONObject userObject = new JSONObject();

            userObject.put("uuid", claims.getSubject());
            userObject.put("email", claims.get("email", String.class));
            userObject.put("name", claims.get("name", String.class));

            return userObject;

        } catch (Exception e) {
            System.err.println("Error occurred: " + e.getMessage());
        }
        return null;
    }

    /**
     * gets the jwt key id from an apple id token
     *
     * @param staticToken staticToken
     * @return {@link String}
     * @see String
     */
    public static String getJwtKeyId(String staticToken) {
        String[] jwtParts = staticToken.split("\\.");
        if (jwtParts.length < 2) {
            throw new IllegalArgumentException("Invalid JWT format: " + staticToken);
        }

        // Extract the header part (first part)
        String jwtHeader = jwtParts[0];

        // Decode the JWT header from Base64 URL encoding
        byte[] decodedHeader = Base64.getDecoder().decode(jwtHeader.getBytes());

        // Convert the decoded header bytes to a string
        String decodedHeaderString = new String(decodedHeader);

        // Parse the decoded header string into a JSON object
        JSONObject headerJson = new JSONObject(decodedHeaderString);

        // Extract the 'kid' (Key ID) from the JSON object
        return headerJson.getString("kid");
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy