Device flow: Autenticação com Logto
Este guia assume que você criou um Aplicativo do tipo "Nativo" com device flow como o fluxo de autorização no Logto Console.
Introdução
O device authorization grant do OAuth 2.0 (device flow) foi projetado para dispositivos com capacidades de entrada limitadas, como smart TVs, consoles de jogos, ferramentas CLI e dispositivos IoT. Ele permite que os usuários iniciem o processo de login no dispositivo, mas concluam a autenticação em outro dispositivo com navegador, como um celular ou laptop.
Como o próprio dispositivo não pode lidar com um fluxo de login baseado em navegador, o dispositivo exibe um código curto e uma URL. O usuário acessa essa URL em outro dispositivo, insere o código e faz login. Enquanto isso, o dispositivo original faz polling no Logto até que a autorização seja concluída.
Obtenha as credenciais do aplicativo
No seu Logto Console, navegue até a página de detalhes do seu aplicativo para obter as seguintes credenciais:
- App ID: O identificador único do seu aplicativo (também conhecido como
client_id). - Endpoint do Logto: O endpoint do seu servidor de autorização Logto. Você pode encontrá-lo no Logto Console em "Detalhes do aplicativo".
Para Logto Cloud, o endpoint é https://{your-tenant-id}.logto.app.
Apps com device flow são clientes públicos, portanto, não é necessário App Secret.
Solicite um device code
Inicie o device flow enviando uma requisição POST para o endpoint de autorização do dispositivo:
curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access profile'
A resposta inclui:
| Campo | Descrição |
|---|---|
device_code | Um código único para seu app usar ao fazer polling no endpoint de token. |
user_code | Um código curto para exibir ao usuário inserir no navegador. |
verification_uri | A URL onde o usuário insere o user_code. |
verification_uri_complete | Uma URL com o user_code pré-preenchido. Usuários podem acessar essa URL diretamente para pular a digitação manual — você pode apresentá-la como QR code, link clicável, etc. |
expires_in | O tempo de vida em segundos de device_code e user_code. Pare de fazer polling após esse tempo expirar. |
Exiba a URL de verificação para o usuário
Mostre o user_code e o verification_uri na tela do seu dispositivo.
Alternativamente, você pode usar o verification_uri_complete, que já tem o código preenchido — o usuário só precisa confirmar. Como apresentar isso fica a seu critério: QR code, link clicável, etc.
Poll para tokens
Enquanto o usuário conclui a autenticação no navegador, seu dispositivo deve fazer polling no endpoint de token. Seu app deve aguardar pelo menos 5 segundos entre as requisições de polling:
curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
--data-urlencode 'device_code=DEVICE_CODE'
Substitua DEVICE_CODE pelo valor de device_code da resposta de autorização do dispositivo.
Pare o polling quando:
- Você receber uma resposta de token bem-sucedida.
- O tempo
expires_inda resposta do device code expirar. - Você receber um erro não-repetível como
expired_tokenouaccess_denied.
Resposta de token
Após a aprovação do usuário, a resposta inclui:
| Campo | Descrição |
|---|---|
access_token | O token de acesso. Por padrão, é uma string opaca; quando um resource é solicitado, é um JWT com aud definido para o URI do recurso. |
id_token | O token de ID contendo reivindicações de identidade do usuário. Presente apenas quando o escopo openid é solicitado. |
refresh_token | Usado para obter novos tokens sem reautenticação. Presente apenas quando o escopo offline_access é solicitado. |
token_type | Sempre Bearer. |
expires_in | Tempo de vida do token em segundos. |
scope | Os escopos concedidos pelo servidor de autorização. |
Checkpoint: Teste seu device flow
Agora, teste a integração do seu device flow:
- Execute seu app e acione o device flow para obter um
device_codeeuser_code. - Abra o
verification_uriem um navegador e insira ouser_code, ou use overification_uri_completepara pular a digitação manual. - Conclua o processo de login no navegador.
- Verifique se seu app recebe os tokens após o polling.
Obtenha informações do usuário
Decodifique as reivindicações do ID token
O id_token retornado na resposta de token é um JSON Web Token (JWT) padrão. Você pode decodificar o payload Base64URL (a segunda parte do JWT, separada por .) para acessar reivindicações básicas do usuário sem uma requisição de rede adicional.
O payload decodificado contém reivindicações como sub (ID do usuário), name, email, etc., dependendo dos escopos solicitados.
Para uso em produção, você deve validar a assinatura do JWT antes de confiar nas reivindicações. Use o JWKS do seu endpoint Logto (https://your.logto.endpoint/oidc/jwks) para verificar o token.
Buscar no endpoint userinfo
O ID token contém reivindicações básicas com base nos escopos solicitados. Algumas reivindicações estendidas (como custom_data, identities) estão disponíveis apenas via endpoint OIDC UserInfo:
curl --request GET 'https://your.logto.endpoint/oidc/me' \
--header 'Authorization: Bearer ACCESS_TOKEN'
Substitua ACCESS_TOKEN pelo token de acesso opaco (não o token JWT de recurso) obtido na resposta de token. A resposta é um objeto JSON contendo as reivindicações do usuário com base nos escopos concedidos.
Solicite reivindicações adicionais
Você pode perceber que algumas informações do usuário estão ausentes no ID token. Isso ocorre porque OAuth 2.0 e OpenID Connect (OIDC) são projetados para seguir o princípio do menor privilégio (PoLP), e o Logto é construído sobre esses padrões.
Por padrão, reivindicações limitadas são retornadas. Se você precisar de mais informações, pode solicitar escopos adicionais para acessar mais reivindicações.
Uma "reivindicação (Claim)" é uma afirmação feita sobre um sujeito; um "escopo (Scope)" é um grupo de reivindicações. No caso atual, uma reivindicação é uma informação sobre o usuário.
Aqui está um exemplo não normativo da relação escopo - reivindicação:
A reivindicação "sub" significa "sujeito (Subject)", que é o identificador único do usuário (ou seja, ID do usuário).
O Logto SDK sempre solicitará três escopos: openid, profile e offline_access.
Para solicitar escopos adicionais, inclua-os no parâmetro scope da requisição de autorização do dispositivo. Por exemplo, para solicitar email e telefone do usuário:
curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access profile email phone'
Escopos e reivindicações
Aqui está a lista de escopos suportados e as reivindicações correspondentes:
Escopos OIDC padrão
openid (padrão)
| Nome da reivindicação | Tipo | Descrição |
|---|---|---|
| sub | string | O identificador único do usuário |
profile (padrão)
| Nome da reivindicação | Tipo | Descrição |
|---|---|---|
| name | string | O nome completo do usuário |
| username | string | O nome de usuário do usuário |
| picture | string | URL da foto de perfil do usuário final. Esta URL DEVE se referir a um arquivo de imagem (por exemplo, um arquivo de imagem PNG, JPEG ou GIF), em vez de uma página da Web contendo uma imagem. Observe que esta URL DEVE referenciar especificamente uma foto de perfil do usuário final adequada para exibição, em vez de uma foto arbitrária tirada pelo usuário final. |
| created_at | number | Momento em que o usuário final foi criado. O tempo é representado como o número de milissegundos desde a época Unix (1970-01-01T00:00:00Z). |
| updated_at | number | Momento em que as informações do usuário final foram atualizadas pela última vez. O tempo é representado como o número de milissegundos desde a época Unix (1970-01-01T00:00:00Z). |
Outras reivindicações padrão incluem family_name, given_name, middle_name, nickname, preferred_username, profile, website, gender, birthdate, zoneinfo e locale também serão incluídas no escopo profile sem a necessidade de solicitar o endpoint userinfo. Uma diferença em relação às reivindicações acima é que essas reivindicações só serão retornadas quando seus valores não forem vazios, enquanto as reivindicações acima retornarão null se os valores estiverem vazios.
Diferente das reivindicações padrão, as reivindicações created_at e updated_at usam milissegundos em vez de segundos.
email
| Nome da reivindicação | Tipo | Descrição |
|---|---|---|
string | O endereço de email do usuário | |
| email_verified | boolean | Se o endereço de email foi verificado |
phone
| Nome da reivindicação | Tipo | Descrição |
|---|---|---|
| phone_number | string | O número de telefone do usuário |
| phone_number_verified | boolean | Se o número de telefone foi verificado |
address
Consulte o OpenID Connect Core 1.0 para detalhes sobre a reivindicação de endereço.
Escopos marcados como (padrão) são sempre solicitados pelo SDK do Logto. As reivindicações sob escopos OIDC padrão são sempre incluídas no token de ID quando o escopo correspondente é solicitado — elas não podem ser desativadas.
Escopos estendidos
Os seguintes escopos são estendidos pelo Logto e retornarão reivindicações através do endpoint userinfo. Essas reivindicações também podem ser configuradas para serem incluídas diretamente no token de ID através de Console > Custom JWT. Veja Token de ID personalizado para mais detalhes.
custom_data
| Nome da reivindicação | Tipo | Descrição | Incluído no token de ID por padrão |
|---|---|---|---|
| custom_data | object | Os dados personalizados do usuário |
identities
| Nome da reivindicação | Tipo | Descrição | Incluído no token de ID por padrão |
|---|---|---|---|
| identities | object | As identidades vinculadas do usuário | |
| sso_identities | array | As identidades SSO vinculadas do usuário |
roles
| Nome da reivindicação | Tipo | Descrição | Incluído no token de ID por padrão |
|---|---|---|---|
| roles | string[] | Os papéis do usuário | ✅ |
urn:logto:scope:organizations
| Nome da reivindicação | Tipo | Descrição | Incluído no token de ID por padrão |
|---|---|---|---|
| organizations | string[] | Os IDs das organizações às quais o usuário pertence | ✅ |
| organization_data | object[] | Os dados das organizações às quais o usuário pertence |
Essas reivindicações de organização também podem ser recuperadas via endpoint userinfo ao usar um token opaco. No entanto, tokens opacos não podem ser usados como tokens de organização para acessar recursos específicos da organização. Veja Token opaco e organizações para mais detalhes.
urn:logto:scope:organization_roles
| Nome da reivindicação | Tipo | Descrição | Incluído no token de ID por padrão |
|---|---|---|---|
| organization_roles | string[] | Os papéis da organização aos quais o usuário pertence no formato <organization_id>:<role_name> | ✅ |
Recursos de API e organizações
Recomendamos ler 🔐 Controle de Acesso Baseado em Papel (RBAC) primeiro para entender os conceitos básicos do RBAC do Logto e como configurar corretamente os recursos de API.
Solicite acesso para recursos de API
Para acessar um recurso de API específico, inclua o parâmetro resource na requisição de autorização do dispositivo:
curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access' \
--data-urlencode 'resource=https://your-api-resource-indicator'
Depois que o usuário concluir a autorização e você receber um refresh token, você pode buscar tokens de acesso JWT para o recurso de API:
curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'resource=https://your-api-resource-indicator'
A resposta conterá um access_token JWT com aud definido para o indicador do seu recurso de API.
O refresh_token só está disponível quando o escopo offline_access é incluído na requisição inicial de autorização do dispositivo. Sempre armazene e use o último refresh_token, pois o Logto utiliza rotação de tokens.
Buscar tokens de organização
Se organizações é novo para você, leia 🏢 Organizações (Multi-tenancy) para começar.
Para solicitar informações relacionadas à organização, adicione o escopo urn:logto:scope:organizations na requisição de autorização do dispositivo:
curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access urn:logto:scope:organizations' \
--data-urlencode 'resource=urn:logto:resource:organizations'
Depois que o usuário fizer login, você pode buscar tokens de organização usando o refresh token:
curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'organization_id=your-organization-id'
A resposta conterá um token de acesso com escopo para a organização especificada.
Recursos de API da organização
Para buscar um token de acesso para um recurso de API dentro de uma organização, inclua ambos os parâmetros resource e organization_id:
curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'organization_id=your-organization-id' \
--data-urlencode 'resource=https://your-api-resource-indicator'