Saltar al contenido principal
Este tutorial te ayuda a llamar a tu propia API desde una aplicación nativa, móvil o de una sola página mediante el Flujo de código de autorización con PKCE. Para saber cómo funciona el flujo y por qué deberías usarlo, consulta Flujo de código de autorización con Proof Key for Code Exchange (PKCE). Para aprender a añadir Login a tu aplicación nativa, móvil o de una sola página, consulta Añadir Login mediante el Flujo de código de autorización con PKCE.
Auth0 facilita que tu aplicación implemente el Flujo de código de autorización con Proof Key for Code Exchange (PKCE) mediante:

Requisitos previos

Antes de comenzar este tutorial:
  • Registre la aplicación en Auth0.
    • Seleccione Native o Single-Page App en Tipo de aplicación, según corresponda a su aplicación.
    • Agregue {yourCallbackUrl} como URL de devolución de llamada permitida. El formato de la URL de devolución de llamada varía según el tipo de aplicación y la plataforma. Para obtener más información sobre el formato correspondiente a su tipo de aplicación y plataforma, consulte nuestros Quickstarts de Native/Mobile y Quickstarts de Single-Page App.
    • Asegúrese de que los Tipos de concesión de la aplicación incluyan código de autorización. Para saber cómo hacerlo, consulte Actualizar tipos de concesión.
    • Si quiere que su aplicación pueda usar tokens de actualización, asegúrese de que los Tipos de concesión de la aplicación incluyan Token de actualización. Para saber cómo hacerlo, consulte Actualizar tipos de concesión. Para obtener más información sobre los tokens de actualización, consulte Tokens de actualización.
  • Registre su API en Auth0
    • Si quiere que su API reciba tokens de actualización para obtener tokens nuevos cuando los anteriores expiren, habilite Permitir acceso sin conexión.

Pasos

  1. Crear verificador de código: Genera un code_verifier que se enviará a Auth0 para solicitar tokens.
  2. Crear desafío de código: Genera un code_challenge a partir del code_verifier que se enviará a Auth0 para solicitar un authorization_code.
  3. Autorizar al usuario: Solicita la autorización del usuario y redirígelo a tu aplicación con un authorization_code.
  4. Solicitar tokens: Intercambia tu authorization_code y code_verifier por tokens.
  5. Llamar a la API: Usa el Token de acceso obtenido para llamar a tu API.
  6. Tokens de actualización: Usa un token de actualización para solicitar nuevos tokens cuando los actuales expiren.
Opcional: Explorar ejemplos de casos de uso.

Crear el verificador de código

Cree un code_verifier, que es una clave aleatoria codificada en Base64 y criptográficamente segura, que posteriormente se enviará a Auth0 para solicitar tokens.

Ejemplo de JavaScript

// Dependencia: módulo crypto de Node.js
// https://nodejs.org/api/crypto.html#crypto_crypto
function base64URLEncode(str) {
    return str.toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}
var verifier = base64URLEncode(crypto.randomBytes(32));

Ejemplo en Java

// Dependencia: Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/
// Importar la clase Base64.
// import org.apache.commons.codec.binary.Base64;
SecureRandom sr = new SecureRandom();
byte[] code = new byte[32];
sr.nextBytes(code);
String verifier = Base64.getUrlEncoder().withoutPadding().encodeToString(code);

Ejemplo para Android

// Ver https://developer.android.com/reference/android/util/Base64
// Importar la clase Base64
// import android.util.Base64;
SecureRandom sr = new SecureRandom();
byte[] code = new byte[32];
sr.nextBytes(code);
String verifier = Base64.encodeToString(code, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);

Ejemplo en Swift 5

var buffer = [UInt8](repeating: 0, count: 32)
_ = SecRandomCopyBytes(kSecRandomDefault, buffer.count, &buffer)
let verifier = Data(buffer).base64EncodedString()
    .replacingOccurrences(of: "+", with: "-")
    .replacingOccurrences(of: "/", with: "_")
    .replacingOccurrences(of: "=", with: "")

