Noções básicas de API (FAPI) de nivel financeiro

Table of Contents

Prefácio

Este documento descreve a visão geral das disposições de segurança definidas em API de nível financeiro - Parte 2: Ler e Escrever Perfil de Segurança da API (doravante chamado “FAPI”) e instruções de configuração da Authlete através de etapas para a construção de um servidor de autorização compatível com FAPI.

É fortemente aconselhável que você tenha conhecimento básico do OpenID Connect e Authlete fazendo o tutorial a seguir.

Componentes

Neste tutorial, assumimos os seguintes componentes. Observe que apenas os consoles e APIs da Authlete estão funcionando, enquanto um servidor de autorização (provedor de identidade OIDC) e um servidor de recursos realmente não existem.

Em vez disso, você usará o comando curl para simular como esses servidores fazem solicitações de API para Authlete ao receber solicitações de autorização, solicitações de token e solicitações de introspecção de token de clientes (OIDC participante).

Components in this tutorial

As FQDNs de cada componente são as seguintes: O servidor de autorização e o cliente não existem como indicado acima, mas suas FQDNs são pelo menos necessárias para explicar o fluxo OAuth.

Componente FQDN
API Authlete api.authlete.com
Authlete Service Owner console so.authlete.com
Authlete Developer console cd.authlete.com
Servidor de Autorização (Provedor de Identidade OIDC) as.example.com
Cliente (OIDC Relying Party) client.example.org
servidor de recursos N/A

Interação entre cliente API e servidor API usando FAPI

Neste documento, você configurará o Authlete para habilitar o seguinte processo de concessão de tokens e fluxos de acesso à API de forma compatível com o FAPI.

FAPI-compliant token granting process and API access flows

1. Requisição de Autorização

Um cliente compatível com FAPI tem que empregar um objeto de solicitação para criar uma solicitação de autoração a um servidor de autorização compatível com FAPI.

O objeto de solicitação é passado para o servidor por qualquer valor (usando request parâmetro) ou referência (request_uri). Neste documento, o cliente estará usando o antigo.

Além do objeto de solicitação, você tem que cumprir outras disposições de segurança da FAPI, tais como response_type e claims Parâmetros. Neste documento, o cliente estará usando code id_token durante response_type parâmetro. Outras configurações devem ser explicadas mais tarde.

2. Resposta de Autorização

As disposições de segurança da FAPI não permitem que um servidor de autorização inclua um código de autorização (code), como uma sequência de consulta em uma resposta de autorização. Neste documento, o servidor estará fazendo uma resposta incluir o code como um fragmento desde response_type=code id_token é especificado na etapa anterior.

3. Requisição de token

Um servidor de autorização tem que empregar métodos de chave pública para autenticar clientes ao receber uma solicitação de token. Neste documento, o servidor usará autenticação TLS mútua.

4. Resposta de token

Um servidor de autorização tem que vincular um token de acesso a um certificado de cliente obtido a partir da comunicação TLS mútua no ponto final do token do servidor, e fazer uma resposta de token ao cliente.

5. Requisição de API

Um cliente e um servidor de recursos têm que estabelecer uma comunicação TLS mútua. O servidor de recursos estará verificando a vinculação entre o certificado do cliente e o token de acesso em uma solicitação de API e, em seguida, fazendo uma resposta se a vinculação for válida.

Configuração inicial

Adicionando um novo serviço Authlete com um cliente

Criando um serviço no Authlete e habilitando FAPI

Faça login no console proprietário de serviços da Authlete https://so.authlete.com/ e clique no botão “Criar serviço”. Você verá a página de criação do serviço. Digite nome de serviço e identificador de emissor de tokens da seguinte forma e clique no botão “Criar”. Pressione “OK” em um diálogo para confirmação.

Item Valor
Nome de serviço Um valor arbitrário, por exemplo. FAPI Service
Identificador de emissor de token https://as.example.com

O novo serviço foi criado. Os valores gerados automaticamente de “Chave de API” e “Segredo de API” serão usados como “ID de login” e “Senha” para fazer login no Console do Desenvolvedor, bem como credencial para que seu servidor de autorização faça solicitações a APIs Authlete.

Item Valor
chave da API Gerado automaticamente, por exemplo. 174381609020
Secretas da API Gerado automaticamente, por exemplo. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k

Vamos habilitar o suporte fapi do serviço. Clique no botão “Editar” na parte inferior da página para tornar as configurações editáveis e ir para a guia Autorização. Deve haver FAPI com uma caixa de seleção, que não é verificada, em Perfis de Serviço suportados. Verifique a caixa e clique no botão “Atualizar” na parte inferior da página. Pressione “OK” em um diálogo para confirmação.

Supported Service Profiles in Service Details

Clique no botão “Editar” para tornar as configurações editáveis novamente e vá para a guia Token. Deve haver escopos suportados e alguns escopos predefinidos, como address e openid. Clique no botão “Criar escopo” no lado direito para que você possa ver uma caixa de diálogo para definir um escopo. Adicione um novo escopo com os seguintes parâmetros.

Item Valor
Nome do escopo payment
Entrada Padrão Escolher Non default
Description Um valor arbitrário
Atributos (Clique no botão “Novo atributo” para adicionar) Chave: fapi / Valor: rw

Create Scope in Service Owner Console

Criando um novo cliente e configuração básica

