/*
  This example depends on the following jar files

  commons-codec.jar from http://commons.apache.org/proper/commons-codec/
  json-smart.jar from https://code.google.com/p/json-smart/
  nimbus-jose-jwt.jar from https://bitbucket.org/nimbusds/nimbus-jose-jwt/overview
  
  Because of this [1] issue in nimbus-jose-jwt, please make sure to use a 
  version >= 2.13.1 as Zendesk expects seconds in the iat parameter
  [1]: https://bitbucket.org/nimbusds/nimbus-jose-jwt/issue/35/jwtclaimsset-milliseconds-vs-seconds-issue
*/

package com.zendesk.login;

import java.util.Date;
import java.util.UUID;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;
import com.nimbusds.jose.util.*;
import com.nimbusds.jwt.*;

public class JWT extends HttpServlet {
  private static final String SHARED_KEY = "{my zendesk token}";
  private static final String SUBDOMAIN  = "{my zendesk subdomain}";

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException {

    // Given a user instance
    // Compose the JWT claims set
    JWTClaimsSet jwtClaims = new JWTClaimsSet();
    jwtClaims.setIssueTime(new Date());
    jwtClaims.setJWTID(UUID.randomUUID().toString());
    // jwtClaims.setCustomClaim("name", user.name);
    // jwtClaims.setCustomClaim("email", user.email);

    // Create JWS header with HS256 algorithm
    JWSHeader header = new JWSHeader(JWSAlgorithm.HS256);
    header.setContentType("text/plain");

    // Create JWS object
    JWSObject jwsObject = new JWSObject(header, new Payload(jwtClaims.toJSONObject()));

    // Create HMAC signer
    JWSSigner signer = new MACSigner(SHARED_KEY.getBytes());

    try {
      jwsObject.sign(signer);
    } catch(com.nimbusds.jose.JOSEException e) {
      System.err.println("Error signing JWT: " + e.getMessage());
      return;
    }

    // Serialise to JWT compact form
    String jwtString = jwsObject.serialize();

    String redirectUrl = "https://" + SUBDOMAIN + ".zendesk.com/access/jwt?jwt=" + jwtString;

    String returnTo = request.getParameter("return_to");
    if (returnTo != null) {
        redirectUrl += "&return_to=" + returnTo;
    }

    response.sendRedirect(redirectUrl);
  }
}

@@ -558,115 +558,263 @@
 ort 
-java.util.Date;%0Aimport java.util.UUID;%0A%0Aimport java.io.IOException;%0A%0Aimport javax.servlet.ServletException;
+com.nimbusds.jose.JWSAlgorithm;%0Aimport com.nimbusds.jose.JWSHeader;%0Aimport com.nimbusds.jose.JWSObject;%0Aimport com.nimbusds.jose.JWSSigner;%0Aimport com.nimbusds.jose.Payload;%0Aimport com.nimbusds.jose.crypto.MACSigner;%0Aimport com.nimbusds.jwt.JWTClaimsSet;%0A
 %0Aimp
@@ -835,29 +835,24 @@
 let.
-annotation.WebServlet
+ServletException
 ;%0Aim
@@ -985,103 +985,130 @@
 se;%0A
-%0A
 import 
-com.nimbusds.jose.*;%0Aimport com.nimbusds.jose.crypto.*;%0Aimport com.nimbusds.jose
+java.io.IOException;%0Aimport java.io.UnsupportedEncodingException;%0Aimport java.net.URLEncoder;%0Aimport java
 .util.
-*
+Date
 ;%0Aim
@@ -1116,26 +1116,22 @@
 ort 
-com.nimbusds.jwt.*
+java.util.UUID
 ;%0A%0Ap
@@ -2582,24 +2582,31 @@
 _to=%22 + 
+encode(
 returnTo
 ;%0A    %7D%0A
@@ -2597,16 +2597,17 @@
 returnTo
+)
 ;%0A    %7D%0A
@@ -2650,11 +2650,241 @@
 rl);%0A  %7D
+%0A%0A  private static String encode(String url) %7B%0A    try %7B%0A      return URLEncoder.encode(url, %22UTF-8%22);%0A    %7D catch (UnsupportedEncodingException e) %7B%0A      System.err.println(%22UTF-8 is not supported!%22);%0A      return url;%0A    %7D%0A  %7D
 %0A%7D%0A

Support for return_to param.