Ejemplo en Objective-C

NSMutableData *data = [NSMutableData dataWithLength:32];
int result __attribute__((unused)) = SecRandomCopyBytes(kSecRandomDefault, 32, data.mutableBytes);
NSString *verifier = [[[[data base64EncodedStringWithOptions:0]
                        stringByReplacingOccurrencesOfString:@"+" withString:@"-"]
                        stringByReplacingOccurrencesOfString:@"/" withString:@"_"]
                        stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];

Crear el desafío de código

Genera un code_challenge a partir del code_verifier que se enviará a Auth0 para solicitar un authorization_code.

Ejemplo de Javascript

// Dependencia: módulo crypto de Node.js
// https://nodejs.org/api/crypto.html#crypto_crypto
function sha256(buffer) {
    return crypto.createHash('sha256').update(buffer).digest();
}
var challenge = base64URLEncode(sha256(verifier));

Ejemplo en Java

// Dependencia: Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/
// Importar la clase Base64.
// import org.apache.commons.codec.binary.Base64;
byte[] bytes = verifier.getBytes("US-ASCII");
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(bytes, 0, bytes.length);
byte[] digest = md.digest();
String challenge = Base64.encodeBase64URLSafeString(digest);

Ejemplo en Swift 5

import CommonCrypto

// ...

guard let data = verifier.data(using: .utf8) else { return nil }
var buffer = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
_ = data.withUnsafeBytes {
    CC_SHA256($0.baseAddress, CC_LONG(data.count), &buffer)
}
let hash = Data(buffer)
let challenge = hash.base64EncodedString()
    .replacingOccurrences(of: "+", with: "-")
    .replacingOccurrences(of: "/", with: "_")
    .replacingOccurrences(of: "=", with: "")

Ejemplo en Objective-C

