Flujo de soporte JWT de OAuth 2.0 para la integración de servidor a servidor
En algunos casos desea autorizar a servidores para acceder a los datos sin tener que iniciar sesión de forma interactiva cada vez que los servidores intercambian información. Para estos casos, puede utilizar el flujo del token de soporte JWT de OAuth 2.0. Este flujo utiliza un certificado para firmar la solicitud JWT y no requiere una interacción de usuario explĆcita. No obstante, este flujo requiere aprobación previa de la aplicación cliente.
Ediciones necesarias
| Disponible en: Salesforce Classic y Lightning Experience |
| Disponible en: todas las ediciones |
Consulte Las nuevas aplicaciones conectadas ya no se pueden crear en Spring ā26 para obtener mĆ”s detalles.
Con el flujo del token de soporte JWT de OAuth 2.0, el cliente publica un JWT en el extremo de token de Salesforce OAuth. Salesforce procesa el JWT, que incluye una firma digital, y emite un token de acceso basÔndose en la aprobación previa de la aplicación.
Este ejemplo muestra los pasos realizados en el flujo.
- Un servicio de reporte comienza su reporte por lotes nocturno.
- La aplicación conectada envĆa el JWT al extremo de tokens de Salesforce. El JWT activa la información de identidad y seguridad que va a compartir en los dominios de seguridad.
- Salesforce valida el JWT en base a una firma empleando un certificado configurado anteriormente y parƔmetros adicionales.
- Suponiendo que el JWT es vÔlido y que la aplicación conectada tenga aprobación previa, Salesforce emite un token de acceso. La aprobación previa se produce de una de estas formas:
- Si su polĆtica de aplicación conectada se establece como Los usuarios aprobados por el administrador se han autorizado previamente, puede utilizar perfiles de usuario y conjuntos de permiso.
- Si su polĆtica de aplicación conectada se establece como Todos los usuarios pueden autorizarse, puede utilizar la aprobación de usuario final y la emisión de un token de actualización. Sin embargo, el cliente no necesita tener un token de actualización actual o almacenado. Tampoco se requiere al cliente pasar una pregunta secreta del cliente al extremo del token.
Nota Para ambas opciones, Salesforce emite un nuevo token de acceso solo cuando el token de acceso original incluye al menos un Ômbito estÔndar que no sea el Ômbitorefresh_token. - La aplicación conectada utiliza el token de acceso para acceder a los datos protegidos en el servidor de Salesforce.
- El servicio de reporte extrae los datos autorizados para su reporte nocturno.
Vayamos por cada paso de este flujo de autorización.
Crear un JWT
Salesforce requiere que un JWT esté firmado empleando RSA SHA256, que utiliza un certificado cargado como el secreto de firmas. Antes de utilizar este flujo de autorización, asegúrese de completar estos pasos.
- Cargue un certificado X509 en un Java Key Store (JKS). El tamaño del certificado no puede superar los 4 KB. En caso contrario, intente utilizar un archivo con codificación DER para reducir el tamaño.
- Registre el certificado X509 para la aplicación conectada. El certificado se corresponde con la clave privada de la aplicación. Cuando se guarda la aplicación conectada, el
client_idy elclient_secretse generan y se asignan a la aplicación. - Construya una aplicación que genere un JWT, que estÔ firmado con la clave privada del certificado X509. La aplicación conectada asociada utiliza el certificado para verificar la firma. El JWT debe cumplir las reglas generales de formato especificadas en https://tools.ietf.org/html/rfc7519.
Nota Salesforce no requiere reclamaciones de Id. de JWT ID (JTI) en sus tokens de soporte de JWT. Sin embargo, si pasa una reclamación de JTI en su token de soporte de JWT, Salesforce valida que la reclamación de JTI no se envió antes. Esta validación evita ataques de reproducción de JWT.
Para crear un JWT vƔlido, siga estos pasos.
- Cree un encabezado JWT con este formato:
{"alg":"RS256"}. - El encabezado JWT tiene una codificación Base64url, tal y como se define en http://tools.ietf.org/html/rfc4648#page-7. El resultado es similar a
eyJhbGciOiJSUzI1NiJ9. - Cree un conjunto de solicitudes de JSON para el JWT con estos parƔmetros.
Este es un ejemplo de conjunto de solicitudes de JSON para el JWT.ParÔmetro Descripción issEl emisor debe incluir client_idde OAuth o la aplicación conectada para la que registró el certificado.audLa audiencia identifica el servidor de autorización como una audiencia dirigida. El servidor de autorización debe verificar que es una audiencia dirigida para el token.
Utilice la URL del servidor de autorización para el valor de audiencia: https://login.salesforce.com, https://test.salesforce.com, o https://site.force.com/customers si se implementa para un sitio de Experience Cloud.
subSi estĆ” implementando este flujo para un sitio de Experience Cloud, el asunto debe contener el nombre de usuario del usuario.
Para la compatibilidad con versiones anteriores, puede utilizar el principal (
prn) en vez del asunto (sub). Si se especifican ambos, se utilizaprn.expLa fecha y hora a la que caduca el token, expresada como el nĆŗmero de segundos desde 1970-01-01T0:0:0Z segĆŗn la zona horaria UTC. Salesforce permite a 3 minutos de desfase de reloj. Por ejemplo, si la hora de caducidad estĆ” establecida en 1,735,743,600 segundos o el 1 de enero de 2025 a las 15:00:00 UTC, el token sigue siendo vĆ”lido hasta las 15:03:00 UTC en esta fecha. {"iss": "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQ ukXnVjzRgSuQqGn75NL7yfkQcyy7", "sub": "my@email.com", "aud": "https://login.salesforce.com", "exp": "1333685628"} - Codifique con Base64url el conjunto de solicitudes de JWT sin saltos de lĆnea. Por ejemplo:
eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz Njg1NjI4In0= - Cree una cadena para el encabezado de JWT codificado y el conjunto de solicitudes de JWT codificado con este formato.
En este ejemplo, el encabezado de JWT codificado estĆ” resaltado.encoded_JWT_Header + "." + encoded_JWT_Claims_SeteyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz Njg1NjI4In0= - Descargue el certificado X509 desde el JKS.
- Firme la cadena resultante utilizando RSA SHA256.
- Cree una cadena a partir de la cadena de este paso con este formato.
En este ejemplo, la firma con codificación base64 estĆ” resaltada.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 de Java es un ejemplo sencillo de cómo crear un token de soporte 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 un token de acceso
Para solicitar un token de acceso, la aplicación conectada publica una solicitud de token en el extremo de tokens de la instancia de Salesforce. Incluye el JWT en la publicación.
Este ejemplo muestra una solicitud de token de muestra.
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]...ZTIncluya estos parÔmetros en la publicación.
| ParÔmetro | Descripción |
|---|---|
grant_type
|
Utilice estos valores para el tipo de otorgamiento: urn:ietf:params:oauth:grant-type:jwt-bearer. |
assertion
|
La afirmación es el valor de JWT completo. |
format
|
(Opcional) Utilizar para especificar el formato de devolución esperado. Este parÔmetro sustituye al encabezado de la solicitud. Se admiten estos formatos.
|
ParƔmetro de Ɣmbito
No puede especificar Ć”mbitos en un flujo de token de soporte JWT. Los Ć”mbitos se emiten segĆŗn la polĆtica Usuarios permitidos de la aplicación conectada o la configuración Control de acceso de API de su organización, como se muestra en esta tabla.
| Configuración | Resultado |
|---|---|
| PolĆtica Usuarios permitidos: Todos los usuarios pueden autorizarse | Con una autorización realizada con Ć©xito, los Ć”mbitos devueltos con el token de acceso se derivan de los Ć”mbitos de aprobaciones previas. |
| PolĆtica Usuarios permitidos: Los usuarios aprobados por el administrador se han autorizado previamente | Los Ć”mbitos estĆ”ndar y personalizados asignados a la aplicación conectada se devuelven con el token de acceso. |
| Control de acceso de API: Incluir en lista de permitidos aplicaciones conectadas en su organización | Los Ômbitos estÔndar y personalizados asignados a la aplicación conectada se devuelven con el token de acceso. Si incluye aplicaciones conectadas en la lista de permitidos en su organización y no recibe los Ômbitos esperados, siga estos pasos.
|
Salesforce otorga un token de acceso
Las solicitud de flujo de soporte de afirmación de SAML y de soporte JWT de OAuth 2.0 comprueban todas las aprobaciones anteriores para el usuario que incluyan un token de actualización. Si Salesforce encuentra aprobaciones coincidentes, combina los valores de los Ć”mbitos aprobados. Salesforce emite a continuación un token de acceso. Si Salesforce no encuentra aprobaciones previas que incluĆan un token de actualización o ningĆŗn Ć”mbito aprobado disponible, la solicitud falla como no autorizada.
Tras una verificación correcta, la instancia de Salesforce envĆa una respuesta a la aplicación conectada. Una respuesta de token para el flujo de token de soporte JWT de OAuth 2.0 sigue el mismo formato que un flujo de código de autorización, aunque nunca se haya emitido un token de actualización.
Este ejemplo muestra una respuesta de 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"}Estos parƔmetros se encuentran en el cuerpo de la respuesta.
| ParÔmetro | Descripción |
|---|---|
access_token |
Token de OAuth que una aplicación conectada utiliza para solicitar el acceso a un recurso protegido en nombre de una aplicación cliente. Pueden acompañar permisos adicionales en la forma de Ômbitos al token de acceso. |
token_type |
Un tipo de token Bearer, que se utiliza para todas las respuestas que influyen un token de acceso. |
scope |
Los Ć”mbitos se emiten segĆŗn la polĆtica Usuarios permitidos de la aplicación conectada o la configuración Control de acceso de API de su organización. Consulte ParĆ”metro de Ć”mbito. |
instance_url |
Una URL que indica la instancia de la organización del usuario. Por ejemplo: https://yourInstance.salesforce.com/. |
id |
Una URL de identidad que se puede utilizar para identificar al usuario y para consultar con el fin de obtener mÔs información acerca del usuario. Consulte URL de identidad. |
sfdc_site_url |
Si el usuario es un miembro de un sitio de Experience Cloud, se proporciona la URL del sitio. |
sfdc_site_id |
Si el usuario es un miembro de un sitio de Experience Cloud, se proporciona el Id. de sitio del usuario. Para sitios de Experience Cloud, este flujo incluye el valor "sfdc_site_id" en el extremo del token. Este Id. de sitio es posiblemente obligatorio en solicitudes de API de REST de Connect. |
Acceder a datos protegidos
Después de que la aplicación conectada reciba access_token, puede pasarlo como un token de soporte en la solicitud del encabezado de autorización. Este ejemplo muestra una llamada de API de REST a los sitios de Experience Cloud:
https://site.force.com/customers/services/data/v32.0/ -H
"Authorization: Bearer 00D50000000IehZ\!AQcAQH0dMHZfz972Szmpkb58urFRkgeBGsxL_QJWwYMfAbUeeG7c1E6 LYUfiDUkWe6H34r1AAwOR8B8fLEz6n04NPGRrq0FM"

