Pular para o conteúdo

Máquina a máquina

Deixe um serviço chamar as suas APIs como ele mesmo com o grant client credentials: clients e consumers, escopos e audiência, cache de tokens e rotação de credenciais.

Quando não há pessoa envolvida — um job noturno, um backend chamando outro, a integração de um parceiro —, quem chama se autentica como ele mesmo com o grant client_credentials (RFC 6749). Ele apresenta um client ID e um segredo no endpoint de token e recebe um access token que descreve o serviço, não um usuário.

Configure o client

  1. Crie um client confidencial

    Em Clients, crie um client com a autenticação de client ligada e habilite o grant client_credentials. Um client público não pode usá-lo: ele não tem segredo para apresentar. Copie o segredo quando ele aparecer — ele aparece uma única vez.

  2. Dê a ele os escopos de que o serviço precisa

    Libere os escopos no client, ou num consumer, se cada integração deve ter credencial e permissões próprias.

  3. Deixe-o alcançar a API

    Registre a API como servidor de recurso, por exemplo https://api.example.com, e acrescente o client aos clients permitidos dele. Os tokens pedidos com resource passam a levar esse identificador em aud.

Consumers: uma credencial por integração

Um consumer é uma credencial extra presa a um client, com escopos e papéis próprios. Dê a cada sistema que chama você um consumer próprio e você consegue ver, limitar e revogar cada um sem mexer nos outros. Crie-os em Consumers: escolha o client, o tipo Client Secret, um valor de 8 a 512 caracteres (ou gere um) e os escopos e papéis. O valor aparece uma vez, quando o consumer é criado ou o valor é trocado; depois só os quatro últimos caracteres aparecem, e uma edição que deixa o valor em branco o mantém.

AspectoSegredo do clientConsumer
Enviado comoclient_id e o segredo do client.client_id do client e o valor do consumer como segredo.
EscoposOs escopos do client.Só os escopos do consumer; nada é herdado do client.
PapéisNenhum.Os papéis do consumer, na claim consumer_resource_access.
Identificado no token porazp.azp, mais consumer_name, credential_id e credential_type.
Desligado aoDesativar o client, o que para todas as integrações.Desativar ou suspender só aquele consumer.

A credencial de um consumer só vale para o client a que pertence, é apresentada com o método de autenticação registrado no client e precisa estar ativa. Quantos consumers você pode manter ativos depende do seu plano.

Tipos de consumer

TipoApresentado comoValidado por
Client SecretO segredo do client, com o client_id do client, no token endpoint.O Authio, que emite um token de client_credentials para o consumer.
Personal Access Tokenclient_secret do grant personal_access_token, com o client_id do client.O Authio, que emite um token com sub = o consumer e azp = o client_id do client.
API KeyComo está, para a sua própria API (por exemplo num cabeçalho x-api-key que você define).A sua API, no endpoint de introspecção do realm — veja Chaves de API.

O tipo é definido na criação do consumer: uma atualização sem type o mantém, e uma que pede outro tipo é recusada com ValidationFailed em type. Para outro tipo, crie outro consumer. Cada autenticação de consumer — um token emitido ou recusado, uma chave aceita ou recusada — é um registro no log de acesso com o consumer e o client, e um webhook login_succeeded ou login_failed com consumer_id e consumer_name.

Chaves de API

Um consumer API Key é uma chave que o parceiro envia à sua API em cada chamada, sem trocar por token. A sua API confere a chave no endpoint de introspecção do realm (RFC 7662), autenticada como o client a que o consumer pertence — ou como o client com que o seu resource server faz introspecção, quando é o mesmo client — com token_type_hint=api_key. A chave nunca é validada pela API administrativa, e a API administrativa não a aceita.

TerminalBash
curl https://authio.api.hyperio.tech/realms/acme/protocol/openid-connect/introspect \
  -u "acme-orders-api:$CLIENT_SECRET" \
  -d token="$PARTNER_API_KEY" \
  -d token_type_hint=api_key
  • sub e credential_id são o consumer; client_id é o client; scope traz todos os escopos permitidos ao consumer (inclusive os opcionais, já que uma chave não tem como pedi-los), sem os escopos de pessoa.
  • Uma chave errada, de outro client, ou de um consumer inativo ou suspenso responde {"active": false}. Não há exp: a chave vale até o consumer ser desligado ou ter o valor trocado, então faça a introspecção em cada chamada ou guarde a resposta por poucos segundos.
  • Sem token_type_hint=api_key um valor só é verificado como token, então uma API que espera tokens nunca recebe uma chave como se fosse um. Com o hint, um valor que não é chave ainda é verificado como token, como pede a RFC 7662.

Peça um token

TerminalBash
curl -X POST https://authio.api.hyperio.tech/realms/acme/protocol/openid-connect/token \
  -u 'acme-reports:YOUR_CLIENT_SECRET' \
  -d grant_type=client_credentials \
  -d scope=orders:read \
  --data-urlencode resource=https://api.example.com

