package in.ajsd.jwt;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;

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


/** A verifier to verify JWT tokens. */
public class JwtVerifier {

  private final byte[] secret;

  public JwtVerifier(byte[] secret) {
    this.secret = secret;
  }

  public JwtVerifier(String urlSafeBase64Secret) {
    this(Util.base64Decode(urlSafeBase64Secret));
  }

  public JwtData verify(String token) throws JwtException {
    List<String> parts = Util.split(token);
    if (parts.size() != 3) {
      throw new JwtException("Malformed token");
    }
    JwtData jwt = createJwtData(parts.get(0), parts.get(1));
    verifySignature(Util.join(parts.get(0), parts.get(1)), parts.get(2),
        Algorithm.fromJwt(jwt.getAlgorithm()));

    return jwt;
  }

  public void verifySignature(String unsigned, String signature, Algorithm algorithm)
      throws JwtException {
    byte[] toVerify = {};
    try {
      SecretKeySpec key = new SecretKeySpec(secret, algorithm.getName());
      Mac hmac = Mac.getInstance(algorithm.getName());
      hmac.init(key);
      toVerify = hmac.doFinal(unsigned.getBytes());
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
      throw new JwtException(e);
    }
    if (!Arrays.equals(toVerify, Util.base64Decode(signature))) {
      throw new JwtException("Signatures do not match");
    }
  }

  public static JwtData verifyToken(byte[] secret, String token) throws JwtException {
    return new JwtVerifier(secret).verify(token);
  }

  public static JwtData verifyToken(String urlSafeBase64Secret, String token)
      throws JwtException {
    return new JwtVerifier(urlSafeBase64Secret).verify(token);
  }

  private static JwtData createJwtData(String headerBase64, String claimsBase64) {
    String headerJson = new String(Util.base64Decode(headerBase64));
    String claimsJson = new String(Util.base64Decode(claimsBase64));
    JwtData.Header header = Util.GSON.fromJson(headerJson, JwtData.Header.class);
    JwtData.Claims claims = Util.GSON.fromJson(claimsJson, JwtData.Claims.class);
    return JwtData.of(header, claims);
  }
}

@@ -11,24 +11,56 @@
 .ajsd.jwt;%0A%0A
+import org.joda.time.DateTime;%0A%0A
 import java.
@@ -81,32 +81,32 @@
 idKeyException;%0A
-
 import java.secu
@@ -898,16 +898,148 @@
 m()));%0A%0A
+    long now = DateTime.now().getMillis();%0A    verifyExpires(jwt.getExpires(), now);%0A    verifyNotBefore(jwt.getNotBefore(), now);%0A%0A
     retu
@@ -1570,24 +1570,24 @@
 nature))) %7B%0A
-
       throw 
@@ -1638,24 +1638,416 @@
 %0A    %7D%0A  %7D%0A%0A
+  public void verifyExpires(Long expires, long now) throws JwtException %7B%0A    if (expires != null && now %3C expires) %7B  // TODO: threshold%0A      throw new JwtException(%22Token has expired%22);%0A    %7D%0A  %7D%0A%0A  public void verifyNotBefore(Long notBefore, long now) throws JwtException %7B%0A    if (notBefore != null && now %3E notBefore) %7B%0A      throw new JwtException(%22Token isn't valid yet%22);%0A    %7D%0A  %7D%0A%0A
   public sta

add verification for exp,nbf