Fluxo portador JWT de OAuth 2.0 para integração entre servidores
Às vezes, você deseja autorizar os servidores a acessar dados sem fazer login de modo interativo sempre que os servidores trocam informações. Para esses casos, você pode usar o fluxo do portador JSON Web Token (JWT) do OAuth 2.0. Esse fluxo usa um certificado para assinar a solicitação do JWT e não requer interação explícita do usuário. Porém, esse fluxo requer aprovação prévia do aplicativo cliente.
Edições obrigatórias
| Disponível em: Salesforce Classic e Lightning Experience |
| Disponível em: Todas as edições |
Com o fluxo de token de portador JWT do OAuth 2.0, o cliente publica um JWT no ponto de extremidade do token OAuth do Salesforce. O Salesforce processa o JWT, que inclui uma assinatura digital, e emite um token de acesso baseado em uma aprovação do aplicativo.
Este exemplo mostra as etapas seguidas no fluxo.
- Um serviço de relatório começa seu relatório em lote noturno.
- O aplicativo conectado envia o JWT ao ponto de extremidade de token do Salesforce. O JWT permite que as informações de identidade e segurança sejam compartilhadas entre domínios de segurança.
- O Salesforce valida o JWT com base em uma assinatura usando um certificado configurado anteriormente e parâmetros adicionais.
- Supondo que o JWT seja válido e que o aplicativo conectado tenha aprovação prévia, o Salesforce emite um token de acesso. A aprovação anterior ocorre em uma destas maneiras:
- Se sua política de aplicativo conectado estiver definida como Usuários aprovados pelo administrador estão pré-autorizados, você poderá usar perfis e conjuntos de permissões.
- Se sua política de aplicativo conectado estiver definida como Todos os usuários podem conceder autorização a si mesmos, você poderá usar a aprovação de usuário final e emissão de um token de atualização. No entanto, o cliente não precisa ter token de atualização atual ou armazenado. O cliente também não precisa passar um segredo de cliente para o ponto de extremidade do token.
Nota Para ambas as opções, o Salesforce somente emite um novo token de acesso quando o token de acesso original inclui, no mínimo, um escopo padrão diferente do escoporefresh_token. - O aplicativo conectado usa o token de acesso para acessar os dados protegidos no servidor do Salesforce.
- O serviço de relatório obtém os dados autorizados para seu relatório noturno.
Vamos repassar cada etapa desse fluxo de autorização.
Criar um JWT
O Salesforce exige que o JWT seja assinado usando RSA SHA256, que usa o certificado carregado como segredo de assinatura. Antes de usar esse fluxo de autorização, conclua estas etapas.
- Carregue um certificado X509 para uma Java Key Store (JKS). O tamanho do certificado não pode exceder 4 KB. Caso contrário, tente usar um arquivo codificado DER para reduzir o tamanho.
- Registre o certificado X509 para o aplicativo conectado. O certificado corresponde à chave privada do aplicativo. Quando o aplicativo conectado é salvo,
client_ideclient_secretsão gerados e atribuídos ao aplicativo. - Crie um aplicativo que gere um JWT, que é assinado com a chave privada do Certificado X509. O aplicativo conectado associado usa o certificado para verificar a assinatura. O JWT deve estar de acordo com as regras gerais de formato especificadas em https://tools.ietf.org/html/rfc7519.
Nota O Salesforce não exige reivindicações de ID do JWT (JTI) nos tokens ao portador do JWT. No entanto, se você passar uma reivindicação JTI no token ao portador do JWT, o Salesforce verificará se ela já enviada anteriormente. Essa verificação evita ataques de repetição de JWT.
Para criar um JWT válido, siga estas etapas.
- Construa um cabeçalho JWT com este formato:
{"alg":"RS256"}. - Codifique o cabeçalho JWT com Base64url, conforme definido em http://tools.ietf.org/html/rfc4648#page-7. O resultado é semelhante a
eyJhbGciOiJSUzI1NiJ9. - Crie um conjunto de declarações JSON para o JWT com os seguintes parâmetros.
Aqui está um exemplo de conjunto de declarações JSON para o JWT.Parâmetro Descrição issO emissor deve conter o client_idOAuth do aplicativo conectado para o qual você registrou o certificado.audO público identifica o servidor de autorização como um público pretendido. O servidor de autorização deve verificar se esse é um público pretendido para o token.
Use o URL do servidor de autorização para o valor do público: https://login.salesforce.com, https://test.salesforce.com ou https://site.force.com/customers se estiver implementando para um site do Experience Cloud.
subSe você estiver implementando esse fluxo para um site do Experience Cloud, o assunto deverá conter o nome de usuário do usuário.
Para compatibilidade com versões anteriores, você pode usar principal (
prn) em vez de assunto (sub). Se ambos forem especificados,prnserá usado.expA data e hora de expiração do token, expressas como o número de segundos a partir de 1970-01-01T0:0:0Z medido em UTC. O Salesforce permite um buffer de 3 minutos para defasagem de relógio. Por exemplo, se o horário de expiração for definido como 1,735,743,600 segundos ou 1o de janeiro de 2025 às 15:00:00 UTC, o token será válido até 15:03:00 UTC nessa data. {"iss": "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQ ukXnVjzRgSuQqGn75NL7yfkQcyy7", "sub": "my@email.com", "aud": "https://login.salesforce.com", "exp": "1333685628"} - Codifique o conjunto de afirmações JWT para Base64url sem quebras de linha. Por exemplo:
eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz Njg1NjI4In0= - Crie uma string para o cabeçalho JWT codificado e para o conjunto de reivindicações JWT codificado, neste formato.
Neste exemplo, o Cabeçalho JWT codificado está destacado.encoded_JWT_Header + "." + encoded_JWT_Claims_SeteyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz Njg1NjI4In0= - Baixe o certificado X509 do JKS.
- Assine a string resultante usando RSA SHA256.
- Crie uma string da string desta etapa no seguinte formato.
Neste exemplo, a assinatura codificada usando base64 está destacado.existing_string + "." + base64_encoded_signatureeyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz Njg1NjI4In0=.iYCthqWCQucwi35yFs-nWNgpF5NA_a46fXDTNIY8ACko6BaEtQ9E6h4Hn1l_pcwcK I_GlmfUO2dJDg1A610t09TeoPagJsZDm_H83bsoZUoI8LpAA1s-2aj_Wbysqb1j4uDToz 480WtEbkwIv09sIeS_-QuWak2RXOl1Krnf72mpVGS4WWSULodgNzlKHHyjAMAHiBHIDNt 36y2L2Bh7M8TNWiKa_BNM6s1FNKDAwHEWQrNtAeReXgRy0MZgQY2rZtqT2FcDyjY3JVQb En_CSjH2WV7ZlUwsKHqGfI7hzeEvVdfOjH9NuaJozxvhPF489IgW6cntPuT2V647JWi7ng
Este código Java é um exemplo simples da construção de um token portador JWT.
import org.apache.commons.codec.binary.Base64;
import java.io.*;
import java.security.*;
import java.text.MessageFormat;
public class JWTExample {
public static void main(String[] args) {
String header = "{\"alg\":\"RS256\"}";
String claimTemplate = "'{'\"iss\": \"{0}\", \"sub\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\", \"jti\": \"{4}\"'}'";
try {
StringBuffer token = new StringBuffer();
//Encode the JWT Header and add it to our string to sign
token.append(Base64.encodeBase64URLSafeString(header.getBytes("UTF-8")));
//Separate with a period
token.append(".");
//Create the JWT Claims Object
String[] claimArray = new String[5];
claimArray[0] = "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQukXnVjzRgSuQqGn75NL7yfkQcyy7";
claimArray[1] = "my@email.com";
claimArray[2] = "https://login.salesforce.com";
claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
claimArray[4]=<JTI>
MessageFormat claims;
claims = new MessageFormat(claimTemplate);
String payload = claims.format(claimArray);
//Add the encoded claims object
token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8")));
//Load the private key from a keystore
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("./path/to/keystore.jks"), "keystorepassword".toCharArray());
PrivateKey privateKey = (PrivateKey) keystore.getKey("certalias", "privatekeypassword".toCharArray());
//Sign the JWT Header + "." + JWT Claims Object
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(token.toString().getBytes("UTF-8"));
String signedPayload = Base64.encodeBase64URLSafeString(signature.sign());
//Separate with a period
token.append(".");
//Add the encoded signature
token.append(signedPayload);
System.out.println(token.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}Solicitar um token de acesso
Para solicitar um token de acesso, o aplicativo conectado publica uma solicitação de token para o ponto de extremidade da instância do Salesforce. Ele inclui o JWT na publicação.
Este exemplo exibe uma solicitação de token.
POST /services/oauth2/token HTTP/1.1
Host: login.example.com
Content-Type: application/x-www-form-urlencoded
grant_type= urn:ietf:params:oauth:grant-type:jwt-bearer&
assertion=eyJpc3MiOiAiM01WRz...[omitted for brevity]...ZTInclua esses parâmetros na publicação.
| Parâmetro | Descrição |
|---|---|
grant_type
|
Use estes valores para o tipo de concessão: urn:ietf:params:oauth:grant-type:jwt-bearer. |
assertion
|
A declaração é todo o valor do JWT. |
format
|
(Opcional) Use para especificar o formato de retorno esperado. Esse parâmetro substitui o cabeçalho da solicitação. Há suporte para esses formatos.
|
Parâmetro de escopo
Não é possível especificar os escopos em um fluxo de token de portador JWT. Os escopos são emitidos de acordo com a política de usuários permitidos do aplicativo conectado ou as configurações de Controle de acesso da API da sua organização, como mostrado nesta tabela.
| Configuração | Resultado |
|---|---|
| Política de usuários permitidos: Todos os usuários podem se autoautorizar | Com uma autorização bem-sucedida, os escopos retornados com o token de acesso são derivados dos escopos de aprovações anteriores. |
| Política de usuários permitidos: Usuários aprovados pelo administrador são pré-autorizados | Os escopos padrão e personalizados atribuídos ao aplicativo conectado são retornados com o token de acesso. |
| Controle de acesso da API: Lista de permissões para aplicativos conectados na sua organização | Os escopos padrão e personalizados atribuídos ao aplicativo conectado são retornados com o token de acesso. Se você permitir aplicativos conectados na sua organização e não receber os escopos esperados, siga estas etapas.
|
O Salesforce concede um token de acesso
As solicitações de fluxo de portador OAuth 2.0 JWT e o portador de declaração SAML procuram em todas as aprovações anteriores o usuário que inclui um token de atualização. Se o Salesforce encontrar aprovações correspondentes, ele combinará os valores dos escopos aprovados. O Salesforce então emite um token de acesso. Se o Salesforce não encontrar aprovações anteriores que incluíam um token de atualização ou qualquer escopo aprovado disponível, a solicitação falhará como não autorizada.
Depois de uma verificação bem-sucedida, a instância do Salesforce envia uma resposta ao aplicativo conectado. Uma resposta de token para o fluxo de token portador JWT do OAuth 2.0 segue o mesmo formato que um fluxo de código de autorização, embora um token de atualização nunca seja emitido.
Este exemplo exibe uma resposta do Salesforce.
{"access_token":"00Dxx0000001gPL!AR8AQJXg5oj8jXSgxJfA0lBog.
39AsX.LVpxezPwuX5VAIrrbbHMuol7GQxnMeYMN7cj8EoWr78nt1u44zU31
IbYNNJguseu",
"scope":"web openid api id","instance_url":"
https://yourInstance.salesforce.com","id":"
https://yourInstance.salesforce.com
/id/00Dxx0000001gPLEAY/005xx000001SwiUAAS","token_type":"Bearer"}Estes parâmetros estão no corpo da resposta.
| Parâmetro | Descrição |
|---|---|
access_token |
Token OAuth que um aplicativo conectado usa para solicitar acesso a um recurso protegido em nome do aplicativo cliente. Permissões adicionais na forma de escopos podem acompanhar o token de acesso. |
token_type |
Um tipo de token Bearer, que é usado para todas as respostas que incluem um token de acesso. |
scope |
Os escopos são emitidos de acordo com a política de usuários permitidos do aplicativo conectado ou as configurações de Controle de acesso da API da sua organização. Consulte Parâmetro de escopo. |
instance_url |
Um URL que indica a instância da organização do usuário. Por exemplo: https://yourInstance.salesforce.com/. |
id |
Um URL de identidade que pode ser usado para identificar o usuário e consultar mais informações sobre o usuário. Veja os URLs de identidade. |
sfdc_site_url |
Se o usuário for um membro de um site do Experience Cloud, o URL do site será fornecido. |
sfdc_site_id |
Se o usuário for um membro de um site do Experience Cloud, o ID do site do usuário será fornecido. Para sites do Experience Cloud, esse fluxo inclui o valor "sfdc_site_id" no ponto de extremidade do token. Esse ID do site é potencialmente obrigatório em solicitações da API REST do Connect. |
Acessar dados protegidos
Depois que o aplicativo conectado receber access_token, ele pode passar como um token portador na solicitação de cabeçalho de autorização. Este exemplo mostra uma chamada de API REST para sites do Experience Cloud:
https://site.force.com/customers/services/data/v32.0/ -H
"Authorization: Bearer 00D50000000IehZ\!AQcAQH0dMHZfz972Szmpkb58urFRkgeBGsxL_QJWwYMfAbUeeG7c1E6 LYUfiDUkWe6H34r1AAwOR8B8fLEz6n04NPGRrq0FM"

