edu.uniandes.ecos.codeaholics.config.AuthenticationJWT.java Source code

Java tutorial

Introduction

Here is the source code for edu.uniandes.ecos.codeaholics.config.AuthenticationJWT.java

Source

/** Copyright or License
 *
 */

package edu.uniandes.ecos.codeaholics.config;

import java.util.ArrayList;
import java.util.Date;

//import java.util.HashMap;
//import java.util.Map;
//import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bson.Document;

import com.mongodb.ErrorCategory;
import com.mongodb.MongoWriteException;

import edu.uniandes.ecos.codeaholics.exceptions.AuthenticationException.SessionAlreadyExistsException;
import edu.uniandes.ecos.codeaholics.exceptions.AuthenticationException.WrongUserOrPasswordException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

/**
 * Package: edu.uniandes.ecos.codeaholics.config
 *
 * Class: AuthenticationJWT AuthenticationJWT.java
 * 
 * Original Author: @author AOSORIO
 * 
 * Description: Authentication class using JWT
 * 
 * Implementation: uses jsonwebtoken library
 *
 * Created: Aug 12, 2016 6:36:05 PM
 * 
 */
public class AuthenticationJWT implements IAuthenticationSvc {

    // Atributos
    private final static Logger log = LogManager.getLogger(AuthenticationJWT.class);

    private static Object token;

    /*
     * (non-Javadoc)
     * 
     * @see
     * edu.uniandes.ecos.codeaholics.config.IAuthenticationSvc#doAuthentication(
     * java.lang.String, java.lang.String, java.lang.String)
     */
    @Override
    public boolean doAuthentication(String pEmail, String pPwd, String pProfile)
            throws WrongUserOrPasswordException {

        boolean isAuthenticated = false;
        log.info("Verifying user data...");
        Document user = new Document();
        user.append("email", pEmail);

        ArrayList<Document> documents = DataBaseUtil.find(user, pProfile);

        // 1. check if user exists in the DB
        if (documents.isEmpty()) {

            log.info("Usuario no existe");
            throw new WrongUserOrPasswordException("El usuario que ingresaste no existe", "101");
        } else {

            // 2. Create new session
            try {

                String salt = documents.get(0).get("salt").toString();
                String[] hash = GeneralUtil.getHash(pPwd, salt);
                user.append("password", hash[1]);

                String functioryRol = ValidateUser(user, pProfile);

                log.info(pEmail + " has passwd checked. go ahead and create session with token.");

                createSession(pEmail, functioryRol, salt);

                log.info("New session created with token: " + token.toString());

                isAuthenticated = true;

            } catch (WrongUserOrPasswordException valEx) {

                token = "{}";
                log.info("Clave equivocada");
                isAuthenticated = false;
                throw valEx;
            }

        }

        return isAuthenticated;

    }

    private String ValidateUser(Document user, String pProfile) throws WrongUserOrPasswordException {
        String rol = "";
        ArrayList<Document> results = DataBaseUtil.find(user, pProfile);

        if (results.isEmpty()) {
            throw new WrongUserOrPasswordException("La clave que ingresaste es incorrecta", "103");
        } else {
            rol = results.get(0).get("userProfile").toString();
        }
        return rol;
    }

    /*
     * (non-Javadoc)
     * 
     * @see edu.uniandes.ecos.codeaholics.config.IAuthenticationSvc#getAnswer()
     */
    @Override
    public Object getAnswer() {
        return token;
    }

    /** This is the createJWT for citizen
     * @param id
     * @param issuer
     * @param subject
     * @param ttlMillis
     * @return
     */
    private static String createJWT(String pId, String pProfile, String pSalt, String pName, String pLast) {

        // The JWT signature algorithm we will be using to sign the token
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        long expMillis = nowMillis + Constants.TOKEN_LIFETIME;
        Date exp = new Date(expMillis);

        log.debug(pSalt);

        StringBuilder subject = new StringBuilder();
        subject.append(pName);
        subject.append(",");
        subject.append(pLast);

        // Let's set the JWT Claims
        JwtBuilder builder = Jwts.builder().setId(pId);
        builder.setIssuedAt(now);
        builder.setSubject(subject.toString());
        builder.setIssuer(Constants.TOKEN_ISSUER);
        builder.signWith(signatureAlgorithm, pSalt);
        builder.setExpiration(exp);
        builder.setAudience(pProfile);

        // Builds the JWT and serializes it to a compact, URL-safe string
        return builder.compact();

    }

