org.openwms.client.security.TokenUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.openwms.client.security.TokenUtils.java

Source

/*
 * openwms.org, the Open Warehouse Management System.
 * Copyright (C) 2014 Heiko Scherrer
 *
 * This file is part of openwms.org.
 *
 * openwms.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * openwms.org 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software. If not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.openwms.client.security;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.springframework.security.core.token.Sha512DigestUtils;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * A TokenUtils is an utility class that creates and validates authentication
 * tokens from UserDetails.
 * 
 * @author <a href="mailto:scherrer@openwms.org">Heiko Scherrer</a>
 * @version $Revision: $
 * @since 0.1
 */
public class TokenUtils {

    private static final String MAGIC_KEY = "spicy";

    /**
     * Create a new authentication token from the given username with an
     * expiration period of one hour.
     * 
     * @param userDetails
     *            From where the username is taken
     * @return Token as colon concatenated String
     */
    public static String createToken(UserDetails userDetails) {
        long expires = System.currentTimeMillis() + 1000L * 60 * 60;
        StringBuilder tokenBuilder = new StringBuilder();
        tokenBuilder.append(userDetails.getUsername()).append(":");
        tokenBuilder.append(expires).append(":");
        tokenBuilder.append(TokenUtils.computeSignature(userDetails, expires));
        return tokenBuilder.toString();
    }

    /**
     * Concatenate credentials with <code>expires</code>, add a salt and hash
     * this String.
     * 
     * @param userDetails
     *            Where to take the credentials from
     * @param expires
     *            Expiration lease
     * @return The hashed String
     */
    public static String computeSignature(UserDetails userDetails, long expires) {
        StringBuilder signatureBuilder = new StringBuilder();
        signatureBuilder.append(userDetails.getUsername());
        signatureBuilder.append(":");
        signatureBuilder.append(expires);
        signatureBuilder.append(":");
        signatureBuilder.append(userDetails.getPassword());
        signatureBuilder.append(":");
        signatureBuilder.append(TokenUtils.MAGIC_KEY);
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("No MD5 algorithm found on platform!");
        }
        return new String(Sha512DigestUtils.shaHex(digest.digest(signatureBuilder.toString().getBytes())));
    }

    /**
     * Split token at colons and return the first part as username.
     * 
     * @param authenticationToken
     *            The token
     * @return The username or <code>null</code>
     */
    public static String getUserNameFromToken(String authenticationToken) {
        if (null == authenticationToken) {
            return null;
        }
        String[] parts = authenticationToken.split(":");
        return parts[0];
    }

    /**
     * Validate <code>authenticationToken</code> if expired and its content.
     * 
     * @param authenticationToken
     *            The token
     * @param userDetails
     *            To be used for content comparison
     * @return <code>true</code> is valid, otherwise <code>false</code>
     */
    public static boolean validateToken(String authenticationToken, UserDetails userDetails) {
        String[] parts = authenticationToken.split(":");
        long expires = Long.parseLong(parts[1]);
        String signature = parts[2];
        if (expires < System.currentTimeMillis()) {
            return false;
        }
        return signature.equals(TokenUtils.computeSignature(userDetails, expires));
    }
}