Versões comparadas
Chave
- Esta linha foi adicionada.
- Esta linha foi removida.
- A formatação mudou.
Introdução
Para reforçar a segurança do Web Service padrão REST do Protheus, está disponível o modelo de autenticação através de token de acesso, também conhecido como Bearer token.
A obtenção desse token de acesso é realizada através de uma requisição à uma API (Application Programming Interface) específica.
Existe uma configuração* que define se é necessário realizar a autenticação do usuário para se ter acesso às API’s e caso essa autenticação esteja habilitada, é necessário utilizar um dos modelo de autenticação.
O modelo mais simples de autenticação disponível é conhecido como Basic Auth, mas ele não pode ser considerado como seguro pois trafega em cada requisição, o usuário e a senha que está se autenticando. Para evitar que o usuário e a senha sejam trafegados no cabeçalho de cada requisição REST, pode-se então optar por esse novo modelo proposto.
* Mais detalhes sobre a configuração e dos modelos de autenticação disponível no link: https://tdn.totvs.com.br/pages/viewpage.action?pageId=75268866
Fluxo
Esse token é resultado de um POST no endpoint /token e tem uma validade de curta duração. Seu contexto de acesso pode variar de acordo com o usuário que está se autenticando.
Nesse modelo fica necessário então o tráfego de usuário e senha apenas nessa requisição de acesso (que é fortemente recomendado que seja protegida por SSL - Secure Sockets Layer para não ser interceptada por terceiros), e após a obtenção, basta incluir o token no cabeçalho de cada requisição para garantir o acesso às demais API’s que o usuário tenha direito.
Após a expiração da validade do token de acesso é necessário repetir a requisição através do fornecimento de usuário e senha ou, melhor ainda, também é possível a utilização de um token de refresh para obter outro token de acesso sem a necessidade de trafegar a senha novamente.
Esse token de refresh é obtido juntamente com o token de acesso na primeira requisição e tem um tempo de expiração bem superior ao do token de acesso. Atualmente o tempo de expiração do token de acesso está definido em uma hora e o de refresh em vinte e quatro horas.
Uma vez que é requisitada a atualização dos tokens, o prazo de validade de ambos é renovado e com isso é possível manter o acesso garantido pelo tempo que for necessário de forma circular.
Caso a atualização não seja requisitada até o momento de expiração do token de refresh, não será mais possível obter acesso por atualização, sendo então necessário solicitar o token de acesso informando usuário e senha novamente.
O Endpoint /token
Devido ao trafego de usuário e senha para esse endpoint, ele é um servido que recomendamos fortemente que seja acessado pelo protocolo seguro https. Caso seja utilizado sem o uso do SSL, uma mensagem é impressa no console do servidor a cada requisição que é respondida.
Seus parâmetros são trafegados via http headers conforme exemplo abaixo:
Bloco de código | ||
---|---|---|
| ||
https://localhost:8080/rest/api/oauth2/v1/token?grant_type=password POST /api/oauth2/v1/token Host exemplo: https://localhost:8080/rest Query Params: ?grant_type=password Headers password : senha do usuario username : usuario do sistema |
Parâmetro | Valor |
grant_type | password |
password | Senha do usuário |
username | Usuário para autenticação |
Reposta da requisição
Caso as credenciais sejam válidas, a resposta será retornada no seguinte formato:
Bloco de código | ||
---|---|---|
| ||
{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJUT1RWUy1BRFZQTC1GV0pXVCIsInN1YiI6Im1hcmlvIiwiaWF0IjoxNTUzMDIyMjYwLCJleHAiOjE1NTMwMjU4NjAsInJlc3RyaWN0ZWR0byI6WyJhcGkvcHJvdGhldXMvIiwiYXBpL2ZyYW1ld29yay8iXX0.jgvejFxPYDchLtj04r7mizRZCerb7xFXhB8Ihk+kFqg=", "refresh_token": "YEv3dtFbNCisITD3yDtKi5/x.T0jkPv12SWK/JjWS0xI01YbIXWM10KWw2ehCxG9yRVkXCiItBYN57Rizh4OH67m7H3-Jd-3ruC4/pBAWBkXVO251HPiS91KAh7FfbZqWaiDPmvYBvoiaP4KRR1gYcvCr9ES7wC3iRA2wQrQvODlH7b3FCTmvHzCVmRMi4eApgy4iOGVpBK7-ryI=.fD77MI4MBk1rW6eBjMq9EutN1ZIC1YKKuKqdEhbLf/k=", "scope": "default", "token_type": "Bearer", "expires_in": 3600 } |
Acesso às API’s REST
De posse então do access_token, basta fazer a requisição à API desejada incluindo no cabeçalho a parâmetro Authorization com o valor Bearer mais o token de acesso.
Mais detalhes podem ser obtidos no link http://tdn.totvs.com.br/pages/viewpage.action?pageId=465386127
A atualização do token
Após a expiração do token de acesso, ao tentar requisitar alguma API protegida, será retornado o status 401 de não autorizado, como se não houvesse sido enviado um token de acesso.
É o momento então de requisitar para a mesma API de token a atualização conforme o exemplo abaixo:
Bloco de código | ||
---|---|---|
| ||
https://localhost:8081/rest/api/oauth2/v1/token?grant_type=refresh_token&refresh_token=YEv3dtFbNCisITD3yDtKi5/x.T0jkPv12SWK/JjWS0xI01YbIXWM10KWw2ehCxG9yRVkXCiItBYN57Rizh4OH67m7H3-Jd-3ruC4/pBAWBkXVO251HPiS91KAh7FfbZqWaiDPmvYBvoiaP4KRR1gYcvCr9ES7wC3iRA2wQrQvODlH7b3FCTmvHzCVmRMi4eApgy4iOGVpBK7-ryI=.fD77MI4MBk1rW6eBjMq9EutN1ZIC1YKKuKqdEhbLf/k= POST /api/oauth2/v1/token Host exemplo: https://localhost:8080/rest Query Params: ?grant_type=refresh_token&refresh_token=YEv3dtFbNCisITD3yDtKi5/x.T0jkPv12SWK/JjWS0xI01YbIXWM10KWw2ehCxG9yRVkXCiItBYN57Rizh4OH67m7H3-Jd-3ruC4/pBAWBkXVO251HPiS91KAh7FfbZqWaiDPmvYBvoiaP4KRR1gYcvCr9ES7wC3iRA2wQrQvODlH7b3FCTmvHzCVmRMi4eApgy4iOGVpBK7-ryI=.fD77MI4MBk1rW6eBjMq9EutN1ZIC1YKKuKqdEhbLf/k= |
Parâmetro | Valor |
grant_type | refresh_token |
refresh_token | Token de refresh |
Reposta da requisição
Caso o refresh token seja válido, a resposta será retornada no mesmo formato anterior e esse ciclo pode se repetir inúmeras vezes, desde que o tempo de expiração não seja excedido:
Bloco de código | ||
---|---|---|
| ||
{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJUT1RWUy1BRFZQTC1GV0pXVCIsInN1YiI6Im1hcmlvIiwiaWF0IjoxNTUzMDIyOTQ0LCJleHAiOjE1NTMwMjY1NDQsInJlc3RyaWN0ZWR0byI6WyJhcGkvcHJvdGhldXMvIiwiYXBpL2ZyYW1ld29yay8iXX0.XsS38RdeJIetwh6Zq2DLQs0PhyLSRxCxOnCgp4SaoeY=", "refresh_token": "YEv3dtFbNCisMST1yztKi5/x.T0jkPv12SWK/JjWS0xI01YbIXWM10KWw2ehCxG9yRVkXCiItBYN57Rizh4OH67m7H3-Jd-3ruC4/pBAWBkXVO251HPiS91KAh7FfbZqWaiDPmvYBvoiaP4KRR1hUct67vFah2VLUSymyfLQtOjltqqzVPkqZMBaVtyVl4c4pxTw4IQtpHw==.tIUbpKC8sWcB6oIMhXcbOhq/bveF216m9gmboBrxJ7U=", "scope": "default", "token_type": "Bearer", "expires_in": 3600 } |
Informações |
---|
Disponível a partir da LIB versão 20210517 |
Assinatura da Requisição
Os tokens gerados no protheus são assinados por uma chave privada e podem ser conferidos utilizando uma chave pública. A partir da LIB versão 20210517 será possível recuperar a chave pública para verificar a assinatura do token recebido. A chave pública para o algoritmo RSA fica na propriedade "n" do objeto de definição. Para mais informações sobre o formato da resposta consulte https://tools.ietf.org/html/rfc7517
Bloco de código | ||
---|---|---|
| ||
https://localhost:8081/rest/api/oauth2/v1/jwks GET/api/oauth2/v1/jwks Host exemplo: https://localhost:8080/rest |
Bloco de código | ||
---|---|---|
| ||
{ "keys": [ { "e": "AQAB", "alg": "RS256", "n": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp0Lg4RLzX2NrsFj4i9lIxgzCmMQU4p4FdsWAzFm8S5YUTyEaDmk1J36bdrj3YXM5VJTA6IhbLOvEE9UAMRWWgrpOEsEN+sVijFgha0SflKQhY4XJUv45zCP/pZbfhr0N6M1AD3Up+yA/TYq9gUQoEOsf/x0G9Wsi4UHDxQCVpLPUfrlHUAOUksqZZhAO6bU2jqH7Y2EchBMe4tMydoQ6xn8+n2yEe5oZijaAVDM4V8oYE5zyGDTodMUsbau8uqQM5KykL/RyGCZGlQlEsDFwcFu8NP/Y+zyUTE+fyqWBR0YEG0I0gZwSNMK40PaoiKtee28+nh9gqfRfvmwwQaFEYwIDAQAB", "kid": "protheus jwt public key for RS256", "use": "sig", "kty": "RSA" }, { "e": "AQAB", "alg": "RS512", "n": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp0Lg4RLzX2NrsFj4i9lIxgzCmMQU4p4FdsWAzFm8S5YUTyEaDmk1J36bdrj3YXM5VJTA6IhbLOvEE9UAMRWWgrpOEsEN+sVijFgha0SflKQhY4XJUv45zCP/pZbfhr0N6M1AD3Up+yA/TYq9gUQoEOsf/x0G9Wsi4UHDxQCVpLPUfrlHUAOUksqZZhAO6bU2jqH7Y2EchBMe4tMydoQ6xn8+n2yEe5oZijaAVDM4V8oYE5zyGDTodMUsbau8uqQM5KykL/RyGCZGlQlEsDFwcFu8NP/Y+zyUTE+fyqWBR0YEG0I0gZwSNMK40PaoiKtee28+nh9gqfRfvmwwQaFEYwIDAQAB", "kid": "protheus jwt public key for RS512", "use": "sig", "kty": "RSA" } ] } |
Informações |
---|
Não é possível alterar o tempo de expiração do token (expires_in), esse valor é definido internamente, assim como também não é possível alterar o valor de expiração do refresh_token. |
Informações |
---|
Disponível a partir da LIB versão 20190705 |