// Dependencia: biblioteca Apple Common Crypto
// http://opensource.apple.com//source/CommonCrypto
u_int8_t buffer[CC_SHA256_DIGEST_LENGTH * sizeof(u_int8_t)];
memset(buffer, 0x0, CC_SHA256_DIGEST_LENGTH);
NSData *data = [verifier dataUsingEncoding:NSUTF8StringEncoding];
CC_SHA256([data bytes], (CC_LONG)[data length], buffer);
NSData *hash = [NSData dataWithBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
NSString *challenge = [[[[hash base64EncodedStringWithOptions:0]
                         stringByReplacingOccurrencesOfString:@"+" withString:@"-"]
                         stringByReplacingOccurrencesOfString:@"/" withString:@"_"]
                         stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];

Autorizar al usuario

Una vez que hayas creado el code_verifier y el code_challenge, debes obtener la autorización del usuario. Técnicamente, este es el inicio del , y este paso puede incluir uno o más de los siguientes procesos:
  • Autenticar al usuario;
  • Redirigir al usuario a un para gestionar la autenticación;
  • Verificar si hay sesiones activas de inicio de sesión único (SSO);
  • Obtener el consentimiento del usuario para el nivel de permisos solicitado, a menos que ya se haya otorgado previamente.
Para autorizar al usuario, tu aplicación debe dirigir al usuario a la URL de autorización, incluido el code_challenge que generaste en el paso anterior y el método que usaste para generarlo.

Ejemplo de URL de autorización

Parámetros
Ten en cuenta que, para autorizar a un usuario al llamar a una API personalizada, debes:
  • incluir un parámetro
  • puedes incluir alcances adicionales admitidos por la API de destino
Nombre del parámetroDescripción
response_typeIndica el tipo de credencial que devolverá Auth0 (code o token). Para este flujo, el valor debe ser code.
code_challengeDesafío generado a partir de code_verifier.
code_challenge_methodMétodo utilizado para generar el desafío (por ejemplo, S256). La especificación PKCE define dos métodos, S256 y plain; en este ejemplo se usa el primero y es el único compatible con Auth0, ya que el segundo no se recomienda.
client_idEl ID de cliente de tu aplicación. Puedes encontrar este valor en la configuración de la aplicación.
redirect_uriLa URL a la que Auth0 redirigirá el navegador después de que el usuario haya otorgado la autorización. El código de autorización estará disponible en el parámetro de URL code. Debes especificar esta URL como una URL de devolución de llamada válida en la configuración de la aplicación.

Advertencia: Según la especificación de OAuth 2.0, Auth0 elimina todo lo que aparece después del hash y no respeta ningún fragmento.
scopeLos alcances para los que quieres solicitar autorización. Deben estar separados por espacios. Puedes solicitar cualquiera de los alcances estándar de OpenID Connect (OIDC) sobre usuarios, como profile y email, claims personalizados que cumplan con un formato con espacio de nombres, o cualquier alcance admitido por la API de destino (por ejemplo, read:contacts). Incluye offline_access para obtener un Token de actualización (asegúrate de que el campo Allow Offline Access esté habilitado en la configuración de la aplicación).
audienceEl identificador único de la API a la que tu aplicación móvil quiere acceder. Usa el valor Identifier en la pestaña Settings de la API que creaste como parte de los requisitos previos de este tutorial.
state(recomendado) Una cadena alfanumérica arbitraria y opaca que tu aplicación agrega a la solicitud inicial y que Auth0 incluye al redirigir de vuelta a tu aplicación. Para ver cómo usar este valor para prevenir ataques de Cross-site Request Forgery (CSRF), consulta Mitigar ataques CSRF con parámetros state.
organization(opcional) ID de la organización que se usará al autenticar a un usuario. Si no se proporciona y tu aplicación está configurada para Display Organization Prompt, el usuario podrá introducir el nombre de la organización al autenticarse.
invitation(opcional) ID del ticket de la invitación a la organización. Al invitar a un miembro a una Organización, tu aplicación debe gestionar la aceptación de la invitación reenviando los pares clave-valor invitation y organization cuando el usuario acepte la invitación.
Como ejemplo, tu fragmento HTML para la URL de autorización al llamar a una API podría verse así:

Respuesta

Si todo sale bien, recibirá una respuesta HTTP 302. El código de autorización se incluye al final de la URL:
HTTP/1.1 302 Found
Location: {yourCallbackUrl}?code={authorizationCode}&state=xyzABC123

Solicitar tokens

Ahora que ya tiene un código de autorización, debe intercambiarlo por tokens. Con el código de autorización extraído (code) en el paso anterior, deberá realizar un POST a la URL del token y enviar también el code_verifier.

Ejemplo de una solicitud POST a la URL del token

Parámetros
Nombre del parámetroDescripción
grant_typeEstablécelo en “authorization_code”.
code_verifierLa clave criptográficamente aleatoria que se generó en el primer paso de este tutorial.
codeEl authorization_code obtenido en el paso anterior de este tutorial.
client_idEl ID de cliente de tu aplicación. Puedes encontrar este valor en la configuración de la aplicación.
redirect_uriLa URL de devolución de llamada válida configurada en la configuración de tu aplicación. Debe coincidir exactamente con el redirect_uri enviado a la URL de autorización en el paso anterior de este tutorial. Ten en cuenta que debe estar codificada como URL.

Respuesta

Si todo sale bien, recibirás una respuesta HTTP 200 con una carga útil que incluye los valores access_token, refresh_token, id_token y token_type:
{
  "access_token":"eyJz93a...k4laUWw",
  "refresh_token":"GEbRxBN...edjnXbL",
  "id_token":"eyJ0XAi...4faeEoQ",
  "token_type":"Bearer",
  "expires_in":86400
}
Valide sus tokens antes de guardarlos. Para obtener más información, consulte Validar ID Token y Validar tokens de acceso.
ID Token contiene información del usuario que debe decodificarse y extraerse. Los tokens de acceso se usan para llamar al endpoint /userinfo de la API de autenticación de Auth0 o a otra API. Si está llamando a su propia API, lo primero que deberá hacer es verificar el token de acceso. Los tokens de actualización se usan para obtener un nuevo o después de que haya expirado el anterior. El refresh_token solo estará presente en la respuesta si incluyó el scope offline_access y habilitó Allow Offline Access para su API en el Dashboard.
Los tokens de actualización deben almacenarse de forma segura, ya que permiten que un usuario permanezca autenticado prácticamente para siempre.

Llamar a la API

Para llamar a la API desde una aplicación nativa o móvil, la aplicación debe enviar el Token de acceso obtenido como Bearer Token en el encabezado Authorization de la solicitud HTTP.

Tokens de actualización

Ya recibió un token de actualización si ha seguido este tutorial y completó lo siguiente:
  • configuró su API para permitir acceso sin conexión
  • incluyó el scope offline_access cuando inició la solicitud de autenticación a través del endpoint de autorización.
Puede usar el para obtener un nuevo token de acceso. Normalmente, un usuario solo necesitará un nuevo token de acceso después de que caduque el anterior o cuando obtenga acceso a un recurso nuevo por primera vez. Es una mala práctica llamar al endpoint para obtener un nuevo token de acceso cada vez que llame a una API, y Auth0 aplica límites de frecuencia que restringen la cantidad de solicitudes al endpoint que pueden ejecutarse con el mismo token desde la misma IP. Para renovar su token, haga una solicitud POST al endpoint /oauth/token en la Authentication API, usando grant_type=refresh_token.

Ejemplo de solicitud POST a la URL del token

Parámetros
Nombre del parámetroDescripción
grant_typeEstablece este valor en refresh_token.
client_idEl ID de cliente de tu aplicación. Puedes encontrar este valor en la configuración de la aplicación.
refresh_tokenEl token de actualización que se usará.
scope(opcional) Una lista de permisos de scope solicitados, delimitada por espacios. Si no se envía, se usarán los alcances originales; de lo contrario, puedes solicitar un conjunto reducido de alcances. Ten en cuenta que debe estar codificado en URL.

Respuesta

Si todo sale bien, recibirás una respuesta HTTP 200 con una carga útil que incluye un nuevo access_token, su duración en segundos (expires_in), los valores de scope concedidos y token_type. Si el scope del token inicial incluía openid, la respuesta también incluirá un nuevo id_token:
{
  "access_token": "eyJ...MoQ",
  "expires_in": 86400,
  "scope": "openid offline_access",
  "id_token": "eyJ...0NE",
  "token_type": "Bearer"
}
Valida tus tokens antes de guardarlos. Para obtener más información, consulta Validar ID Tokens y Validar tokens de acceso.

Ejemplos de casos de uso

Personalizar tokens

Puede usar Actions para cambiar los alcances que devuelven los tokens de acceso y/o agregar claims a los tokens de acceso y a los ID Token. (Para obtener más información sobre Actions, lea Auth0 Actions. ) Para ello, agregue la siguiente Action, que se ejecutará después de que el usuario se autentique:
exports.onExecutePostLogin = async (event, api) => {
  // Agregar claim personalizado al Token de acceso y al ID Token
  api.accessToken.setCustomClaim('https://foo/bar', 'value');
  api.idToken.setCustomClaim('https://fiz/baz', 'some other value');

  // Modificar el scope del Token de acceso
  api.accessToken.addScope('foo');
  api.accessToken.addScope('bar');
};
Los alcances estarán disponibles en el token después de que se ejecute la Action.
Auth0 devuelve la información del perfil en un formato estructurado de claims, tal como lo define la especificación de OpenID Connect (OIDC). Esto significa que los claims personalizados agregados a ID Token o tokens de acceso deben ajustarse a las pautas y restricciones para evitar posibles colisiones.

Ver la aplicación de ejemplo: aplicación móvil + API

Para ver una implementación de ejemplo, consulte el escenario de arquitectura Mobile + API. Esta serie de tutoriales incluye un ejemplo de código al que puede acceder en GitHub.

Más información