Pular para o conteúdo

Fluxo de dispositivo

Faça o login em TVs, CLIs e outros aparelhos sem um navegador utilizável: mostre um código curto, deixe a pessoa aprová-lo em outra tela e consulte os tokens (RFC 8628).

O device authorization grant (RFC 8628) é para aparelhos que não conseguem mostrar uma tela de login, ou em que digitar uma senha seria penoso: uma smart TV, uma ferramenta de linha de comando, um quiosque. O aparelho pede ao Authio um par de códigos, mostra o curto para a pessoa e consulta o endpoint de token enquanto ela aprova o pedido no celular ou no computador.

Como funciona

  1. O aparelho pede os códigos

    Ele chama o endpoint de autorização de dispositivo e recebe um device_code, que guarda para si, um user_code para a pessoa e o endereço onde o código é digitado.

  2. Ele mostra o código

    Na tela: o endereço e o código e, muitas vezes, um QR code do endereço com o código já preenchido.

  3. A pessoa aprova em outra tela

    A página de verificação hospedada do realm confere o código, faz o login da pessoa se precisar e pede que ela aprove ou negue. Ela usa a marca do client que fez o pedido.

  4. O aparelho consulta os tokens

    Enquanto isso, o aparelho chama o endpoint de token a cada poucos segundos até receber os tokens, uma recusa ou o código expirar.

Configure o client

Em Clients, habilite o grant de device code (urn:ietf:params:oauth:grant-type:device_code) no client que o aparelho usa e libere os escopos que ele vai pedir — openid para um ID token, offline_access para um refresh token. Um aparelho distribuído a clientes não consegue guardar segredo, então use um client público; um client confidencial autentica as duas chamadas normalmente.

Peça um device code

TerminalBash
curl -X POST https://authio.api.hyperio.tech/realms/acme/protocol/openid-connect/device/auth \
  -d client_id=acme-tv \
  -d 'scope=openid profile offline_access'
CampoO que é
device_codeA referência secreta do aparelho para o pedido. Nunca mostre.
user_codeOito caracteres em dois grupos, de um alfabeto sem caracteres parecidos. Maiúsculas e separadores são relevados na digitação.
verification_uriA página de verificação hospedada, {issuer}/device.
verification_uri_completeA mesma página com o código preenchido; o endereço para pôr num QR code.
expires_inSegundos até os códigos expirarem: 10 minutos.
intervalO mínimo de segundos entre duas consultas: 5.

Se o client não tiver o grant de device code, o pedido é recusado antes de qualquer código ser criado. Escopos que o client não libera também são recusados.

Mostre o código

Mostre verification_uri e user_code em letras grandes, e verification_uri_complete como QR code para celulares. A página hospedada conduz a pessoa por três passos numa tela só: informar o código (já preenchido quando vem do QR code), entrar e, por fim, aprovar ou negar.

  • O login nessa página é por usuário e senha. Uma conta que exige segundo fator não consegue concluir o login ali; quem tem o app do Authio pareado pode aprovar o pedido pelo app.
  • Um código desconhecido, expirado, já usado ou de outro realm é recusado.
  • Aprovar abre uma sessão para o client, e os tokens do aparelho pertencem a ela: encerrar essa sessão — pelo portal da conta, pelo console ou por um logout — desconecta o aparelho.

Consulte os tokens

Espere interval segundos e chame o endpoint de token com o device code. Repita até a resposta deixar de ser authorization_pending.

TerminalBash
curl -X POST https://authio.api.hyperio.tech/realms/acme/protocol/openid-connect/token \
  -d grant_type=urn:ietf:params:oauth:grant-type:device_code \
  -d device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS \
  -d client_id=acme-tv

Enquanto a pessoa não decide, o endpoint responde 400 com um error do RFC 8628. Quando ela aprova, ele responde 200 com a mesma resposta de tokens do fluxo de código de autorização: um access token, um ID token com openid e um refresh token com offline_access.

ErroSignificadoO que o aparelho faz
authorization_pendingA pessoa ainda não decidiu.Espera interval segundos e consulta de novo.
slow_downO aparelho consultou antes do que interval permite.Soma 5 segundos ao intervalo para todas as consultas seguintes e consulta de novo.
expired_tokenOs 10 minutos passaram sem aprovação.Para e recomeça com um device code novo.
access_deniedA pessoa negou, o código já foi resgatado ou pertence a outro client.Para. Ofereça recomeçar.

Consultar não estende a vida do código, e um código gera tokens uma única vez. Um laço que segue essas regras:

device-sign-in.tsTypeScript
const issuer = 'https://authio.api.hyperio.tech/realms/acme'
const clientId = 'acme-cli'

export async function signInOnDevice() {
  const authorization = await fetch(`${issuer}/protocol/openid-connect/device/auth`, {
    method: 'POST',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({ client_id: clientId, scope: 'openid offline_access' }),
  }).then((response) => response.json())

  console.log(`Abra ${authorization.verification_uri} e digite ${authorization.user_code}`)

  let interval = authorization.interval * 1000

  while (true) {
    await new Promise((resolve) => setTimeout(resolve, interval))

    const response = await fetch(`${issuer}/protocol/openid-connect/token`, {
      method: 'POST',
      headers: { 'content-type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
        device_code: authorization.device_code,
        client_id: clientId,
      }),
    })
    const body = await response.json()

    if (response.ok) return body
    if (body.error === 'authorization_pending') continue
    if (body.error === 'slow_down') {
      interval += 5000
      continue
    }

    throw new Error(body.error_description ?? body.error)
  }
}

No .NET, o PollDeviceTokenAsync do Authio.Client espera o intervalo antes de cada consulta, soma 5 segundos num slow_down e lança AuthioProtocolException em access_denied ou expired_token. Registre o client com AddAuthioClient e ClientAuthentication em None para um client público.

Mantenha o aparelho conectado

Guarde o refresh token no aparelho e renove o access token com o grant refresh_token, como descrito em Qualquer client OIDC. Refresh tokens são rotacionados, então guarde o novo a cada vez. Quando uma renovação falhar com invalid_grant — a sessão foi encerrada, o refresh token expirou —, comece o fluxo de dispositivo de novo.

Solução de problemas

O que aparecePor quêO que fazer
unauthorized_client ao pedir um códigoO grant de device code não está habilitado no client.Habilite-o nos grants do client.
invalid_clientUm client confidencial não mandou o segredo, mandou o errado ou usou um método diferente do registrado.Mande o segredo como está registrado, ou torne o client público.
A página diz que o login da conta não é suportadoA conta exige um segundo fator, que a página de dispositivo não oferece.Aprove pelo app do Authio, ou use uma conta sem segundo fator obrigatório.
access_denied logo depois de aprovarO código foi consultado por um client diferente do que o pediu.Consulte com o mesmo client_id que pediu o código.

Próximos passos

Cookies de analytics

Gostaríamos de medir como o console é usado, com o Google Analytics, para enxergar em quais telas as pessoas travam. Isso grava um cookie que reconhece este navegador na sua próxima visita.

Recusar não muda mais nada. Os cookies que mantêm você conectado e lembram o seu idioma e o seu tema são necessários para o console funcionar, e ficam de qualquer forma. Ler a Política de Privacidade