Añade autenticación a tu aplicación Android (Kotlin/Java)
Esta guía te mostrará cómo integrar Logto en tu aplicación Android.
- El ejemplo se basa en View system y View Model, pero los conceptos son los mismos al usar Jetpack Compose.
- El ejemplo está escrito en Kotlin, pero los conceptos son los mismos para Java.
- Los proyectos de ejemplo tanto en Kotlin como en Java están disponibles en nuestro repositorio SDK.
- El video tutorial está disponible en nuestro canal de YouTube.
Prerrequisitos
- Una cuenta de Logto Cloud o un Logto autoalojado.
- Una aplicación nativa de Logto creada.
- Un proyecto de aplicación Android en Kotlin.
Instalación
El nivel mínimo de API de Android compatible con Logto Android SDK es el nivel 24.
Logto Android SDK viene en dos versiones principales:
- v2: Abre la experiencia de inicio de sesión en un WebView integrado, que es requerido por los conectores sociales nativos, pero no admite el inicio de sesión con passkey (WebView no admite WebAuthn, el estándar subyacente de las passkeys).
- v3 (beta): Abre la experiencia de inicio de sesión en Chrome Custom Tabs (el navegador del sistema), lo que habilita el inicio de sesión con passkey y comparte la sesión del navegador. Ten en cuenta que v3 elimina el soporte para los conectores WeChat (Nativo) y Alipay (Nativo); puedes usar WeChat (Web) y Alipay (Web) en su lugar, que funcionan a través del navegador. Si dependes de los conectores nativos, quédate en v2.
Esta guía cubre ambas versiones. Elige tu versión en las pestañas a continuación, y la elección se mantendrá sincronizada en toda esta guía.
Antes de instalar Logto Android SDK, asegúrate de que mavenCentral() esté agregado a la configuración de tu repositorio en el archivo de construcción del proyecto Gradle:
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
Añade Logto Android SDK a tus dependencias:
- v2
- v3 (beta)
- Kotlin
- Groovy
dependencies {
implementation("io.logto.sdk:android:2.0.3")
}
dependencies {
implementation 'io.logto.sdk:android:2.0.3'
}
v3 se publica como versiones preliminares 3.0.0-beta hasta GA. Usa la última versión preliminar como la versión:
- Kotlin
- Groovy
dependencies {
implementation("io.logto.sdk:android:3.0.0-beta")
}
dependencies {
implementation 'io.logto.sdk:android:3.0.0-beta'
}
Dado que el SDK necesita acceso a internet, debes añadir el siguiente permiso a tu archivo AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- añadir permiso de internet -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- otras configuraciones... -->
</manifest>
Integración
Inicializar LogtoClient
Crea un LogtoViewModel.kt e inicializa LogtoClient en este modelo de vista:
//...con otras importaciones
import io.logto.sdk.android.LogtoClient
import io.logto.sdk.android.type.LogtoConfig
class LogtoViewModel(application: Application) : AndroidViewModel(application) {
private val logtoConfig = LogtoConfig(
endpoint = "<your-logto-endpoint>",
appId = "<your-app-id>",
scopes = null,
resources = null,
usingPersistStorage = true,
)
private val logtoClient = LogtoClient(logtoConfig, application)
companion object {
val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(
modelClass: Class<T>,
extras: CreationExtras
): T {
// Obtén el objeto Application de extras
val application = checkNotNull(extras[APPLICATION_KEY])
return LogtoViewModel(application) as T
}
}
}
}
luego, crea un LogtoViewModel para tu MainActivity.kt:
//...con otras importaciones
class MainActivity : AppCompatActivity() {
private val logtoViewModel: LogtoViewModel by viewModels { LogtoViewModel.Factory }
//...otros códigos
}
Configurar URI de redirección
Antes de entrar en los detalles, aquí tienes una visión general rápida de la experiencia del usuario final. El proceso de inicio de sesión se puede simplificar de la siguiente manera:
- Tu aplicación invoca el método de inicio de sesión.
- El usuario es redirigido a la página de inicio de sesión de Logto. Para aplicaciones nativas, se abre el navegador del sistema.
- El usuario inicia sesión y es redirigido de vuelta a tu aplicación (configurada como el URI de redirección).
Sobre el inicio de sesión basado en redirección
- Este proceso de autenticación sigue el protocolo OpenID Connect (OIDC), y Logto aplica medidas de seguridad estrictas para proteger el inicio de sesión del usuario.
- Si tienes múltiples aplicaciones, puedes usar el mismo proveedor de identidad (Logto). Una vez que el usuario inicia sesión en una aplicación, Logto completará automáticamente el proceso de inicio de sesión cuando el usuario acceda a otra aplicación.
Para aprender más sobre la lógica y los beneficios del inicio de sesión basado en redirección, consulta Experiencia de inicio de sesión de Logto explicada.
Vamos a cambiar a la página de detalles de la aplicación en Logto Console. Añade un URI de redirección io.logto.android://io.logto.sample/callback y haz clic en "Guardar cambios".
En Android, el URI de redirección sigue el patrón: $(LOGTO_REDIRECT_SCHEME)://$(YOUR_APP_PACKAGE)/callback:
- El
LOGTO_REDIRECT_SCHEMEdebe ser un esquema personalizado en el formato de dominio inverso. - El
YOUR_APP_PACKAGEes el nombre del paquete de tu aplicación.
Suponiendo que trates io.logto.android como el esquema personalizado LOGTO_REDIRECT_SCHEME, y io.logto.sample sea el nombre del paquete de tu aplicación, el URI de redirección debería ser io.logto.android://io.logto.sample/callback.
- v2
- v3 (beta)
No se requiere configuración adicional. La experiencia de inicio de sesión se abre en un WebView integrado, y el SDK intercepta la redirección dentro del WebView.
En v3, la experiencia de inicio de sesión se abre en un Custom Tab (el navegador del sistema), y la redirección se enruta de vuelta a tu aplicación a través de un filtro de intents a nivel del sistema operativo. Debes declarar el esquema de tu URI de redirección con el marcador de posición de manifiesto logtoRedirectScheme en el archivo de compilación de tu aplicación:
- Kotlin
- Groovy
android {
defaultConfig {
manifestPlaceholders["logtoRedirectScheme"] = "io.logto.android"
}
}
android {
defaultConfig {
manifestPlaceholders.logtoRedirectScheme = 'io.logto.android'
}
}
Además, v3 aplica el patrón de URI de redirección a través de la coincidencia de filtros de intents de Android, por lo que un URI de redirección que se desvíe del patrón nunca se entregará a tu aplicación:
- El esquema debe ser igual al marcador de posición de manifiesto
logtoRedirectScheme. - El host debe ser tu
applicationId. - La ruta debe ser
/callback.
Mantén el esquema y el host en minúsculas, ya que la coincidencia de filtros de intents distingue entre mayúsculas y minúsculas, y los navegadores convierten el esquema a minúsculas.
¿Usar App Links en lugar de un esquema personalizado?
Para usar Android App Links (un URI de redirección https en un dominio de tu propiedad) en lugar del esquema personalizado:
-
Aloja el archivo Digital Asset Links en
https://your.domain/.well-known/assetlinks.json, declarando el ID de tu aplicación y las huellas digitales SHA-256 de tus certificados de firma. Al publicar con Play App Signing, puedes encontrar la huella digital de la versión en Play Console bajo Configuración > Firma de la aplicación. El archivo debe servirse comoContent-Type: application/jsoncon HTTP 200 y sin redirecciones. -
Declara el filtro de intents de App Links en la actividad receptora de redirección del SDK
io.logto.sdk.android.auth.logto.LogtoRedirectReceiverActivityen tu archivoAndroidManifest.xml. Si no usas el esquema personalizado en absoluto, elimina el filtro incorporado del SDK contools:node="removeAll", y el marcador de posición de manifiestologtoRedirectSchemeya no será necesario:AndroidManifest.xml<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><application><activity android:name="io.logto.sdk.android.auth.logto.LogtoRedirectReceiverActivity"><!-- Omite esta línea para mantener también funcionando la redirección con esquema personalizado. --><intent-filter tools:node="removeAll" /><intent-filter android:autoVerify="true"><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><data android:scheme="https" android:host="your.domain" android:path="/callback" /></intent-filter></activity></application></manifest> -
Añade
https://your.domain/callbackcomo URI de redirección (y, si se usa para cerrar sesión, como URI de redirección posterior al cierre de sesión) en la página de detalles de la aplicación de Logto Console, y pásalo asignIn/signOut.
Ten en cuenta que el callback es ahora una URL real en tu dominio, por lo que debes servir una página de respaldo allí (p. ej., un botón "Volver a la aplicación") para los navegadores que no inicien App Links en una redirección del servidor. El botón solo necesita enlazar a la URL actual (p. ej., estableciendo href en window.location.href): los parámetros de autorización están en la cadena de consulta, y un clic iniciado por el usuario da a la misma URL otra oportunidad de ser enrutada a tu aplicación. En Android 12+ un dominio no verificado nunca abre la aplicación, por lo que un assetlinks.json roto falla silenciosamente. Puedes comprobar el estado de verificación con adb shell pm get-app-links <applicationId>.
Implementar inicio y cierre de sesión
Antes de llamar a logtoClient.signIn, asegúrate de haber configurado correctamente el URI de redirección en la Consola de Administración.
Puedes usar logtoClient.signIn para iniciar sesión del usuario y logtoClient.signOut para cerrar sesión del usuario.
- v2
- v3 (beta)
Por ejemplo, en una aplicación Android:
//...con otras importaciones
class LogtoViewModel(application: Application) : AndroidViewModel(application) {
// ...otros códigos
// Añadir un live data para observar el estado de autenticación
private val _authenticated = MutableLiveData(logtoClient.isAuthenticated)
val authenticated: LiveData<Boolean>
get() = _authenticated
fun signIn(context: Activity) {
logtoClient.signIn(context, "io.logto.android://io.logto.sample/callback") { logtoException ->
logtoException?.let { println(it) }
// Actualizar el live data
_authenticated.postValue(logtoClient.isAuthenticated)
}
}
fun signOut() {
logtoClient.signOut { logtoException ->
logtoException?.let { println(it) }
// Actualizar el live data
_authenticated.postValue(logtoClient.isAuthenticated)
}
}
}
Luego llama a los métodos signIn y signOut en tu actividad:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//...otros códigos
// Supón que tienes un botón con id "sign_in_button" en tu diseño
val signInButton = findViewById<Button>(R.id.sign_in_button)
signInButton.setOnClickListener {
logtoViewModel.signIn(this)
}
// Supón que tienes un botón con id "sign_out_button" en tu diseño
val signOutButton = findViewById<Button>(R.id.sign_out_button)
signOutButton.setOnClickListener {
if (logtoViewModel.authenticated) { // Verifica si el usuario está autenticado
logtoViewModel.signOut()
}
}
// Observa el estado de autenticación para actualizar la interfaz de usuario
logtoViewModel.authenticated.observe(this) { authenticated ->
if (authenticated) {
// El usuario está autenticado
signInButton.visibility = View.GONE
signOutButton.visibility = View.VISIBLE
} else {
// El usuario no está autenticado
signInButton.visibility = View.VISIBLE
signOutButton.visibility = View.GONE
}
}
}
}
En v3, logtoClient.signOut realiza un cierre de sesión completo: limpia las credenciales locales, revoca el token de actualización y finaliza la sesión de Logto abriendo el endpoint de cierre de sesión en el navegador. El navegador luego navega de vuelta a tu aplicación a través del URI de redirección posterior al cierre de sesión. Antes de usarlo, ve a la página de detalles de la aplicación en Logto Console, añade el URI de redirección posterior al cierre de sesión io.logto.android://io.logto.sample/callback y haz clic en "Guardar cambios". El URI de redirección posterior al cierre de sesión sigue el mismo patrón que el URI de redirección, y su esquema también debe coincidir con el marcador de posición de manifiesto logtoRedirectScheme.
Por ejemplo, en una aplicación Android:
//...con otras importaciones
class LogtoViewModel(application: Application) : AndroidViewModel(application) {
// ...otros códigos
// Añadir un live data para observar el estado de autenticación
private val _authenticated = MutableLiveData(logtoClient.isAuthenticated)
val authenticated: LiveData<Boolean>
get() = _authenticated
fun signIn(context: Activity) {
logtoClient.signIn(context, "io.logto.android://io.logto.sample/callback") { logtoException ->
logtoException?.let { println(it) }
// Actualizar el live data
_authenticated.postValue(logtoClient.isAuthenticated)
}
}
fun signOut(context: Activity) {
logtoClient.signOut(context, "io.logto.android://io.logto.sample/callback") { logtoException ->
logtoException?.let { println(it) }
// Actualizar el live data
_authenticated.postValue(logtoClient.isAuthenticated)
}
}
}
Luego llama a los métodos signIn y signOut en tu actividad:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//...otros códigos
// Supón que tienes un botón con id "sign_in_button" en tu diseño
val signInButton = findViewById<Button>(R.id.sign_in_button)
signInButton.setOnClickListener {
logtoViewModel.signIn(this)
}
// Supón que tienes un botón con id "sign_out_button" en tu diseño
val signOutButton = findViewById<Button>(R.id.sign_out_button)
signOutButton.setOnClickListener {
if (logtoViewModel.authenticated) { // Verifica si el usuario está autenticado
logtoViewModel.signOut(this)
}
}
// Observa el estado de autenticación para actualizar la interfaz de usuario
logtoViewModel.authenticated.observe(this) { authenticated ->
if (authenticated) {
// El usuario está autenticado
signInButton.visibility = View.GONE
signOutButton.visibility = View.VISIBLE
} else {
// El usuario no está autenticado
signInButton.visibility = View.VISIBLE
signOutButton.visibility = View.GONE
}
}
}
}
- También puedes llamar a
logtoClient.signOut(context)sin un URI de redirección posterior al cierre de sesión. En este caso no se necesita configuración en Console: el navegador muestra la página de cierre de sesión de Logto, y el usuario regresa a la aplicación cerrándola manualmente. - Si no hay contexto de UI disponible, puedes llamar a
logtoClient.clearCredentialspara limpiar las credenciales locales y revocar el token de actualización. Ten en cuenta que esto mantiene la sesión de Logto en el navegador, por lo que el próximosignInpuede iniciar sesión silenciosamente al usuario a través de esa sesión.
Punto de control: Prueba tu aplicación
Ahora, puedes probar tu aplicación:
- Ejecuta tu aplicación, verás el botón de inicio de sesión.
- Haz clic en el botón de inicio de sesión, el SDK iniciará el proceso de inicio de sesión y te redirigirá a la página de inicio de sesión de Logto.
- Después de iniciar sesión, serás redirigido de vuelta a tu aplicación y verás el botón de cierre de sesión.
- Haz clic en el botón de cierre de sesión para limpiar el almacenamiento de tokens y cerrar sesión.
Obtener información del usuario
Mostrar información del usuario
Para mostrar la información del usuario, puedes usar el método logtoClient.getIdTokenClaims(). Por ejemplo, puedes obtener información del usuario en un ViewModel y luego mostrarla en tu actividad:
class LogtoViewModel(application: Application) : AndroidViewModel(application) {
// ...otros códigos
// Añadir un live data para observar los reclamos del token de ID
private val _idTokenClaims = MutableLiveData<IdTokenClaims>()
val idTokenClaims: LiveData<IdTokenClaims>
get() = _idTokenClaims
fun getIdTokenClaims() {
logtoClient.getIdTokenClaims { logtoException, idTokenClaims ->
logtoException?.let { _logtoException.postValue(it) } ?: _idTokenClaims.postValue(idTokenClaims)
}
}
}
//...con otras importaciones
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//...otros códigos
// Supón que tienes un TextView con id `user_info_text_view` en tu diseño
val userInfoResponseTextView: TextView = findViewById(R.id.user_info_text_view)
logtoViewModel.userInfoResponse.observe(this) { userInfoResponse ->
userInfoResponseTextView.text = if (userInfoResponse !== null) {
val json = Gson().toJson(userInfoResponse, UserInfoResponse::class.java)
JSONObject(json).toString(2)
} else {
""
}
}
}
}
Solicitar reclamos adicionales
Es posible que encuentres que falta alguna información del usuario en el objeto devuelto desde logtoClient.getIdTokenClaims(). Esto se debe a que OAuth 2.0 y OpenID Connect (OIDC) están diseñados para seguir el principio de privilegio mínimo (PoLP), y Logto está construido sobre estos estándares.
De forma predeterminada, se devuelven reclamos limitados. Si necesitas más información, puedes solicitar alcances adicionales para acceder a más reclamos.
Un "reclamo (Claim)" es una afirmación hecha sobre un sujeto; un "alcance (Scope)" es un grupo de reclamos. En el caso actual, un reclamo es una pieza de información sobre el usuario.
Aquí tienes un ejemplo no normativo de la relación alcance - reclamo:
El reclamo "sub" significa "sujeto", que es el identificador único del usuario (es decir, el ID del usuario).
El SDK de Logto siempre solicitará tres alcances: openid, profile y offline_access.
Para solicitar alcances adicionales, puedes pasarlos al objeto LogtoConfig. Por ejemplo:
private val logtoConfig = LogtoConfig(
// ...otras configuraciones
scopes = listOf("email", "phone"), // o `listOf(UserScope.EMAIL, UserScope.PHONE)`
)
Luego puedes acceder a los reclamos adicionales en el valor de retorno de logtoClient.getIdTokenClaims():
logtoClient.getIdTokenClaims { logtoException, idTokenClaims ->
println("IdTokenClaims:$idTokenClaims")
}
// Ahora puedes acceder a los reclamos adicionales `claims.email`, `claims.phone`, etc.
Reclamos que necesitan solicitudes de red
Para evitar sobrecargar el Token de ID, algunos reclamos requieren solicitudes de red para ser obtenidos. Por ejemplo, el reclamo custom_data no se incluye en el objeto de usuario incluso si se solicita en los alcances. Para acceder a estos reclamos, puedes usar el método logtoClient.fetchUserInfo():
logtoClient.fetchUserInfo {_, userInfoResponse ->
println("UserInfoResponse:$userInfoResponse")
}
// Ahora puedes acceder al reclamo `userInfo.custom_data`
Alcances y reclamos
Logto utiliza las convenciones de OIDC alcances y reclamos (scopes and claims) para definir los alcances y reclamos para obtener información del usuario desde el token de ID y el endpoint OIDC userinfo. Tanto "alcance (scope)" como "reclamo (claim)" son términos de las especificaciones OAuth 2.0 y OpenID Connect (OIDC).
Para los reclamos estándar de OIDC, la inclusión en el token de ID está estrictamente determinada por los alcances solicitados. Los reclamos extendidos (como custom_data y organizations) pueden configurarse adicionalmente para aparecer en el token de ID a través de la configuración de Token de ID personalizado.
Aquí tienes la lista de alcances (Alcances) soportados y los reclamos (Reclamos) correspondientes:
Alcances OIDC estándar
openid (predeterminado)
| Claim name | Type | Description |
|---|---|---|
| sub | string | El identificador único del usuario |
profile (predeterminado)
| Claim name | Type | Description |
|---|---|---|
| name | string | El nombre completo del usuario |
| username | string | El nombre de usuario del usuario |
| picture | string | URL de la foto de perfil del usuario final. Esta URL DEBE referirse a un archivo de imagen (por ejemplo, un archivo de imagen PNG, JPEG o GIF), en lugar de a una página web que contenga una imagen. Ten en cuenta que esta URL DEBERÍA referenciar específicamente una foto de perfil del usuario final adecuada para mostrar al describir al usuario final, en lugar de una foto arbitraria tomada por el usuario final. |
| created_at | number | Momento en que se creó el usuario final. El tiempo se representa como el número de milisegundos desde la época Unix (1970-01-01T00:00:00Z). |
| updated_at | number | Momento en que se actualizó por última vez la información del usuario final. El tiempo se representa como el número de milisegundos desde la época Unix (1970-01-01T00:00:00Z). |
Otros reclamos estándar incluyen family_name, given_name, middle_name, nickname, preferred_username, profile, website, gender, birthdate, zoneinfo y locale, que también se incluirán en el alcance profile sin necesidad de solicitar el endpoint userinfo. Una diferencia en comparación con los reclamos anteriores es que estos reclamos solo se devolverán cuando sus valores no estén vacíos, mientras que los reclamos anteriores devolverán null si los valores están vacíos.
A diferencia de los reclamos estándar, los reclamos created_at y updated_at utilizan milisegundos en lugar de segundos.
email
| Claim name | Type | Description |
|---|---|---|
string | La dirección de correo electrónico del usuario | |
| email_verified | boolean | Si la dirección de correo electrónico ha sido verificada |
phone
| Claim name | Type | Description |
|---|---|---|
| phone_number | string | El número de teléfono del usuario |
| phone_number_verified | boolean | Si el número de teléfono ha sido verificado |
address
Por favor, consulta OpenID Connect Core 1.0 para los detalles del reclamo de dirección.
Los alcances marcados como (predeterminado) siempre son solicitados por el SDK de Logto. Los reclamos bajo los alcances OIDC estándar siempre se incluyen en el token de ID cuando se solicita el alcance correspondiente; no se pueden desactivar.
Alcances extendidos
Los siguientes alcances son extendidos por Logto y devolverán reclamos a través del endpoint userinfo. Estos reclamos también pueden configurarse para incluirse directamente en el token de ID a través de Consola > JWT personalizado. Consulta Token de ID personalizado para más detalles.
custom_data
| Claim name | Type | Description | Included in ID token by default |
|---|---|---|---|
| custom_data | object | Los datos personalizados del usuario |
identities
| Claim name | Type | Description | Included in ID token by default |
|---|---|---|---|
| identities | object | Las identidades vinculadas del usuario | |
| sso_identities | array | Las identidades SSO vinculadas del usuario |
roles
| Claim name | Type | Description | Included in ID token by default |
|---|---|---|---|
| roles | string[] | Los roles del usuario | ✅ |
urn:logto:scope:organizations
| Claim name | Type | Description | Included in ID token by default |
|---|---|---|---|
| organizations | string[] | Los IDs de las organizaciones a las que pertenece el usuario | ✅ |
| organization_data | object[] | Los datos de las organizaciones a las que pertenece el usuario |
Estos reclamos de organización también pueden recuperarse a través del endpoint userinfo cuando se utiliza un token opaco. Sin embargo, los tokens opacos no pueden usarse como tokens de organización para acceder a recursos específicos de la organización. Consulta Token opaco y organizaciones para más detalles.
urn:logto:scope:organization_roles
| Claim name | Type | Description | Included in ID token by default |
|---|---|---|---|
| organization_roles | string[] | Los roles de organización a los que pertenece el usuario con el formato <organization_id>:<role_name> | ✅ |
Recursos de API y organizaciones
Recomendamos leer primero 🔐 Control de acceso basado en roles (RBAC) para entender los conceptos básicos de Logto RBAC y cómo configurar correctamente los recursos de API.
Configurar cliente Logto
Una vez que hayas configurado los recursos de API, puedes agregarlos al configurar Logto en tu aplicación:
val logtoConfig = LogtoConfig(
//...other configs
resources = listOf("https://shopping.your-app.com/api", "https://store.your-app.com/api"), // Añadir recursos de API
)
Cada recurso de API tiene sus propios permisos (alcances).
Por ejemplo, el recurso https://shopping.your-app.com/api tiene los permisos shopping:read y shopping:write, y el recurso https://store.your-app.com/api tiene los permisos store:read y store:write.
Para solicitar estos permisos, puedes agregarlos al configurar Logto en tu aplicación:
val logtoConfig = LogtoConfig(
// ..other configs
scopes = listOf("shopping:read", "shopping:write", "store:read", "store:write"),
resources = listOf("https://shopping.your-app.com/api", "https://store.your-app.com/api"),
)
Puedes notar que los alcances se definen por separado de los recursos de API. Esto se debe a que Resource Indicators for OAuth 2.0 especifica que los alcances finales para la solicitud serán el producto cartesiano de todos los alcances en todos los servicios objetivo.
Así, en el caso anterior, los alcances se pueden simplificar desde la definición en Logto, ambos recursos de API pueden tener alcances read y write sin el prefijo. Luego, en la configuración de Logto:
val logtoConfig = LogtoConfig(
// ...other configs
scopes = listOf("read", "write"),
resources = listOf("https://shopping.your-app.com/api", "https://store.your-app.com/api"),
)
Para cada recurso de API, se solicitarán tanto los alcances read como write.
Está bien solicitar alcances que no están definidos en los recursos de API. Por ejemplo, puedes solicitar el alcance email incluso si los recursos de API no tienen el alcance email disponible. Los alcances no disponibles serán ignorados de manera segura.
Después de un inicio de sesión exitoso, Logto emitirá los alcances apropiados a los recursos de API de acuerdo con los roles del usuario.
Obtener token de acceso para el recurso de API
Para obtener el token de acceso para un recurso de API específico, puedes usar el método getAccessToken:
logtoClient.getAccessToken("https://shopping.your-app.com/api") { logtoException, accessToken ->
logtoException?.let { println(it) }
accessToken?.let { println(it) }
}
Este método devolverá un token de acceso JWT que se puede usar para acceder al recurso de API cuando el usuario tiene permisos relacionados. Si el token de acceso en caché actual ha expirado, este método intentará automáticamente usar un token de actualización para obtener un nuevo token de acceso.
Obtener tokens de organización
Si la organización es nueva para ti, por favor lee 🏢 Organizaciones (Multi-tenancy) para comenzar.
Necesitas añadir el alcance UserScope.Organizations al configurar el cliente Logto:
val logtoConfig = LogtoConfig(
// ...other configs
scopes = listOf(UserScope.Organizations),
)
Una vez que el usuario ha iniciado sesión, puedes obtener el token de organización para el usuario:
// Reemplaza el parámetro con un ID de organización válido.
// Los IDs de organización válidos para el usuario se pueden encontrar en el reclamo del token de ID `organizations`.
logtoClient.getOrganizationToken("organization-id") { logtoException, organizationToken ->
logtoException?.let { println(it) }
organizationToken?.let { println(it) }
}
// o
logtoClient.getOrganizationTokenClaims("organization-id") { logtoException, claims ->
logtoException?.let { println(it) }
claims?.let { println(it) }
}
Recursos de API de la organización
Para obtener un token de acceso para un recurso de API en una organización, puedes usar el método getAccessToken con ambos, el recurso de API y el ID de la organización como parámetros:
logtoClient.getAccessToken(
'https://shopping.your-app.com/api',
organizationId
) { logtoException, accessToken ->
println("AccessToken:$accessToken")
}