Abra o link para o Console de Desenvolvedores da Authlete para o serviço (https://cd.authlete.com/<API Key> por exemplo, https://cd.authlete.com/174381609020) e faça login no console com sua chave de API e segredo de API como ID de login e senha, respectivamente.

Clique no botão “Criar aplicativo” no lado direito e digite/escolha os seguintes valores na página do aplicativo de criação.

Item Valor
Nome do cliente Um valor arbitrário, por exemplo. FAPI Client
do tipo cliente Escolher CONFIDENTIAL

Em seguida, clique na guia Autorização ao lado do Básico e digite o seguinte valor para Redirecionar URIs.

Item Valor
Redirecionar uris https://client.example.org/cb/example.com

Clique no botão “Criar” na parte inferior da página. Pressione “OK” em um diálogo para confirmação.

Agora você fez o registro do cliente para o serviço. Valores gerados automaticamente de “Client ID” e “Client Secret” serão usados como client_id e client_secret para que o cliente faça solicitações ao servidor de autorização. Certifique-se também de que outros valores sejam definidos como esperado.

Item Valor
ID do Cliente Auto-generetad, por exemplo. 591205987816490
Secreto do Cliente Gerado automaticamente, por exemplo. e7iqzq7WE8Kg00yepYnpMTjvDnAnBlq5nfA9DDQLkiYkPQBV6Lr8sLhn7DhUJd17i0O6TwQ2hKFeDAYuU160Vg
tipo do cliente CONFIDENTIAL
Redirecionar uris https://client.example.org/cb/example.com

Testando a configuração inicial

/auth/authorization API

Vamos verificar como o Authlete funciona com a configuração inicial. Nós usaremos /auth/authorization API com esse propósito.

Requisição de autorização para escopos não FAPI

Vamos supor que o servidor receba uma solicitação de autorização (scope=openid), que não inclui nenhum escopo sujeito à FAPI. O servidor fará uma solicitação para /auth/authorization API. Aqui está uma versão da requisição.

Substitua as chaves API Key, API Secret, Client ID pelos valores gerados no passo anterior.

curl -s -X POST https://api.authlete.com/api/auth/authorization \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"parameters": "redirect_uri=https://client.example.org/cb/example.com&scope=openid&response_type=code&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj"}' |jq

Substitua as chaves API Key, API Secret, Client ID pelos valores gerados no passo anterior.

Se você estar usando curl.exe via PowerShell no Windows 10's, garanta que o comando utilizado seja curl.exe ao invés curl, e verifique o uso correto dos caracter " e `.

curl.exe -s -X POST https://api.authlete.com/api/auth/authorization `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"parameters\": \"redirect_uri=https://client.example.org/cb/example.com&scope=openid&response_type=code&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj\"}'

Authlete faz a seguinte resposta (dobrada para legibilidade).

{
  "type": "authorizationResponse",
  "resultCode": "A004001",
  "resultMessage": "[A004001] Authlete has successfully issued a ticket
   to the service (API Key = 174381609020) for the authorization request
   from the client (ID = 591205987816490). [response_type=code, openid=true]",
[...]

De acordo com o valor de resultMessage, Authlete aceitou o pedido de autorização quando seus escopos não estão relacionados à FAPI. Então, o que acontece se a solicitação incluir escopos FAPI? Vamos tentar na próxima seção.

Authorization request for FAPI scope (parte 1)

Vamos supor que o servidor de auhtorização receba uma solicitação de autorização (scope=openid payment) que inclui um escopo (payment), sujeito à FAPI. O servidor fará uma solicitação para /auth/authorization API. Aqui está uma versão enrolada do pedido.

curl -s -X POST https://api.authlete.com/api/auth/authorization \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"parameters": "redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj"}' |jq
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"parameters\": \"redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj\"}'

Authlete faz a seguinte resposta de erro (dobrada para legibilidade).

{
  "type": "authorizationResponse",
  "resultCode": "A150312",
  "resultMessage": "[A150312] The value of 'response_type' (code) is not allowed.",
[...]

De acordo com o valor de resultMessage, response_type=code não é permitido.

Isso se deve às disposições de segurança da FAPI. 5.2 Leia e escreva as disposições de segurança da API / 5.2.2. Servidor de autorização estados da seguinte forma.

deve exigir o response_type Valores code id_token ou code id_token token;

Assim, você tem que usar qualquer um response_type=code id_token ou response_type=code id_token token em um ambiente compatível com FAPI. Em outras palavras, outros tipos, como response_type=code, response_type=token são proibidos, ou seja, um servidor de autorização não deve aceitá-los.

Requisição de Autorização para escopos FAPI (parte 2)

Então, que tal um pedido de autorização que inclui response_type=code id_token Em vez de response_type=code? Vamos fazer um pedido para /auth/authorization API como segue.

curl -s -X POST https://api.authlete.com/api/auth/authorization \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"parameters": "redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj"}' |jq
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"parameters\": \"redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj\"}'

Novamente Authlete faz outra resposta de erro.

{
  "type": "authorizationResponse",
  "resultCode": "A150301",
  "resultMessage": "[A150301] A request object is required.",
[...]

De acordo com o valor de resultMessage, um objeto de solicitação é necessário para prosseguir.

Isso se deve às disposições de segurança da FAPI. Na mesma seção, 5.2 Leia e escreva as disposições de segurança da API / 5.2.2. Servidor de autorização estados da seguinte forma.

deve exigir o request ou request_uri parâmetro a ser passado como um JWS assinado JWT como na cláusula 6 de [OIDC];

Um servidor de autorização tem que obrigar os clientes a passar um objeto de solicitação por valor (request) ou por referência (request_uri).

Então vamos criar uma solicitação de autorização com um objeto de solicitação na próxima seção para tornar a solicitação compatível com FAPI.

Fazendo uma solicitação de autorização compatível com FAPI

Nesta seção, criaremos uma solicitação de autorização usando um objeto de solicitação. Também prepararemos uma reivindicação adicional exigida pela FAPI.

Solicitar configurações de objeto

Configuring a signing key used for a request object

Temos que preparar uma chave para um cliente assinar um objeto de solicitação. Neste documento, usaremos mkjwk para criar um par de chaves ES256 e dois tipos de conjuntos-chave; Uma inclui uma chave privada e outra não.

Os parâmetros para mkjwk são os seguintes.

Item Valor
Guia EC (Curva Elíptica)
Curve curva P-256
Key Use Signing
Algorithm ES256 (ECDSA using P-256 and SHA-256)
Key ID Um valor arbitrário, por exemplo. 1

Generating a JWK Set with mkjwk

Aqui estão exemplos de um conjunto de teclas gerado e um conjunto derivado sem uma chave privada.

  • es256_keyset.txt (incluindo uma linha de uma chave privada "d")
{
  "keys": [
    {
      "kty": "EC",
      "d": "L6KxA-db4oh5NKYEpO6IulUDSRXP7fqNAmScu6fygIE",
      "use": "sig",
      "crv": "P-256",
      "kid": "1",
      "x": "icP8p_AigyTzwSpLRyv_bBQTSGu_NG7pMVXd-RAxwYE",
      "y": "06tC0MJeBlZNYlnY8g4bCA9wJ34XN-rWfWlmmlhf-F0",
      "alg": "ES256"
    }
  ]
}
  • es256_keyset_pub.txt (excluindo uma linha de uma chave privada "d" De es256_keyset.txt)
{
  "keys": [
    {
      "kty": "EC",
      "use": "sig",
      "crv": "P-256",
      "kid": "1",
      "x": "icP8p_AigyTzwSpLRyv_bBQTSGu_NG7pMVXd-RAxwYE",
      "y": "06tC0MJeBlZNYlnY8g4bCA9wJ34XN-rWfWlmmlhf-F0",
      "alg": "ES256"
    }
  ]
}

Additional client settings

Para que o serviço Authlete verifique a assinatura de um objeto de solicitação proveniente de um cliente, você tem que registrar sua chave pública para as configurações do cliente e especificar um algoritmo de assinatura que o cliente usa.

Faça login no Console do Desenvolvedor para o serviço (https://cd.authlete.com/<API Key> por exemplo, https://cd.authlete.com/174381609020) e configurar as configurações do cliente da seguinte forma.

  • Guia JWK Set
Item Valor
Conteúdo JWK Colar conteúdo de es256_keyset_pub.txt

JWK Set Content in Developer Console

  • Guia de autorização
Item Valor
Solicitar algoritmo de assinatura de objeto ES256

Request Object Signature Algorithm in Developer Console

Agora terminamos a preparação para que Authlete verifique a assinatura de um objeto de solicitação.

Criando um objeto de requisição

Vamos agir como um cliente gerando um objeto de solicitação e elaborando uma solicitação de autorização com o objeto. Aqui está uma carga de amostra neste documento. Digite o valor correto de client_id, que foi gerado automaticamente em seu ambiente.

payload.txt

{
"redirect_uri":"https://client.example.org/cb/example.com",
"response_type":"code id_token",
"client_id":"<client_id> e.g. 591205987816490",
"scope":"openid payment",
"exp":15549730000,
"aud":"https://as.example.com",
"nonce":"n-0S6_WzA2Mj"
}

O cliente estará criando um JWT assinado com a chave privada gerada na seção anterior. Neste documento, usamos mkjose por exemplo. Digite/escolha valores para cada item e clique em “Gerar” para que você possa encontrar o JWT assinado na seção Saída.

Item Valor
Conteudo Colar de payload.txt
Algoritmo de signatura Escolher EC256
Chave de assinatura Remova as duas primeiras linhas ("keys":, [) e as duas últimas linhas (], }), do conteúdo de es256_keyset.txt (como deve ser um JWK, não um conjunto JWK) e cole-o

Generating a signed JWT with mkjose

Outro exemplo usando passo CLI é o seguinte.

cat payload.txt | \
step crypto jws sign --jwks=es256_keyset.txt --kid=1

Neste documento, foi feito o seguinte resultado. Isso será usado como um valor de request parâmetro em uma solicitação autorizada.

eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iLAoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZXhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoibm9uY2UiOiJuLTBTNl9XekEyTWoiCn0K.q_MbfV5qN-gnB93JaQGVrEXu8WvhDuUzWx6DwC50J8AiQGjXDEpw9satUAMN18rrgnGNciiFztoEFJuJjrJoyA

Testando a configuração

Vamos supor que o servidor de auhtorização receba uma solicitação de autorização, incluindo um objeto de solicitação, de um cliente. O servidor fará uma solicitação para /auth/authorization API. Aqui está uma versão enrolada do pedido.

curl -s -X POST https://api.authlete.com/api/auth/authorization \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"parameters": "redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj&request=<Request Object e.g. eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iLAoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZXhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoibm9uY2UiOiJuLTBTNl9XekEyTWoiCn0K.q_MbfV5qN-gnB93JaQGVrEXu8WvhDuUzWx6DwC50J8AiQGjXDEpw9satUAMN18rrgnGNciiFztoEFJuJjrJoyA>"}' |jq
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"parameters\": \"redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj&request=<Request Object e.g. eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iLAoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZXhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoibm9uY2UiOiJuLTBTNl9XekEyTWoiCn0K.q_MbfV5qN-gnB93JaQGVrEXu8WvhDuUzWx6DwC50J8AiQGjXDEpw9satUAMN18rrgnGNciiFztoEFJuJjrJoyA>\"}'

Authlete faz a seguinte resposta de erro, apesar de especificar o objeto de solicitação.

{
  "type": "authorizationResponse",
  "resultCode": "A150317",
  "resultMessage": "[A150317] The 'acr' claim is not contained in the request.",
[...]

De acordo com o valor de resultMessage, um cliente tem que incluir um acr (referência de contexto de autenticação) na solicitação.

Isso se deve às disposições de segurança da FAPI. 5.2 Leia e escreva disposições de segurança da API / 5.2.3 Cliente público estados da seguinte forma.

solicitará a autenticação do usuário na LoA 3 ou superior, solicitando a reivindicação acr como uma reivindicação essencial definida na seção 5.5.1.1 de [OIDC];"

Assim, um cliente tem que solicitar um servidor de autorização para autenticar usuários na LoA 3 ou superior. O acr reivindicação é o paramater para especificar a LoA.

Então vamos tentar novamente configurando acr suporte no serviço Authlete e atuando como um cliente para incluir o acr reivindicar em outro pedido de autorização.

Configurações de referência de contexto de autenticação (acr)

Incluindo o suporte a ACR

Faça login no console proprietário de serviços da Authlete https://so.authlete.com/, clique no botão “Editar” na parte inferior da página para tornar as configurações editáveis e vá para a guia Autenticação do usuário. Deve haver seção de referências de classe de contexto de autenticação suportada. Adicione os seguintes valores como um novo acr. Usamos um exemplo de URN urn:example:psd2:sca para indicar LoA 3 ou superior.

Verifique a caixa e clique no botão “Atualizar” na parte inferior da página. Pressione “OK” em um diálogo para confirmação.

Item valor
Supported Authentication Context Class References urn:example:psd2:sca

Supported Authentication Context Class References in Service Owner Console

Com as instruções acima, um cliente pode solicitar este servidor de autoração para autenticar os usuários de acordo com o acr.

Evoluindo o objeto de requisição que ficou incompleto

Vamos adicionar acr reivindicações para a carga preparada na seção anterior da seguinte forma.

payload-including-acr.txt

{
"redirect_uri":"https://client.example.org/cb/example.com",
"response_type":"code id_token",
"client_id":"591205987816490",
"scope":"openid payment",
"exp":15549730000,
"aud":"https://as.example.com",
"claims":{
  "id_token":{
    "acr":{
      "essential":true,
      "values":["urn:example:psd2:sca"]
    }
  }
},
"nonce":"n-0S6_WzA2Mj"
}

Gere outro JWT assinado com a nova carga útil. Aqui está um exemplo para gerar o JWT com mkjose. Digite/escolha valores para cada item e clique em “Gerar” para que você possa encontrar o JWT assinado na seção Saída.

Item Valor
Conteudo Colar conteúdo de payload-including-acr.txt
Algoritmo de assinatura Escolher EC256
Chave de assinatura Remova as duas primeiras linhas ("keys":, [) e as duas últimas linhas (], }), do conteúdo de es256_keyset.txt (como deve ser um JWK, não um conjunto JWK) e cole-o

Generating a signed JWT with mkjose (including acr in the payload)

Outro exemplo usando passo CLI é o seguinte.

cat payload-including-acr.txt | \
step crypto jws sign --jwks=es256_keyset.txt --kid=1

Neste documento, foi feito o resultado seguinte. Este novo será usado como um valor de request parâmetro em uma solicitação autorizada.

eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZ
XhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iL
AoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZ
XhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoiY2xhaW1zIjp7C
iAgImlkX3Rva2VuIjp7CiAgICAiYWNyIjp7CiAgICAgICJlc3NlbnRpYWwiOnRydWUsCiAgICAgICJ2Y
Wx1ZXMiOlsidXJuOmV4YW1wbGU6cHNkMjpzY2EiXQogICAgfQogIH0KfSwKIm5vbmNlIjoibi0wUzZfV
3pBMk1qIgp9Cg.b5rDSqaI3dh8n4A8hK4B5zSpnZNO_8--W-kTU03CNbCq1I_Vuf3w33ZVUhD0A-rla8
cTPlZ25keQBncGWafzOA

Testando a configuração com o objeto corrigido

Vamos substituir o valor de request parâmetro na seção anterior com o novo incluindo o acr reivindicar e fazer um pedido para /auth/authorization API outra vez.

curl -s -X POST https://api.authlete.com/api/auth/authorization \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"parameters": "redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj&request=<Request Object e.g. eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iLAoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZXhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoiY2xhaW1zIjp7CiAgImlkX3Rva2VuIjp7CiAgICAiYWNyIjp7CiAgICAgICJlc3NlbnRpYWwiOnRydWUsCiAgICAgICJ2YWx1ZXMiOlsidXJuOmV4YW1wbGU6cHNkMjpzY2EiXQogICAgfQogIH0KfSwKIm5vbmNlIjoibi0wUzZfV3pBMk1qIgp9Cg.b5rDSqaI3dh8n4A8hK4B5zSpnZNO_8--W-kTU03CNbCq1I_Vuf3w33ZVUhD0A-rla8cTPlZ25keQBncGWafzOA>"}' |jq
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"parameters\": \"redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj&request=<Request Object e.g. eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iLAoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZXhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoiY2xhaW1zIjp7CiAgImlkX3Rva2VuIjp7CiAgICAiYWNyIjp7CiAgICAgICJlc3NlbnRpYWwiOnRydWUsCiAgICAgICJ2YWx1ZXMiOlsidXJuOmV4YW1wbGU6cHNkMjpzY2EiXQogICAgfQogIH0KfSwKIm5vbmNlIjoibi0wUzZfV3pBMk1qIgp9Cg.b5rDSqaI3dh8n4A8hK4B5zSpnZNO_8--W-kTU03CNbCq1I_Vuf3w33ZVUhD0A-rla8cTPlZ25keQBncGWafzOA>\"}'

Authlete fará uma resposta (dobrada para legibilidade) assim.

{
  "type": "authorizationResponse",
  "resultCode": "A004001",
  "resultMessage": "[A004001] Authlete has successfully issued a ticket to the service
   (API Key = 174381609020) for the authorization request from the client
   (ID = 591205987816490). [response_type=code id_token, openid=true]",
[...]
  "ticket": "rjasCNvemUwamKP0G1h9Fh5Uo_3fgBfQsTF1PU4-GiE"
[...]

De acordo com o valor de resultMessage, Authlete aceitou o pedido de autorização. A resposta inclui ticket como esperado. Um servidor de autorização é armazenar o valor de ticket na sessão de login do usuário e tente autenticar o usuário e obter consentimento.

Uma vez concluído, o servidor fará uma solicitação ao Authlete’s /auth/authorization/issue API para gerar uma resposta de autorização. Neste documento, a solicitação de autorização mostrada na seção anterior incluiu response_type=code id_token. Assim, espera-se que Authlete gere uma resposta de autorização que inclua um código de autorização code e um token de ID id_token em fragmento.

/auth/authorization/issue API

Vamos supor que o servidor de auhtorização autentica o usuário, obtém consentimento e determina que o identificador exclusivo do usuário (subject) é testuser01. O servidor fará uma solicitação ao Authlete’s /auth/authorization/issue API com o ticket e o subject. Aqui está uma versão enrolada do pedido.

curl -s -X POST https://api.authlete.com/api/auth/authorization/issue \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"subject":"testuser01","ticket":"rjasCNvemUwamKP0G1h9Fh5Uo_3fgBfQsTF1PU4-GiE"}' | jq
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization/issue `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"subject\":\"testuser01\",\"ticket\":\"rjasCNvemUwamKP0G1h9Fh5Uo_3fgBfQsTF1PU4-GiE\"}'

Authlete faz a seguinte resposta (dobrada para legibilidade).

{
  "type": "authorizationIssueResponse",
  "resultCode": "A151301",
  "resultMessage": "[A151301] The algorithm
   ('HS256' for 'id_token_signed_response_alg')
    to sign the ID token is not allowed.",
[...]

De acordo com o valor de resultMessage, Authlete não permite hs256 (configurações padrão da Authlete) como um algoritmo de assinatura para token ID.

Isso se deve às disposições de segurança da FAPI. 8.6. Considerações do algoritmo JWS estados da seguinte forma.

devem utilizar algoritmos PS256 ou ES256;

Assim, um cliente e um servidor de autorização têm que empregar eS256 ou PS256 como algoritmo JWS. Neste documento, estaremos configurando Authlete para usar o ES256 para algoritmo de assinatura de token de ID.

Fazendo uma resposta de autorização compatível com FAPI

Alterando algoritmo de assinatura de token iD

Adicionando a chave de assunatura no ID Token

Agora vamos gerar um conjunto de chaves ES256 e registrá-lo na Authlete como uma chave de assinatura para o token ID. Também atualizaremos as configurações do cliente para especificar o ES256 como um algoritmo de assinatura para o cliente. Consulte o artigo a seguir na Base de Conhecimento Authlete para obter instruções.

Os parâmetros para mkjwk são os seguintes.

Item Valor
Guia EC (Curva Elíptica)
Curva P-256
Key usage Signing
Algorithm ES256 (ECDSA using P-256 and SHA-256)
Key ID Um valor arbitrário, por exemplo. 1

Registre o “keypair set” gerado para o serviço fazendo login no Console proprietário de serviços da Authlete https://so.authlete.com/, adicionando o conjunto de keypair à seção “JWK Set Content” na guia JWK Set e digite um valor de criança do conjunto de keypair, 1 neste exemplo, para a seção “ID Token Signature Key ID” na mesma página.

JWK Set Content and ID Token Signature Key ID in Service Owner Console

Em seguida, faça login no Console do Desenvolvedor para o serviço (https://cd.authlete.com/<API Key> por exemplo, https://cd.authlete.com/174381609020), clique em um link para o cliente, clique no botão “Editar” na parte inferior da página para tornar as configurações editáveis e vá para a guia ID Token. Deve haver seção de algoritmo de assinatura de token de ID. Escolha ES256 na lista suspensa e clique no botão “Atualizar”.

Essas configurações terão Authlete selecionar ES256 como um algoritmo de assinatura para emitir token de ID para este cliente e usar a chave ES256 registrada.

ID Token Signature Algorithm in Developer Console

Testando o id token criptografado usando ES256

Vamos verificar se Authlete funciona como esperado. Faça o mesmo pedido novamente para /auth/authorization API para obter um ticket inicialmente.

curl -s -X POST https://api.authlete.com/api/auth/authorization \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"parameters": "redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj&request=<Request Object e.g. eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iLAoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZXhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoiY2xhaW1zIjp7CiAgImlkX3Rva2VuIjp7CiAgICAiYWNyIjp7CiAgICAgICJlc3NlbnRpYWwiOnRydWUsCiAgICAgICJ2YWx1ZXMiOlsidXJuOmV4YW1wbGU6cHNkMjpzY2EiXQogICAgfQogIH0KfSwKIm5vbmNlIjoibi0wUzZfV3pBMk1qIgp9Cg.b5rDSqaI3dh8n4A8hK4B5zSpnZNO_8--W-kTU03CNbCq1I_Vuf3w33ZVUhD0A-rla8cTPlZ25keQBncGWafzOA>"}' | jq | grep ticket
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"parameters\": \"redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=<Client ID e.g. 591205987816490>&nonce=n-0S6_WzA2Mj&request=<Request Object e.g. eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iLAoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZXhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoiY2xhaW1zIjp7CiAgImlkX3Rva2VuIjp7CiAgICAiYWNyIjp7CiAgICAgICJlc3NlbnRpYWwiOnRydWUsCiAgICAgICJ2YWx1ZXMiOlsidXJuOmV4YW1wbGU6cHNkMjpzY2EiXQogICAgfQogIH0KfSwKIm5vbmNlIjoibi0wUzZfV3pBMk1qIgp9Cg.b5rDSqaI3dh8n4A8hK4B5zSpnZNO_8--W-kTU03CNbCq1I_Vuf3w33ZVUhD0A-rla8cTPlZ25keQBncGWafzOA>\"}'

Você deve ser capaz de obter uma resposta (dobrada para legibilidade) incluindo ticket.

{
[...]
  "resultMessage": "[A004001] Authlete has successfully issued a ticket to the service
   (API Key = 174381609020) for the authorization request from the client
   (ID = 591205987816490). [response_type=code id_token, openid=true]",
  "ticket": "3TzdZO2t8qXaQXIEUA5LLN106uVk5fpwL8_UDGlcwUQ"
[...]

Faça uma solicitação com o valor do ticket e um valor arbitrário de subject (testuser01 neste exemplo) para /auth/authorization/issue API.

curl -s -X POST https://api.authlete.com/api/auth/authorization/issue \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"subject":"testuser01","ticket":"3TzdZO2t8qXaQXIEUA5LLN106uVk5fpwL8_UDGlcwUQ"}' | jq
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization/issue `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"subject\":\"testuser01\",\"ticket\":\"3TzdZO2t8qXaQXIEUA5LLN106uVk5fpwL8_UDGlcwUQ\"}'

Authlete faz a seguinte resposta (dobrada para legibilidade).

{
  "type": "authorizationIssueResponse",
  "resultCode": "A040001",
  "resultMessage": "[A040001] The authorization request was processed successfully.",
  "accessTokenDuration": 0,
  "accessTokenExpiresAt": 0,
  "action": "LOCATION",
  "authorizationCode": "TSRAvPIp6V3RgPOs2O7FpPG1_7t6Xpc_kcIramz8gBQ",
  "idToken": "eyJraWQiOiIxIiwiYWxnIjoiRVMyNTYifQ.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjU5MTIwN
   Tk4NzgxNjQ5MCJdLCJjX2hhc2giOiJZQjloU01CWkJLdnFobnFaWWRWTXJnIiwiaXNzIjoiaHR0cHM6L
   y9hcy5leGFtcGxlLmNvbSIsImV4cCI6MTU3MjQxMDUyNiwiaWF0IjoxNTcyMzI0MTI2LCJub25jZSI6I
   m4tMFM2X1d6QTJNaiJ9.ZY5XK4TqAfcnLsMhkigNRpyM6CvwD7SdX-f9TQ18pwMUdh7eoGc6ijlfEnc4
   I3l0jYhlm22yuEeffV6XZhdL0A",
  "responseContent": "https://client.example.org/cb/example.com#
   code=TSRAvPIp6V3RgPOs2O7FpPG1_7t6Xpc_kcIramz8gBQ&
   id_token=eyJraWQiOiIxIiwiYWxnIjoiRVMyNTYifQ.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjU5MTIwN
   Tk4NzgxNjQ5MCJdLCJjX2hhc2giOiJZQjloU01CWkJLdnFobnFaWWRWTXJnIiwiaXNzIjoiaHR0cHM6L
   y9hcy5leGFtcGxlLmNvbSIsImV4cCI6MTU3MjQxMDUyNiwiaWF0IjoxNTcyMzI0MTI2LCJub25jZSI6I
   m4tMFM2X1d6QTJNaiJ9.ZY5XK4TqAfcnLsMhkigNRpyM6CvwD7SdX-f9TQ18pwMUdh7eoGc6ijlfEnc4
   I3l0jYhlm22yuEeffV6XZhdL0A"
}

De acordo com o valor de resultMessage, Authlete processou com sucesso o pedido. Há um token de ID emitido e um código de autorização em idToken e authorizationCode respectivamente, e conteúdo de resposta HTTP em responseContent. O conteúdo inclui esses tokens e códigos como fragmento e destina-se a ser enviado de um servidor de autorização para um cliente como resposta de autorização.

Uma vez que o cliente recebeu a resposta do servidor de autorização, ele verificará o token de ID. Se a verificação for feita com sucesso, ela extrairá c_hash do token de ID e usá-lo para verificar o código de autorização. Se a segunda verificação também for feita com sucesso, o cliente fará uma solicitação de token com o código para o servidor de autoração. O servidor de autorização fará uma solicitação, incluindo a solicitação de token, para Authlete /auth/token API para que a API gere uma resposta de token que deve incluir um token de acesso.

/auth/token API

Aqui está uma versão curl do pedido para /auth/token API.

curl -s -X POST https://api.authlete.com/api/auth/token \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"clientId":"<Client ID e.g. 591205987816490>","clientSecret":"<Client Secret e7iqzq7WE8Kg00yepYnpMTjvDnAnBlq5nfA9DDQLkiYkPQBV6Lr8sLhn7DhUJd17i0O6TwQ2hKFeDAYuU160Vg>","parameters": "grant_type=authorization_code&redirect_uri=https://client.example.org/cb/example.com&code=<Code e.g. TSRAvPIp6V3RgPOs2O7FpPG1_7t6Xpc_kcIramz8gBQ>"}'|jq
curl.exe -s -X POST https://api.authlete.com/api/auth/token `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"clientId\":\"<Client ID e.g. 591205987816490>\",\"clientSecret\":\"<Client Secret e7iqzq7WE8Kg00yepYnpMTjvDnAnBlq5nfA9DDQLkiYkPQBV6Lr8sLhn7DhUJd17i0O6TwQ2hKFeDAYuU160Vg>\",\"parameters\": \"grant_type=authorization_code&redirect_uri=https://client.example.org/cb/example.com&code=<Code e.g. TSRAvPIp6V3RgPOs2O7FpPG1_7t6Xpc_kcIramz8gBQ>\"}'

Authlete faz a seguinte resposta de erro (dobrada para legibilidade).

{
  "type": "tokenResponse",
  "resultCode": "A157301",
  "resultMessage": "[A157301] The client type of the client is 'confidential'
   but the client authentication method is 'none'.",
  "accessTokenDuration": 0,
  "accessTokenExpiresAt": 0,
  "action": "INVALID_CLIENT",
  "clientId": 591205987816490,
  "clientIdAliasUsed": false,
  "grantType": "AUTHORIZATION_CODE",
  "refreshTokenDuration": 0,
  "refreshTokenExpiresAt": 0,
  "responseContent": "{\"error_description\":\"[A157301] The client type
   of the client is 'confidential' but the client authentication method is 'none'.\",
   \"error\":\"invalid_client\",\"error_uri\":\"https://docs.authlete.com/#A157301\"}"
}

De acordo com o valor de resultMessage, o método de autenticação do cliente de none, que é o valor padrão da Authlete, não é permitido para clientes confidenciais.

Isso se deve às disposições de segurança da FAPI. 5.2 Leia e escreva as disposições de segurança da API / 5.2.2. Servidor de autorização estados da seguinte forma.

deve autenticar o cliente confidencial no ponto final do token usando um dos seguintes métodos (isso substitui a cláusula 5.2.2.2.4 da FAPI):

  1. TLS mútuo para autenticação de clientes de Aauth conforme especificado na seção 2 de [MTLS];

  2. private_key_jwt conforme especificado na seção 9 de [OIDC];

Assim, você tem que usar o OAuth 2.0 Token Binding [OAUTB] ou OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens [MTLS] em um ambiente compatível com FAPI. Ou seja, outros métodos como none, client_secret_basic que é popular para clientes confidenciais, ou seja, um servidor de autorização não deve empregá-los para autenticar clientes.

Neste documento, teremos Authlete usar o último e Método PKI Mutual-TLS (tls_client_auth) definido no método.

Fazendo uma solicitação de token compatível com FAPI

Configuração de autenticação do cliente TLS

Vamos configurar o serviço e as configurações do cliente para ativar a autenticação do cliente TLS.

Configurando o serviço para autenticar clientes via TLS

Faça login no console proprietário de serviços da Authlete https://so.authlete.com/, clique no botão “Editar” na parte inferior da página para tornar as configurações editáveis e vá para a guia Autorização. Deve haver seção Token Endpoint.

Verifique a caixa em Métodos de Autenticação de Cliente suportados e clique no botão “Atualizar” na parte inferior da página. Pressione “OK” em um diálogo para confirmação.

Item Valor
Métodos de autenticação de clientes suportados TLS_CLIENT_AUTH

Supported Client Authentication Methods in Service Owner Console

Configurações do client para autenticação mútua via TLS

Faça login no Console do Desenvolvedor para o serviço (https://cd.authlete.com/<API Key> por exemplo, https://cd.authlete.com/174381609020) e configure as configurações do cliente na seção “Ponto final de token” na guia Autorização da seguinte forma.

Item Valor
Método de autenticação do cliente TLS_CLIENT_AUTH

Client Authentication Method in Developer Console

Item Valor
Cliente TLS Auth Assunto DN CN=client.example.org, O=Client, L=Chiyoda-ku, ST=Tokyo, C=JP

TLS Client Auth Subject DN in Developer Console

Com essas configurações acima, Authlete suportará a autenticação TLS mútua para autenticação do cliente e aplicará o método para processar solicitações de token do cliente. Assunto DN CN=client.example.org, ... é usado como o identificador do cliente.

Gerando certificados auto assinados

Você tem que preparar um certificado digital para que o cliente seja autenticado pelo servidor de autorização. O assunto DN do certificado deve ser o mesmo que foi especificado na seção anterior, CN=client.example.org, ... neste documento.

O exemplo a seguir ilustra que gerar um auto-assinado certificado usando OpenSSL.

  • Gerando uma chave privada
$ openssl genrsa 2048  > private_key_nopass.pem
Generating RSA private key, 2048 bit long modulus
...............+++
.......................+++
e is 65537 (0x10001)
  • Gerando uma RSE
    • Usando CN=client.example.org, O=Client, L=Chiyoda-ku, ST=Tokyo, C=JP como Sujeito DN
$ openssl req -new -key private_key_nopass.pem -out server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) []:Chiyoda-ku
Organization Name (eg, company) []:Client
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:client.example.org
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
$ cat server.csr
-----BEGIN CERTIFICATE REQUEST-----
MIICpTCCAY0CAQAwYDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRMwEQYD
VQQHDApDaGl5b2RhLWt1MQ8wDQYDVQQKDAZDbGllbnQxGzAZBgNVBAMMEmNsaWVu
[...]
r4MUVOwPNWOM6UGYQZwjvtJ2rmKr8cQrbfvbcFiY4s6lLQGOz5yLzmO8GUdmfzUd
p5BW1iL+SpjS
-----END CERTIFICATE REQUEST-----
  • Gerando um certificado
$ openssl x509 -days 365 -req -signkey private_key_nopass.pem -in server.csr -out server.crt
Signature ok
subject=/C=JP/ST=Tokyo/L=Chiyoda-ku/O=Client/CN=client.example.org
Getting Private key

O seguinte é um certificado gerado neste exemplo.

server.crt

-----BEGIN CERTIFICATE-----
MIIDPDCCAiQCCQDWNMOIuzwDfzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJK
UDEOMAwGA1UECAwFVG9reW8xEzARBgNVBAcMCkNoaXlvZGEta3UxDzANBgNVBAoM
BkNsaWVudDEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUub3JnMB4XDTE5MTAyODA3
MjczMFoXDTIwMTAyNzA3MjczMFowYDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRv
a3lvMRMwEQYDVQQHDApDaGl5b2RhLWt1MQ8wDQYDVQQKDAZDbGllbnQxGzAZBgNV
BAMMEmNsaWVudC5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAK2Oyc+BV4N5pYcp47opUwsb2NaJq4X+d5Itq8whpFlZ9uCCHzF5TWSF
XrpYscOp95veGPF42eT1grfxYyvjFotE76caHhBLCkIbBh6Vf222IGMwwBbSZfO9
J3eURtEADBvsZ117HkPVdjYqvt3Pr4RxdR12zG1TcBAoTLGchyr8nBqRADFhUTCL
msYaz1ADiQ/xbJN7VUNQpKhzRWHCdYS03HpbGjYCtAbl9dJnH2EepNF0emGiSPFq
df6taToyCr7oZjM7ufmKPjiiEDbeSYTf6kbPNmmjtoPNNLeejHjP9p0IYx7l0Gkj
mx4kSMLp4vSDftrFgGfcxzaMmKBsosMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
qzdDYbntFLPBlbwAQlpwIjvmvwzvkQt6qgZ9Y0oMAf7pxq3i9q7W1bDol0UF4pIM
z3urEJCHO8w18JRlfOnOENkcLLLntrjOUXuNkaCDLrnv8pnp0yeTQHkSpsyMtJi9
R6r6JT9V57EJ/pWQBgKlN6qMiBkIvX7U2hEMmhZ00h/E5xMmiKbySBiJV9fBzDRf
mAy1p9YEgLsEMLnGjKHTok+hd0BLvcmXVejdUsKCg84F0zqtXEDXLCiKcpXCeeWv
lmmXxC5PH/GEMkSPiGSR7+b1i0sSotsq+M3hbdwabpJ6nQLLbKkFSGcsQ87yL+gr
So6zun26vAUJTu1o9CIjxw==
-----END CERTIFICATE-----

Testando a autenticação mútua usando TLS

Vamos verificar se Authlete funciona como esperado. Executar o mesmo procedimento novamente.

  1. Faça uma solicitação para /auth/authorization API e obter um valor de ticket a partir de uma resposta
  2. Faça uma solicitação para /auth/authorization/issue API e obter um valor de authorizationCode a partir de uma resposta
  3. Faça uma solicitação com a seguinte modificação para /auth/token API * Adicionar clientCertificate parâmetro com o certificado do cliente como seu valor * Remover clientSecret parâmetro (não é mais necessário, pois a autenticação TLS mútua é eficaz)

Aqui está uma versão curl do pedido para /auth/token API.

curl -s -X POST https://api.authlete.com/api/auth/token \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"clientId":"<Client ID e.g. 591205987816490>","parameters": "grant_type=authorization_code&redirect_uri=https://client.example.org/cb/example.com&code=<Code e.g. TSRAvPIp6V3RgPOs2O7FpPG1_7t6Xpc_kcIramz8gBQ>", "clientCertificate":"-----BEGIN CERTIFICATE-----
MIIDPDCCAiQCCQDWNMOIuzwDfzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJK
UDEOMAwGA1UECAwFVG9reW8xEzARBgNVBAcMCkNoaXlvZGEta3UxDzANBgNVBAoM
BkNsaWVudDEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUub3JnMB4XDTE5MTAyODA3
MjczMFoXDTIwMTAyNzA3MjczMFowYDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRv
a3lvMRMwEQYDVQQHDApDaGl5b2RhLWt1MQ8wDQYDVQQKDAZDbGllbnQxGzAZBgNV
BAMMEmNsaWVudC5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAK2Oyc+BV4N5pYcp47opUwsb2NaJq4X+d5Itq8whpFlZ9uCCHzF5TWSF
XrpYscOp95veGPF42eT1grfxYyvjFotE76caHhBLCkIbBh6Vf222IGMwwBbSZfO9
J3eURtEADBvsZ117HkPVdjYqvt3Pr4RxdR12zG1TcBAoTLGchyr8nBqRADFhUTCL
msYaz1ADiQ/xbJN7VUNQpKhzRWHCdYS03HpbGjYCtAbl9dJnH2EepNF0emGiSPFq
df6taToyCr7oZjM7ufmKPjiiEDbeSYTf6kbPNmmjtoPNNLeejHjP9p0IYx7l0Gkj
mx4kSMLp4vSDftrFgGfcxzaMmKBsosMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
qzdDYbntFLPBlbwAQlpwIjvmvwzvkQt6qgZ9Y0oMAf7pxq3i9q7W1bDol0UF4pIM
z3urEJCHO8w18JRlfOnOENkcLLLntrjOUXuNkaCDLrnv8pnp0yeTQHkSpsyMtJi9
R6r6JT9V57EJ/pWQBgKlN6qMiBkIvX7U2hEMmhZ00h/E5xMmiKbySBiJV9fBzDRf
mAy1p9YEgLsEMLnGjKHTok+hd0BLvcmXVejdUsKCg84F0zqtXEDXLCiKcpXCeeWv
lmmXxC5PH/GEMkSPiGSR7+b1i0sSotsq+M3hbdwabpJ6nQLLbKkFSGcsQ87yL+gr
So6zun26vAUJTu1o9CIjxw==
-----END CERTIFICATE-----"}'|jq
curl.exe -s -X POST https://api.authlete.com/api/auth/token `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"clientId\":\"<Client ID e.g. 591205987816490>\",\"clientSecret\":\"<Client Secret e7iqzq7WE8Kg00yepYnpMTjvDnAnBlq5nfA9DDQLkiYkPQBV6Lr8sLhn7DhUJd17i0O6TwQ2hKFeDAYuU160Vg>\",\"parameters\": \"grant_type=authorization_code&redirect_uri=https://client.example.org/cb/example.com&code=<Code e.g. TSRAvPIp6V3RgPOs2O7FpPG1_7t6Xpc_kcIramz8gBQ>\",\"clientCertificate\":\"-----BEGIN CERTIFICATE-----
MIIDPDCCAiQCCQDWNMOIuzwDfzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJK
UDEOMAwGA1UECAwFVG9reW8xEzARBgNVBAcMCkNoaXlvZGEta3UxDzANBgNVBAoM
BkNsaWVudDEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUub3JnMB4XDTE5MTAyODA3
MjczMFoXDTIwMTAyNzA3MjczMFowYDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRv
a3lvMRMwEQYDVQQHDApDaGl5b2RhLWt1MQ8wDQYDVQQKDAZDbGllbnQxGzAZBgNV
BAMMEmNsaWVudC5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAK2Oyc+BV4N5pYcp47opUwsb2NaJq4X+d5Itq8whpFlZ9uCCHzF5TWSF
XrpYscOp95veGPF42eT1grfxYyvjFotE76caHhBLCkIbBh6Vf222IGMwwBbSZfO9
J3eURtEADBvsZ117HkPVdjYqvt3Pr4RxdR12zG1TcBAoTLGchyr8nBqRADFhUTCL
msYaz1ADiQ/xbJN7VUNQpKhzRWHCdYS03HpbGjYCtAbl9dJnH2EepNF0emGiSPFq
df6taToyCr7oZjM7ufmKPjiiEDbeSYTf6kbPNmmjtoPNNLeejHjP9p0IYx7l0Gkj
mx4kSMLp4vSDftrFgGfcxzaMmKBsosMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
qzdDYbntFLPBlbwAQlpwIjvmvwzvkQt6qgZ9Y0oMAf7pxq3i9q7W1bDol0UF4pIM
z3urEJCHO8w18JRlfOnOENkcLLLntrjOUXuNkaCDLrnv8pnp0yeTQHkSpsyMtJi9
R6r6JT9V57EJ/pWQBgKlN6qMiBkIvX7U2hEMmhZ00h/E5xMmiKbySBiJV9fBzDRf
mAy1p9YEgLsEMLnGjKHTok+hd0BLvcmXVejdUsKCg84F0zqtXEDXLCiKcpXCeeWv
lmmXxC5PH/GEMkSPiGSR7+b1i0sSotsq+M3hbdwabpJ6nQLLbKkFSGcsQ87yL+gr
So6zun26vAUJTu1o9CIjxw==
-----END CERTIFICATE-----\"}'

Authlete faz a seguinte resposta com cautela (dobrada para legibilidade).

{
  "type": "tokenResponse",
  "resultCode": "A152305",
  "resultMessage": "[A152305] The service and the client are not configured
   so that the required Holder of Key methods are performed.",
  "accessToken": "RCqjF4tlffJ7-n92sAEFQNIwrRm0syOUrBu0cNLAIJU",
  "accessTokenDuration": 0,
  "accessTokenExpiresAt": 0,
  "action": "BAD_REQUEST",
  "clientId": 591205987816490,
  "clientIdAliasUsed": false,
  "grantType": "AUTHORIZATION_CODE",
  "idToken": "eyJraWQiOiIxIiwiYWxnIjoiRVMyNTYifQ.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjU5MTIwN
  Tk4NzgxNjQ5MCJdLCJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tIiwiZXhwIjoxNTcyNDEyMTcwL
  CJpYXQiOjE1NzIzMjU3NzAsIm5vbmNlIjoibi0wUzZfV3pBMk1qIn0.x4XmPTh698AbNEjCaNcD5k54q
  S249BSPkc9EkwZuUI17AL8z593GYTg3GVQQdhF9k0HYLRA17c3m39OxYDrx3g",
  "refreshToken": "jy5lN7TXZrAlIfgFbOaMMkzDtoJUu4prBtNa3HcoRRE",
  "refreshTokenDuration": 0,
  "refreshTokenExpiresAt": 0,
  "responseContent": "{\"error_description\":\"[A152305] The service and the client are
   not configured so that the required Holder of Key methods are performed.\",
   \"error\":\"invalid_request\",\"error_uri\":\"https://docs.authlete.com/#A152305\"}"
}

De acordo com o valor de resultMessage, Authlete não executou o método “Holder of Key”, que é obrigatório para cumprir as disposições de segurança da FAPI, enquanto um token de acesso foi emitido. Assim, o token de acesso emitido não está vinculado ao certificado de cliente TLS do cliente.

Fazendo uma resposta de token compatível com FAPI

Suporte de configuração de tecla

Configurações do serviço relativo ao access token

Faça login no console proprietário de serviços da Authlete https://so.authlete.com/, clique no botão “Editar” na parte inferior da página para tornar as configurações editáveis e vá para a guia Token. Deve haver seção Access Token. Escolha a seguinte opção para tokens de acesso vinculados ao certificado de cliente TLS.

Item Valor
Tokens de acesso vinculados ao certificado de cliente TLS Escolher Supported

TLS Client Certificate Bound Access Tokens in Service Owner Console

Configurações do cliente relativo ao access token

Faça login no Console do Desenvolvedor para o serviço (https://cd.authlete.com/<API Key> por exemplo, https://cd.authlete.com/174381609020), clique em um link para o cliente, clique no botão “Editar” na parte inferior da página para tornar as configurações editáveis e vá para a guia Básico. Escolha a seguinte opção para tokens de acesso vinculados ao certificado de cliente TLS.

Item Valor
Tokens de acesso vinculados ao certificado de cliente TLS Escolher Enabled

TLS Client Certificate Bound Access Tokens in Developer Console

Parabéns! Finalmente, você terminou a configuração do Authlete para suportar um servidor de autorização compatível com FAPI.

Um exemplo completo de caminhar

FAPI-compliant token granting process and API access flows using Authlete

Uma vez que a configuração é feita, você pode verificar se o Authlete funciona como esperado. Faça solicitações, que são as mesmas da seção anterior, Para /auth/authorization API, /auth/authorization/issue API e /auth/token API.

Além dessas três solicitações, faça outra solicitação para /auth/introspection API para ver se o token de acesso usado para solicitações de API a um servidor de recursos está vinculado ao certificado de cliente TLS do cliente.

Pedido de autorização

curl -s -X POST https://api.authlete.com/api/auth/authorization -u '174381609020:LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k' -H 'Content-Type: application/json' -d '{"parameters": "redirect_uri=https://client.example.org/cb/example.com&scope=openid+payment&response_type=code+id_token&client_id=591205987816490&nonce=n-0S6_WzA2Mj&request=eyJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.ewoicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5vcmcvY2IvZXhhbXBsZS5jb20iLAoicmVzcG9uc2VfdHlwZSI6ImNvZGUgaWRfdG9rZW4iLAoiY2xpZW50X2lkIjoiNTkxMjA1OTg3ODE2NDkwIiwKInNjb3BlIjoib3BlbmlkIHBheW1lbnQiLAoiZXhwIjoxNTU0OTczMDAwMCwKImF1ZCI6Imh0dHBzOi8vYXMuZXhhbXBsZS5jb20iLAoiY2xhaW1zIjp7CiAgImlkX3Rva2VuIjp7CiAgICAiYWNyIjp7CiAgICAgICJlc3NlbnRpYWwiOnRydWUsCiAgICAgICJ2YWx1ZXMiOlsidXJuOm1hY2U6aW5jb21tb246aWFwOnNpbHZlciJdCiAgICB9CiAgfQp9LAoibm9uY2UiOiJuLTBTNl9XekEyTWoiCn0K.50gewunAqCITD6p2kI52GDXdUgQP-EzLDjjjoDT9C4zY8YCKgLzN7sR2ZvkAQ_pimLpwFh2QYjjyPskvvtnC9g"}' |jq|grep ticket
  • Resposta (dobrada para legibilidade)
{
[...]
  "resultMessage": "[A004001] Authlete has successfully issued a ticket
   to the service (API Key = 174381609020) for the authorization request
  from the client (ID = 591205987816490). [response_type=code id_token, openid=true]",
  [...]
  "ticket": "b0JGD-ZkT8ElBGw2ck-T-t87Z033jXvhqC2omPT1bQ4"
  [...]

Resposta de autorização

curl -s -X POST https://api.authlete.com/api/auth/authorization/issue -u '174381609020:LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k' -H 'Content-Type: application/json' -d '{"subject":"testuser01","ticket":"b0JGD-ZkT8ElBGw2ck-T-t87Z033jXvhqC2omPT1bQ4"}' | jq
  • Resposta (dobrada para legibilidade)
{
  "type": "authorizationIssueResponse",
  "resultCode": "A040001",
  "resultMessage": "[A040001] The authorization request was processed successfully.",
  "accessTokenDuration": 0,
  "accessTokenExpiresAt": 0,
  "action": "LOCATION",
  "authorizationCode": "DxiKC0cOc_46nzVjgr41RWBQtMDrAvc0BUbMJ_v7I70",
  "idToken": "eyJraWQiOiIxIiwiYWxnIjoiRVMyNTYifQ.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjU5MTIwN
  Tk4NzgxNjQ5MCJdLCJjX2hhc2giOiJqR2kyOElvYm5HcjNNQ3Y0UUVQRTNnIiwiaXNzIjoiaHR0cHM6L
  y9hcy5leGFtcGxlLmNvbSIsImV4cCI6MTU3MjQxMjY4MiwiaWF0IjoxNTcyMzI2MjgyLCJub25jZSI6I
  m4tMFM2X1d6QTJNaiJ9.1PFmc0gAsBWtLBriq3z9a4Tsi_ioEYlOqOYbicGEXWIS1WGX5ffGOyZNSzVB
  MamZbltZmSys0jlYmmYYLqgGsg",
  "responseContent": "https://client.example.org/cb/example.com#
  code=DxiKC0cOc_46nzVjgr41RWBQtMDrAvc0BUbMJ_v7I70&
  id_token=eyJraWQiOiIxIiwiYWxnIjoiRVMyNTYifQ.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjU5MTIwN
  Tk4NzgxNjQ5MCJdLCJjX2hhc2giOiJqR2kyOElvYm5HcjNNQ3Y0UUVQRTNnIiwiaXNzIjoiaHR0cHM6L
  y9hcy5leGFtcGxlLmNvbSIsImV4cCI6MTU3MjQxMjY4MiwiaWF0IjoxNTcyMzI2MjgyLCJub25jZSI6I
  m4tMFM2X1d6QTJNaiJ9.1PFmc0gAsBWtLBriq3z9a4Tsi_ioEYlOqOYbicGEXWIS1WGX5ffGOyZNSzVB
  MamZbltZmSys0jlYmmYYLqgGsg"
}

Solicitação de token e resposta de token

curl -s -X POST https://api.authlete.com/api/auth/token \
-u '174381609020:LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k' \
-H 'Content-Type: application/json' \
-d '{"clientId":"591205987816490","parameters": "grant_type=authorization_code&redirect_uri=https://client.example.org/cb/example.com&code=DxiKC0cOc_46nzVjgr41RWBQtMDrAvc0BUbMJ_v7I70","clientCertificate":"-----BEGIN CERTIFICATE-----
MIIDPDCCAiQCCQDWNMOIuzwDfzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJK
UDEOMAwGA1UECAwFVG9reW8xEzARBgNVBAcMCkNoaXlvZGEta3UxDzANBgNVBAoM
BkNsaWVudDEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUub3JnMB4XDTE5MTAyODA3
MjczMFoXDTIwMTAyNzA3MjczMFowYDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRv
a3lvMRMwEQYDVQQHDApDaGl5b2RhLWt1MQ8wDQYDVQQKDAZDbGllbnQxGzAZBgNV
BAMMEmNsaWVudC5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAK2Oyc+BV4N5pYcp47opUwsb2NaJq4X+d5Itq8whpFlZ9uCCHzF5TWSF
XrpYscOp95veGPF42eT1grfxYyvjFotE76caHhBLCkIbBh6Vf222IGMwwBbSZfO9
J3eURtEADBvsZ117HkPVdjYqvt3Pr4RxdR12zG1TcBAoTLGchyr8nBqRADFhUTCL
msYaz1ADiQ/xbJN7VUNQpKhzRWHCdYS03HpbGjYCtAbl9dJnH2EepNF0emGiSPFq
df6taToyCr7oZjM7ufmKPjiiEDbeSYTf6kbPNmmjtoPNNLeejHjP9p0IYx7l0Gkj
mx4kSMLp4vSDftrFgGfcxzaMmKBsosMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
qzdDYbntFLPBlbwAQlpwIjvmvwzvkQt6qgZ9Y0oMAf7pxq3i9q7W1bDol0UF4pIM
z3urEJCHO8w18JRlfOnOENkcLLLntrjOUXuNkaCDLrnv8pnp0yeTQHkSpsyMtJi9
R6r6JT9V57EJ/pWQBgKlN6qMiBkIvX7U2hEMmhZ00h/E5xMmiKbySBiJV9fBzDRf
mAy1p9YEgLsEMLnGjKHTok+hd0BLvcmXVejdUsKCg84F0zqtXEDXLCiKcpXCeeWv
lmmXxC5PH/GEMkSPiGSR7+b1i0sSotsq+M3hbdwabpJ6nQLLbKkFSGcsQ87yL+gr
So6zun26vAUJTu1o9CIjxw==
-----END CERTIFICATE-----"}' |jq
  • Resposta (dobrada para legibilidade)
{
  "type": "tokenResponse",
  "resultCode": "A050001",
  "resultMessage": "[A050001] The token request (grant_type=authorization_code)
   was processed successfully.",
  "accessToken": "SUtEVc3Tj3D3xOdysQtssQxe9egAhI4fimexNVMjRyU",
  "accessTokenDuration": 86400,
  "accessTokenExpiresAt": 1572412769390,
  "action": "OK",
  "clientId": 591205987816490,
  "clientIdAliasUsed": false,
  "grantType": "AUTHORIZATION_CODE",
  "idToken": "eyJraWQiOiIxIiwiYWxnIjoiRVMyNTYifQ.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjU5MTIwN
  Tk4NzgxNjQ5MCJdLCJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tIiwiZXhwIjoxNTcyNDEyNzY5L
  CJpYXQiOjE1NzIzMjYzNjksIm5vbmNlIjoibi0wUzZfV3pBMk1qIn0.9EQojck-Cf2hnKAZWR164kr21
  o5lPKehvIHyViZgRg4CY_ZGmnyFooG4FCwlZxu-QOTtaDCffCsuCdz4GqknTA",
  "refreshToken": "tXZjYfoK35I-djg9V3n6s58zsrVqRIzTNMXKIS_wkj8",
  "refreshTokenDuration": 864000,
  "refreshTokenExpiresAt": 1573190369390,
  "responseContent": "{\"access_token\":\"SUtEVc3Tj3D3xOdysQtssQxe9egAhI4fimexNVMjRyU\",
  \"refresh_token\":\"tXZjYfoK35I-djg9V3n6s58zsrVqRIzTNMXKIS_wkj8\",\"scope\":\"openid payment\",
  \"id_token\":\"eyJraWQiOiIxIiwiYWxnIjoiRVMyNTYifQ.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjU5MTIwN
  Tk4NzgxNjQ5MCJdLCJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tIiwiZXhwIjoxNTcyNDEyNzY5L
  CJpYXQiOjE1NzIzMjYzNjksIm5vbmNlIjoibi0wUzZfV3pBMk1qIn0.9EQojck-Cf2hnKAZWR164kr21
  o5lPKehvIHyViZgRg4CY_ZGmnyFooG4FCwlZxu-QOTtaDCffCsuCdz4GqknTA\",
  \"token_type\":\"Bearer\",\"expires_in\":86400}",
  "scopes": [
    "openid",
    "payment"
  ],
  "subject": "testuser01"
}

Solicitação de API

Após o procedimento acima, temos um token de acesso cujo valor é SUtEVc3Tj3D3xOdysQtssQxe9egAhI4fimexNVMjRyU neste exemplo.

Vamos supor que o servidor de recursos receba uma solicitação de API, incluindo o valor como o token de acesso, do cliente. O token no pedido estaria em Authorization: Bearer cabeçalho.

O servidor de recursos é para verificar o token e obter informações relacionadas com ele, fazendo um solicitação para /auth/introspection API. O servidor de recursos também incluirá o certificado do cliente, que deve ser capaz de obter a partir de TLS mútuo comunicação para a solicitação de API, a pedido à Authlete.

/auth/introspection API

curl -s -X POST https://api.authlete.com/api/auth/introspection \
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' \
-H 'Content-Type: application/json' \
-d '{"token":"SUtEVc3Tj3D3xOdysQtssQxe9egAhI4fimexNVMjRyU","clientCertificate":"-----BEGIN CERTIFICATE-----
MIIDPDCCAiQCCQDWNMOIuzwDfzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJK
UDEOMAwGA1UECAwFVG9reW8xEzARBgNVBAcMCkNoaXlvZGEta3UxDzANBgNVBAoM
BkNsaWVudDEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUub3JnMB4XDTE5MTAyODA3
MjczMFoXDTIwMTAyNzA3MjczMFowYDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRv
a3lvMRMwEQYDVQQHDApDaGl5b2RhLWt1MQ8wDQYDVQQKDAZDbGllbnQxGzAZBgNV
BAMMEmNsaWVudC5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAK2Oyc+BV4N5pYcp47opUwsb2NaJq4X+d5Itq8whpFlZ9uCCHzF5TWSF
XrpYscOp95veGPF42eT1grfxYyvjFotE76caHhBLCkIbBh6Vf222IGMwwBbSZfO9
J3eURtEADBvsZ117HkPVdjYqvt3Pr4RxdR12zG1TcBAoTLGchyr8nBqRADFhUTCL
msYaz1ADiQ/xbJN7VUNQpKhzRWHCdYS03HpbGjYCtAbl9dJnH2EepNF0emGiSPFq
df6taToyCr7oZjM7ufmKPjiiEDbeSYTf6kbPNmmjtoPNNLeejHjP9p0IYx7l0Gkj
mx4kSMLp4vSDftrFgGfcxzaMmKBsosMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
qzdDYbntFLPBlbwAQlpwIjvmvwzvkQt6qgZ9Y0oMAf7pxq3i9q7W1bDol0UF4pIM
z3urEJCHO8w18JRlfOnOENkcLLLntrjOUXuNkaCDLrnv8pnp0yeTQHkSpsyMtJi9
R6r6JT9V57EJ/pWQBgKlN6qMiBkIvX7U2hEMmhZ00h/E5xMmiKbySBiJV9fBzDRf
mAy1p9YEgLsEMLnGjKHTok+hd0BLvcmXVejdUsKCg84F0zqtXEDXLCiKcpXCeeWv
lmmXxC5PH/GEMkSPiGSR7+b1i0sSotsq+M3hbdwabpJ6nQLLbKkFSGcsQ87yL+gr
So6zun26vAUJTu1o9CIjxw==
-----END CERTIFICATE-----"}'|jq
curl.exe -s -X POST https://api.authlete.com/api/auth/introspection `
-u '<API Key e.g. 174381609020>:<API Secret e.g. LszYEVDLM5Bu4lRjO9Vaj0tMSMVerWiPf_zcdy-vu4k>' `
-H 'Content-Type: application/json' `
-d '{\"token\":\"SUtEVc3Tj3D3xOdysQtssQxe9egAhI4fimexNVMjRyU\",\"clientCertificate\":\"-----BEGIN CERTIFICATE-----
MIIDPDCCAiQCCQDWNMOIuzwDfzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJK
UDEOMAwGA1UECAwFVG9reW8xEzARBgNVBAcMCkNoaXlvZGEta3UxDzANBgNVBAoM
BkNsaWVudDEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUub3JnMB4XDTE5MTAyODA3
MjczMFoXDTIwMTAyNzA3MjczMFowYDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRv
a3lvMRMwEQYDVQQHDApDaGl5b2RhLWt1MQ8wDQYDVQQKDAZDbGllbnQxGzAZBgNV
BAMMEmNsaWVudC5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAK2Oyc+BV4N5pYcp47opUwsb2NaJq4X+d5Itq8whpFlZ9uCCHzF5TWSF
XrpYscOp95veGPF42eT1grfxYyvjFotE76caHhBLCkIbBh6Vf222IGMwwBbSZfO9
J3eURtEADBvsZ117HkPVdjYqvt3Pr4RxdR12zG1TcBAoTLGchyr8nBqRADFhUTCL
msYaz1ADiQ/xbJN7VUNQpKhzRWHCdYS03HpbGjYCtAbl9dJnH2EepNF0emGiSPFq
df6taToyCr7oZjM7ufmKPjiiEDbeSYTf6kbPNmmjtoPNNLeejHjP9p0IYx7l0Gkj
mx4kSMLp4vSDftrFgGfcxzaMmKBsosMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
qzdDYbntFLPBlbwAQlpwIjvmvwzvkQt6qgZ9Y0oMAf7pxq3i9q7W1bDol0UF4pIM
z3urEJCHO8w18JRlfOnOENkcLLLntrjOUXuNkaCDLrnv8pnp0yeTQHkSpsyMtJi9
R6r6JT9V57EJ/pWQBgKlN6qMiBkIvX7U2hEMmhZ00h/E5xMmiKbySBiJV9fBzDRf
mAy1p9YEgLsEMLnGjKHTok+hd0BLvcmXVejdUsKCg84F0zqtXEDXLCiKcpXCeeWv
lmmXxC5PH/GEMkSPiGSR7+b1i0sSotsq+M3hbdwabpJ6nQLLbKkFSGcsQ87yL+gr
So6zun26vAUJTu1o9CIjxw==
-----END CERTIFICATE-----\"}'
  • Resposta (dobrada para legibilidade)
{
  "type": "introspectionResponse",
  "resultCode": "A056001",
  "resultMessage": "[A056001] The access token is valid.",
  "action": "OK",
  "certificateThumbprint": "cBNP0zNH0fkcIQdVHdB8GDQAbaZyIjKXB0EVRTByJMU",
  "clientId": 591205987816490,
  "clientIdAliasUsed": false,
  "existent": true,
  "expiresAt": 1572412769000,
  "refreshable": true,
  "responseContent": "Bearer error=\"invalid_request\"",
  "scopes": [
    "openid",
    "payment"
  ],
  "subject": "testuser01",
  "sufficient": true,
  "usable": true
}

O servidor de recursos agora é capaz de descobrir que o token de acesso do cliente foi verificado e obter as informações associadas com o token, como assunto e escopos.

Conclusão

Neste tutorial, revisamos as disposições de segurança definidas em API de nível financeiro - Parte 2: Ler e Escrever Perfil de Segurança da API e instruções de configuração da Authlete através de etapas para a construção de um servidor de autorização compatível com FAPI.