-u envia a credencial por HTTP Basic (client_secret_basic, o padrão). Se o client estiver registrado com client_secret_post, mande client_id e client_secret como campos do formulário: o Authio só aceita o método registrado. Não há refresh token nem ID token — não existe sessão para manter.

Quais escopos e qual audiência você recebe

  • Os escopos padrão da credencial são sempre concedidos; os opcionais, só quando scope os cita.
  • Um escopo pedido que a credencial não tem fica fora do token, sem recusa — confira scope na resposta.
  • Escopos de pessoas — openid, profile, email, phone, address, offline_access — nunca entram num token de máquina.
  • Com resource, aud é aquele servidor de recurso e os escopos do servidor que você pedir são acrescentados. Um recurso que o client não pode alcançar é recusado com invalid_target.
  • Sem resource, aud é a audiência do client — Authio por padrão —, que a sua API não deve aceitar.

O sub do token é o ID interno do client e azp é o client ID, então uma API pode admitir um único client de máquina por azp — o RequireAuthioClient faz isso no .NET.

Guarde os tokens em cache

Não peça um token por chamada. Guarde-o até pouco antes de expires_in acabar e então peça outro: cada emissão é uma ida ao Authio, fica no log de acesso e conta como uso de client credentials. Guarde um token por combinação de escopos e recurso.

.NETC#
using Authio.Client.Extensions;

builder.Services.AddAuthioClient(builder.Configuration.GetSection("Authio"));
builder.Services
    .AddHttpClient<OrdersApi>(client => client.BaseAddress = new Uri("https://api.example.com"))
    .AddAuthioClientCredentials(options =>
    {
        options.Scopes = ["orders:read"];
        options.Resource = "https://api.example.com";
    });

No .NET, o AddAuthioClientCredentials faz tudo isso: o token fica em cache por escopos e recurso, é renovado TokenRefreshSkew (um minuto) antes de expirar, é compartilhado entre chamadas simultâneas e é buscado de novo uma vez se a API responder 401. A configuração completa está em .NET.

Gire as credenciais

Gire o segredo de um client pela tela do client em Clients, e uma credencial da conta — uma chave de API, um token de acesso pessoal ou um client secret da conta — pela tela dela em Segredos de API. O novo valor aparece uma única vez. A rotação pergunta por que você está girando, e a resposta decide o que acontece com o valor substituído:

Você escolheO valor anteriorTokens emitidos com ele
Rotação de rotina, sem sobreposiçãoRecusado já na próxima chamada.Continuam valendo até expirar.
Rotação de rotina, mantido por 15 minutos, uma hora ou um diaContinua aceito até o fim do período e depois é recusado. O console só oferece os períodos que o ambiente permite.Continuam valendo até expirar.
O valor atual vazouRecusado já na próxima chamada.Os access tokens emitidos antes da rotação ficam inativos na introspecção e são recusados pelas APIs do próprio Authio, e os refresh tokens deles param de funcionar. No segredo de um client, quem está conectado ao client precisa entrar de novo.
  • Sem indisponibilidade. Escolha uma sobreposição e publique o novo segredo em todas as instâncias enquanto o antigo ainda funciona; a tela do client diz até quando. Ou use consumers: crie um consumer novo com os mesmos escopos e papéis, publique o serviço com o valor dele e depois desative o consumer antigo.
  • Depois de um vazamento. Escolha O valor atual vazou: nenhuma sobreposição é oferecida, porque um valor vazado precisa parar na hora.
  • Corte também os tokens emitidos. Ligue Revoke Issued Tokens Immediately nas configurações de segurança do client. A introspecção passa a responder active: false para um token cuja credencial foi desativada, revogada, expirou ou foi apagada — APIs que só conferem assinaturas localmente não percebem, então precisam da introspecção.
Revogar os tokens de um valor vazado só alcança quem consulta o Authio. Um servidor de recurso que valida JWTs localmente, só pela assinatura, não vê a revogação e continua aceitando esses tokens até expirarem. Faça-o introspectar os tokens, ou mantenha os access tokens de vida curta.

Solução de problemas

O que aparecePor quêO que fazer
401 invalid_clientSegredo errado, consumer inativo ou segredo enviado por um método diferente do registrado.Confira o valor e use Basic ou campos de formulário, conforme o client está registrado.
unauthorized_clientO grant client_credentials não está habilitado no client.Habilite-o nos grants do client.
invalid_targetO recurso não é um servidor de recurso que o client pode alcançar.Confira o identificador e acrescente o client aos clients permitidos do servidor de recurso.
O token não tem um escopo que você pediuA credencial não tem esse escopo, então ele ficou de fora.Libere o escopo no client ou no consumer.
A API recusa a audiência do tokenO token foi pedido sem resource.Mande resource com o identificador da API.

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