O núcleo do single sign-on é a tecnologia de token da web JSON (JWT), que permite que o Zendesk confie nas solicitações de entrada que recebe de seus sistemas. Para obter mais detalhes, consulte Configuração de single sign-on com JWT (Token da web JSON).
Não coloque o JWT diretamente na URL, pois as URLs podem ser expostas a hackers por meio de logs do servidor, do histórico do navegador e de intermediários de rede.
Para integrações de SSO com o Zendesk, um mecanismo do lado do servidor deve gerar o JWT e redirecionar o navegador do usuário para uma URL específica do Zendesk, passando o JWT como um parâmetro na cadeia de caracteres de consulta em vez do cabeçalho HTTP.
Um JWT normalmente consiste em três partes separadas por pontos finais. Cada parte tem uma finalidade diferente na estrutura do JWT: o cabeçalho, a carga e a assinatura.
Parte 1: cabeçalho de JWT
A primeira parte é o cabeçalho de JWT. Ele indica que isso é uma solicitação JWT, além do tipo de algoritmo de hash utilizado. Falaremos mais sobre isso posteriormente.
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
A grade descoberta é: essa parte e o restante dos dados foram codificados com base64. Essa não é uma criptografia de verdade, portanto, pode ser decodificada rapidamente pelas ferramentas abaixo:
- Ferramenta da Web: http://www.base64decode.org/
- Terminal: http://drewsymo.com/how-to/quick-and-simple-base64-encode-on-mac-osx-terminal/
A cadeia de caracteres tem essa aparência após a decodificação:
{"typ":"JWT",
"alg":"HS256"}
Você pode ver que a estrutura de JSON está presente, além de dois pares de chave/valor que efetivamente significam type: JWT
e Algorithm: HMAC SHA 256
: SHA 256 significa um algoritmo de criptografia de 256 bits, que foi criado pela Agência de Segurança Nacional dos Estados Unidos. Ele é uso para gerar a terceira parte, a assinatura, sobre a qual falaremos em breve.
Parte 2: conjunto de solicitações de JWT/carga
A segunda parte é consideravelmente maior porque contém a carga. Ela é conhecida como “conjunto de solicitações de JWT”.
eyJpYXQiOjEzNzIxMTMzMDUsImp0aSI6ODg4MzM2MjUzMTE5Ni4zMjYsIm5hbWUiOiJUZXN0IFVzZXIiLCJlbWFpbCI6InR1c2VyQGV4YW1wbGUub3JnIiwiZXh0ZXJuYWxfaWQiOiI1Njc4Iiwib3JnYW5pemF0aW9uIjoiQXBwbGUiLCJ0YWdzIjoidmlwX3VzZXIiLCJyZW1vdGVfcGhvdG9fdXJsIjoiaHR0cDovL21pdC56ZW5mcy5jb20vMjA2LzIwMTEvMDUvQmFybmFieV9NYXR0X2Nyb3BwZWQuanBnIiwibG9jYWxlX2lkIjoiOCJ9
Ela contém um carimbo de data/hora, um valor aleatório, um nome de usuário, um endereço de email, uma ID externa e algumas tags. Há ainda mais opções disponíveis. Novamente, realize a decodificação base64 para entender a carga. Separaremos as linhas para facilitar a compreensão.
{
"iat":1372113305,
"jti":8883362531196.326,
"name":"Test User",
"email":"tuser@example.org",
"external_id":"5678",
"organization":"Apple",
"tags":"vip_user",
"remote_photo_url":"http://mit.zenfs.com/206/2011/05/Barnaby_Matt_cropped.jpg",
"locale_id":"8"
}
Obrigatório
IAT
A primeira chave é iat, que significa emitido em. Ela é um carimbo de data/hora formatado em segundos desde 01 de janeiro de 1970, que é a representação UNIX padrão de tempo. O carimbo de data/hora deve ser um número inteiro (sem decimais) e estar em UTC. Ele também deve estar dentro de 3 minutos da hora atual quando o servidor da Zendesk receber a solicitação. Isso coloca um mecanismo de autodestruição em cada solicitação de autenticação remota, evitando que uma única solicitação seja usada mais de três minutos após a geração.
JTI
A segunda chave, jti, significa ID do token JSON. Ela é uma simples cadeia de caracteres aleatória. Ela deve ser suficientemente longa e aleatória para eliminar a possibilidade de ser utilizado novamente na conta. Se, por acidente ou acaso, ele for utilizado em outra solicitação de autenticação, a solicitação falhará. O objetivo dessa parte é ser uma chave descartável. Ao incluir um valor obrigatoriamente aleatório como esse, garantimos que as solicitações de autenticação sejam exclusivas. Isso evita a reutilização de uma URL de solicitação válida. Por exemplo, imagine que alguém instalou um malware em seu computador ou rede e começou a analisar seu tráfego. Eles podem ver todas as URLs visitadas. Se eles virem e pegarem a URL emitida ao entrar no Zendesk, podem usá-la para entrar como você em até 3 minutos sem essa chave de uso único.
Nome
A seguir, temos o nome completo do usuário com espaços. O que a Zendesk recebe aqui é definido como nome de usuário, mesmo se o nome já foi outro anteriormente.
O e-mail do usuário. O e-mail é sempre obrigatório. Ele é usado como identificador único do usuário, a menos que uma ID externa seja recebida*. Isso significa que, se pegarmos um email e uma ID externa, tentamos primeiro a correspondência da ID. Se encontrada, atualizados o usuário com o endereço de email especificado.
*Observação: se a opção “Permitir atualização das IDs externas” estiver ativada no Zendesk, continuaremos ignorando o email mesmo se uma ID externa for recebida. Se o email e a ID externa forem diferentes, alteramos a ID.
Opcional
ID externa
A ID externa é opcional e pode ser usada para identificar usuários no lugar do endereço de email (observado acima).
Organização
Você também pode passar um valor de organização para adicionar um usuário a uma organização. A organização nomeada deve existir e a correspondência de nome deve ser exata. Caso contrário, nenhuma ação será tomada.
Tags
A chave tags permite que você defina tags no usuário se conectando. A chave substitui as tags existentes no usuário pelas tags especificadas, portanto, use o recurso com cautela. Passar um parâmetro de tags em branco remove todas as tags de um usuário.
URL da foto remota
Você também pode passar um valor para remote_photo_url, que aceita uma URL contendo a foto, definindo essa foto como a foto de perfil do usuário.
Idioma
Você pode passar um valor para locale_id para definir e atualizar o idioma do usuário autenticado no Zendesk. O valor deve ser um número que corresponda ao idioma ativado no momento em seu Zendesk. Você pode encontrar as localidades usando o ponto de extremidade locales.json da nossa API: https://developer.zendesk.com/api-reference/ticketing/account-configuration/locales/#list-locales
Campos de usuário (não mostrados no exemplo)
Deve ser um objeto JSON que inclui os pares de valor-chave para cada valor e chave. A chave do campo pode ser encontrada ou definida na interface de Campos do usuário. Observe que apenas campos de usuário personalizados podem ser passados.
Por exemplo:
"user_fields": {"checked": false,"date_joined": "2013-08-14T00:00:00+00:00","region": "EMEA","text_field": null}
as caixas de seleção usam valores boolianos, códigos de datas como o exemplo acima, e as listas suspensas aceitam o nome da opção. Os campos de texto aceitam cadeias de caracteres.
Número de telefone (não mostrado no exemplo)
Aceita uma cadeia de caracteres por uma identidade de número de telefone. Especifique o número de telefone em um formato aceito. Para obter mais informações, consulte Quais são os formatos de números de telefone aceitos pelo Talk?.
Parte 3: assinatura de JWS
a última parte da solicitação é a parte criptografada. Você não precisa se preocupar muito com essa parte, mas ela basicamente pega todas as informações acima (iat, jti, nome, email, etc) além do segredo compartilhado e gera uma cadeia de caracteres criptografada de tudo isso. Então, de acordo com os padrões de JWT, uma boa parte dessa cadeia de caracteres criptografada é coletada (chamada de soma de verificação) e essa é a assinatura de JWS.
E como isso é seguro?
Para gerar uma cadeia de caracteres criptografada válida, você deve saber o segredo compartilhado.
A criptografia foi projetada para que não seja possível retrabalhar a cadeia de caracteres para descobrir os dados e a chave. Mesmo que você tenha o conteúdo dos dados, é praticamente impossível deduzir a chave.
No entanto, como você e nós temos a chave, e você envia os mesmos dados com e sem criptografia, podemos criar a assinatura e verificar se corresponde ao que você enviou.
Isso garante que ninguém mexa nos dados em trânsito.
Em pseudocódigo, esse é o método de criação:
URLBase64Encode(
HMAC-SHA256(
URLBase64Encode( header_json ).URLBase64Encode( payload_json )
)
)
Ao gerar o HMAC-SHA256 do cabeçalho codificado e a carga, você inclui o segredo compartilhado.
Esse é o resultado:
Zv9P7PNIcgHfxZaMwQtMpty3TZnmVHRWcsmAMM-mNHg