SecurityServiceImpl.java

package no.ntnu.idatt2105.l4.demo.service;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Service;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * This is a simple implementation for dealing with JWTs.
 *
 * All it really does, is show an implementation for how to create a JWT,
 * and how to get a claim (the subject), from an already exists JWT.
 *
 * This implementation should be more or less directly applicable for
 * your needs (slight expansion might be needed).
 */
@Service
public class SecurityServiceImpl implements SecurityService {

    public static final String secretKey= "4C8kum4LxyKWYLM78sKdXrzbBjDCFyfX";

    private static List<String> tokens = new ArrayList<String>(); // JWTs are just strings, in the end


    /**
     * Creates a JWT token with one claim: the subject. The signs it and returns it.
     *
     * @param subject Basically, whatever you decide to use as user id.
     * @param ttlMillis how long the JWT will last before it needs to be renewed (or becomes invalid).
     * @return a signed JWT.
     */
    @Override
    public String createToken(String subject, long ttlMillis) {

        if (ttlMillis <= 0) {
            throw new RuntimeException("Expiry time must be greater than Zero :["+ttlMillis+"] ");
        }

        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // The JWT signature algorithm we will be using to sign the token
        long nowMillis = System.currentTimeMillis();

        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secretKey);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        JwtBuilder builder = Jwts.builder()
                .setSubject(subject)
                .signWith(signatureAlgorithm, signingKey);

//        builder.setExpiration(new Date(nowMillis + ttlMillis));
        builder.setExpiration(new Date(nowMillis + (1000*60*15)));

        // At this point, we can add the token to a List (either in this class, or in a singleton)
        // which we can then check against when the aspect is run (see TokenRequiredAspect).
        String token = builder.compact();
        tokens.add(token);


        return token;
    }


    /**
     * The subject in JWT parlance is, practically speaking, the same thing as the user id.
     *
     * @param token the JWT token
     * @return the user ID (or whatever one has decided to refer to as "subject")
     */
    @Override
    public String getSubject(String token) {

        Claims claims = Jwts.parser()
                .setSigningKey(DatatypeConverter.parseBase64Binary(secretKey))
                .parseClaimsJws(token).getBody();

        return claims.getSubject();
    }


    /**
     * We simply put all of our tokens in a list, and check to see if the token is in it.
     *
     * @param token the JWT
     * @return true, if the token is in the list of valid tokens, false otherwise.
     */
    @Override
    public boolean validToken(String token) {
        return this.tokens.contains(token);
    }

}