    /** This is the create JWT for functionary
     * @param id
     * @param issuer
     * @param subject
     * @param ttlMillis
     * @return
     */
    private static String createJWT(String pId, String pProfile, String pSalt, String pName, String pLast,
            String pMayorality) {

        // The JWT signature algorithm we will be using to sign the token
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        long expMillis = nowMillis + Constants.TOKEN_LIFETIME;
        Date exp = new Date(expMillis);

        log.debug(pSalt);

        StringBuilder subject = new StringBuilder();
        subject.append(pName);
        subject.append(",");
        subject.append(pLast);
        subject.append(",");
        subject.append(pMayorality);

        // Let's set the JWT Claims
        JwtBuilder builder = Jwts.builder().setId(pId);
        builder.setIssuedAt(now);
        builder.setSubject(subject.toString());
        builder.setIssuer(Constants.TOKEN_ISSUER);
        builder.signWith(signatureAlgorithm, pSalt);
        builder.setExpiration(exp);
        builder.setAudience(pProfile);

        //Map<String, Object> customClaims = new HashMap<String, Object>();
        //customClaims.put("mayorality", pMayorality);
        //builder.setClaims(customClaims);

        // Builds the JWT and serializes it to a compact, URL-safe string
        return builder.compact();

    }

    /**
     * * Crea una sesion para un usuario dado su email.
     * 
     * @param pEmail
     *            correo del usuario al que se le crea la sesion
     * @param pUserProfile
     *            perfil del usuario citizen, functionary, etc
     */
    private static void createSession(String pEmail, String pProfile, String pSalt) {

        if (pProfile.equals(Constants.CITIZEN_USER_PROFILE)) {

            //TODO: this is not safe
            Document filter = new Document();
            filter.append("email", pEmail);
            ArrayList<Document> citizen = DataBaseUtil.find(filter, Constants.CITIZEN_COLLECTION);

            String citizenName = citizen.get(0).get("name").toString();
            String citizenLast = citizen.get(0).get("lastName1").toString();

            token = createJWT(pEmail, pProfile, pSalt, citizenName, citizenLast);

        } else {

            log.info("User is functionary: creating token for functionary");
            //TODO: this is not safe
            Document filter = new Document();
            filter.append("email", pEmail);
            ArrayList<Document> functionary = DataBaseUtil.find(filter, Constants.FUNCTIONARY_COLLECTION);

            String citizenName = functionary.get(0).get("name").toString();
            String citizenLast = functionary.get(0).get("lastName1").toString();
            String citizenMayoralty = functionary.get(0).get("mayoralty").toString();

            token = createJWT(pEmail, pProfile, pSalt, citizenName, citizenLast, citizenMayoralty);

        }

        Document session = new Document();
        session.append("email", pEmail);
        session.append("user-profile", pProfile);
        session.append("token", token);
        session.append("salt", pSalt);
        log.info("Creating Session...");

        try {

            hasSession(pEmail);

            DataBaseUtil.save(session, Constants.SESSION_COLLECTION);

        } catch (SessionAlreadyExistsException ssEx) {

            log.info(ssEx.getMessage() + " : " + pEmail);
            closeSession(pEmail);
            DataBaseUtil.save(session, Constants.SESSION_COLLECTION);

        } catch (MongoWriteException e) {

            if (e.getError().getCategory().equals(ErrorCategory.DUPLICATE_KEY)) {
                log.info("Already exist session for user: " + pEmail);
            }
            throw e;
        }
    }

    /**
     * * Cierra la sesion de un usuario dado su email.
     *
     * @param pEmail
     *            correo del ususario al que se le crea la sesion
     */
    public static void closeSession(String pEmail) {
        Document session = new Document();
        session.append("email", pEmail);
        log.info("Closing Session...");
        DataBaseUtil.delete(session, Constants.SESSION_COLLECTION);
    }

    public static void hasSession(String pEmail) throws SessionAlreadyExistsException {

        Document prevSession = new Document();
        prevSession.append("email", pEmail);
        ArrayList<Document> documents = DataBaseUtil.find(prevSession, Constants.SESSION_COLLECTION);

        if (!documents.isEmpty()) {
            throw new SessionAlreadyExistsException("Session for this user already exists", "105");
        }

    }

}