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

bluecrystal.service.jwt.AppJWTSigner Maven / Gradle / Ivy

There is a newer version: 1.16.0
Show newest version
package bluecrystal.service.jwt;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import com.auth0.jwt.JWTAlgorithmException;
import com.auth0.jwt.internal.org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class AppJWTSigner {
	private byte[] secret;
	private PrivateKey privateKey;

	// Default algorithm HMAC SHA-256 ("HS256")
	protected final static AppAlgorithm DEFAULT_ALGORITHM = AppAlgorithm.HS256;

    public AppJWTSigner(final String secret) {
        this.secret =  secret.getBytes();
    }

    public AppJWTSigner(final byte[] secret) {
        this.secret =  secret;
    }
	
        
	public AppJWTSigner(PrivateKey privateKey) {
		super();
		this.privateKey = privateKey;
	}

	public String sign(final Map claims, final AppAlgorithm algorithm) throws Exception {
		String preSign = preSign(claims, algorithm);
		byte[] preEncoded = signByAlg(preSign, algorithm);
		String signed = postSign(claims, preEncoded, preSign);
		return signed;
	}    
    
	public String preSign(final Map claims, final AppAlgorithm alg) {
		final AppAlgorithm algorithm = (alg != null) ? alg : DEFAULT_ALGORITHM;
		final List segments = new ArrayList<>();
		try {
			segments.add(encodedHeader(algorithm));
			segments.add(encodedPayload(claims));
			String joinPreSign = join(segments, ".");

			return joinPreSign;
		} catch (Exception e) {
			throw new RuntimeException(e.getCause());
		}
	}

	public String postSign(
			final Map claims, 
			byte[] preEncoded, //			final AppAlgorithm alg, 
			String preSign) {
//		final AppAlgorithm algorithm = (alg != null) ? alg : DEFAULT_ALGORITHM;
		final List segments = new ArrayList<>();
		try {
//			byte[] preEncoded = signByAlg(preSign, algorithm);

			String post = postEncodedSignature(preEncoded);

//			segments.add(encodedSignature(preSign, algorithm));
			segments.add(preSign);
			segments.add(post);
			String joinPostSign = join(segments, ".");

			return joinPostSign;
		} catch (Exception e) {
			throw new RuntimeException(e.getCause());
		}
	}


//	public String postSign(final Map claims, final AppAlgorithm alg, String preSign) {
//		final AppAlgorithm algorithm = (alg != null) ? alg : DEFAULT_ALGORITHM;
//		final List segments = new ArrayList<>();
//		try {
//			byte[] preEncoded = signByAlg(preSign, algorithm);
//
//			String post = postEncodedSignature(preEncoded);
//
////			segments.add(encodedSignature(preSign, algorithm));
//			segments.add(preSign);
//			segments.add(post);
//			String joinPostSign = join(segments, ".");
//
//			return joinPostSign;
//		} catch (Exception e) {
//			throw new RuntimeException(e.getCause());
//		}
//	}

	
	
//	public String sign(final Map claims, final AppAlgorithm alg) {
//		final AppAlgorithm algorithm = (alg != null) ? alg : DEFAULT_ALGORITHM;
//		final List segments = new ArrayList<>();
//		try {
//			segments.add(encodedHeader(algorithm));
//			segments.add(encodedPayload(claims));
//			String joinPreSign = join(segments, ".");
//			segments.add(encodedSignature(joinPreSign, algorithm));
//			String joinPostSign = join(segments, ".");
//
//			return joinPostSign;
//		} catch (Exception e) {
//			throw new RuntimeException(e.getCause());
//		}
//	}
	
	
	
	
	/**
	 * Generate the header part of a JSON web token.
	 */
	private String encodedHeader(final AppAlgorithm algorithm) throws UnsupportedEncodingException {
		// Validate.notNull(algorithm);
		// create the header
		final ObjectNode header = JsonNodeFactory.instance.objectNode();
		header.put("typ", "JWT");
		header.put("alg", algorithm.name());
		return base64UrlEncode(header.toString().getBytes("UTF-8"));
	}

	/**
	 * Generate the JSON web token payload string from the claims.
	 *
	 * @param options
	 */
	private String encodedPayload(final Map _claims) throws IOException {
		final Map claims = new HashMap<>(_claims);
		// enforceStringOrURI(claims, "iss");
		// enforceStringOrURI(claims, "sub");
		// enforceStringOrURICollection(claims, "aud");
		// enforceIntDate(claims, "exp");
		// enforceIntDate(claims, "nbf");
		// enforceIntDate(claims, "iat");
		// enforceString(claims, "jti");
		// if (options != null) {
		// processPayloadOptions(claims, options);
		// }
		final String payload = new ObjectMapper().writeValueAsString(claims);
		return base64UrlEncode(payload.getBytes("UTF-8"));
	}

	private String base64UrlEncode(final byte[] str) {
		// Validate.notNull(str);
		return new String(Base64.encodeBase64URLSafe(str));
	}

	private String join(final List input, final String separator) {
		// Validate.notNull(input);
		// Validate.notNull(separator);
		return StringUtils.join(input.iterator(), separator);
	}

	byte[] signByAlg(final String signingInput, final AppAlgorithm algorithm)
			throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException,
			JWTAlgorithmException {
		// Validate.notNull(signingInput);
		// Validate.notNull(algorithm);
		switch (algorithm) {
		case HS256:
		case HS384:
		case HS512:
			return signHmac(algorithm, signingInput, secret);
		case RS256:
		case RS384:
		case RS512:
			return signRs(algorithm, signingInput, privateKey);
		default:
			throw new JWTAlgorithmException("Unsupported signing method");
		}
	}

	private String postEncodedSignature(byte[] preEncoded)
			throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException,
			JWTAlgorithmException {
			return base64UrlEncode(preEncoded);
		}

//	private String encodedSignature(final String signingInput, final AppAlgorithm algorithm) throws Exception {
//		byte[] preEncoded = signByAlg(signingInput, algorithm);
//		return postEncodedSignature(preEncoded);
//	}

	
//	private String encodedSignature(final String signingInput, final AppAlgorithm algorithm)
//			throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException,
//			JWTAlgorithmException {
//		// Validate.notNull(signingInput);
//		// Validate.notNull(algorithm);
//		switch (algorithm) {
//		case HS256:
//		case HS384:
//		case HS512:
//			return base64UrlEncode(signHmac(algorithm, signingInput, secret));
//		case RS256:
//		case RS384:
//		case RS512:
//			return base64UrlEncode(signRs(algorithm, signingInput, privateKey));
//		default:
//			throw new JWTAlgorithmException("Unsupported signing method");
//		}
//	}

	
	
	
	private static byte[] signHmac(final AppAlgorithm algorithm, final String msg, final byte[] secret)
			throws NoSuchAlgorithmException, InvalidKeyException {
		// Validate.notNull(algorithm);
		// Validate.notNull(msg);
		// Validate.notNull(secret);
		final Mac mac = Mac.getInstance(algorithm.getValue());
		mac.init(new SecretKeySpec(secret, algorithm.getValue()));
		return mac.doFinal(msg.getBytes());
	}

	private static byte[] signRs(final AppAlgorithm algorithm, final String msg, final PrivateKey privateKey)
			throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
//		Validate.notNull(algorithm);
//		Validate.notNull(msg);
//		Validate.notNull(privateKey);
		final byte[] messageBytes = msg.getBytes();
		final Signature signature = Signature.getInstance(algorithm.getValue(), "BC");
		signature.initSign(privateKey);
		signature.update(messageBytes);
		return signature.sign();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy