Skip to content

Instantly share code, notes, and snippets.

@csoma
Created February 14, 2015 01:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save csoma/a24f0e7b32f3faf387ee to your computer and use it in GitHub Desktop.
Save csoma/a24f0e7b32f3faf387ee to your computer and use it in GitHub Desktop.
Desk.com integration in scala
// Desk.com integration based on http://dev.desk.com/guides/sso/
// License: Public domain
import scala.util.parsing.json.JSONObject
import org.apache.commons.codec.binary.Base64
import java.util.Arrays
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.Date
import java.net.URLEncoder
import java.security.MessageDigest
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.Mac
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
/**
Create redirect URL for Desk.com "Private Access / Multipass SSO"
Usage:
val desk = new DeskDotCom("yoursite", "xxxx")
val url = desk.loginURL("test123", "john@example.com", "John Smith", "co12", "Example Inc")
redirect(url) // the url format returned: "https://yoursite.desk.com/..."
If you're using custom fields, they have to be created first in the admin console:
https://yoursite.desk.com/admin/case-management/customer-settings/custom-fields
Name=CompanyID key=companyid Type=Text
Name=Company key=company Type=text
*/
class DeskDotCom(siteKeyOrig: String, apiKey:String) {
protected val siteKey: String = siteKeyOrig.toLowerCase
def loginURL(custUid:String, custEmail:String, custName:String, custCompanyID:String="", custCompanyName:String=""): String = {
val salted: String = apiKey + siteKey
val md: MessageDigest = MessageDigest.getInstance("SHA1")
md.update(salted.getBytes("utf-8"))
val digest: Array[Byte] = md.digest()
val key: SecretKeySpec = new SecretKeySpec(Arrays.copyOfRange(digest, 0, 16), "AES")
val iv: Array[Byte] = new Array[Byte](16)
val random: SecureRandom = new SecureRandom()
random.nextBytes(iv)
val df: DateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ")
var userMap: Map[String, String] = Map()
userMap += ("uid"-> custUid)
userMap += ("expires" -> df.format(new Date(new Date().getTime() + 300000)))
userMap += ("customer_email" -> custEmail)
userMap += ("customer_name" -> custName)
if (!custCompanyID.isEmpty) userMap += ("customer_custom_companyid"-> custCompanyID)
if (!custCompanyName.isEmpty) userMap += ("customer_custom_company" -> custCompanyName)
val data = JSONObject( userMap ).toString()
val aes = Cipher.getInstance("AES/CBC/PKCS5Padding")
val ivSpec = new IvParameterSpec(iv)
aes.init(Cipher.ENCRYPT_MODE, key, ivSpec)
val encrypted: Array[Byte] = aes.doFinal(data.getBytes("utf-8"))
val combined: Array[Byte] = new Array(iv.length + encrypted.length)
System.arraycopy(iv, 0, combined, 0, iv.length)
System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length)
val multipass: Array[Byte] = Base64.encodeBase64(combined)
val apiKeyEnc: SecretKeySpec = new SecretKeySpec(apiKey.getBytes("utf-8"), "HmacSHA1")
val hmac: Mac = Mac.getInstance("HmacSHA1")
hmac.init(apiKeyEnc)
val rawHmac: Array[Byte] = hmac.doFinal(multipass)
val signature: Array[Byte] = Base64.encodeBase64(rawHmac)
val encodeType = "UTF-8"
val multipassString = URLEncoder.encode(new String(multipass), encodeType)
val signatureString = URLEncoder.encode(new String(signature), encodeType)
val url = "https://" + siteKey +
".desk.com/customer/authentication/multipass/callback?multipass=" +
multipassString + "&signature=" + signatureString
return url
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment