CONTEÚDO
Informações |
---|
Índice |
---|
maxLevel | 4 |
---|
minLevel | 2 |
---|
indent | 50px |
---|
absoluteUrl | true |
---|
|
|
01.
VISÃO GERALVisão Geral
Disponibilizar um modelo de autenticação e autorização de acesso a recursos (endpoints), que permita abstração e flexibilidade com a utilização de um serviço de login independente (conforme modelo de arquitetura especificado na RFC000010 e RFC000015).
02.
CONCEITOS APLICADOSConceitos Aplicados
OAuth2 é um protocolo que permite aos usuários ter acesso a determinados recursos sem precisar expor suas credenciais. Por isso, serão usados os fluxos de autenticação e autorização baseados no OAuth2.
a. Client Credentials
Esse tópico aborda a autorização entre serviços (M2M) onde o Client age em seu próprio nome Resource Server.
Image Removed
Figura 1 - Modelo de acesso com Client Credentials
Abaixo estão listados os componentes do desenho acima:
IDM: Solução que garante a autenticidade do Resource Owner
Oauth Provider: Solução que assume o papel de Oauth Provider e atua como Authorization Server, esse componente tem a responsabilidade de assinar o access_token com chave assimétrica. O Authorization Server consome uma fila de propagação "Role x ClientId" produzida pelo componente RBAC que persisti para possibilitar a geração do access_token auto-contido com as "Roles" do ClientId. O Authorization Server deve verificar a base para invalidação do clientId de modo que o mesmo ao tentar renovar o access_token utilizando seu refresh_token ou autorizar seja invalidado pelo Oauth Provider;
RBAC: Esse componente é responsável por gerir as permissões possibilitando termos uma relação de "Role x Grant". A responsabilidade de verificação desse componente é classificada como extremamente crítica. A solução permite que o RBAC tenha consistência eventual delegando a verificação de "Grant x ClientID" para uma camada na aplicação (Resource Server);
Resource Server (APP 2): A aplicação que hospeda o recurso tem a responsabilidade de enviar suas Grants para o RBAC via fila. Esse componente também deve consumir a fila de propagação de "Role x Grant" e gravar os dados recebidos para possibilitar a verificação de permissão das "Roles" que estarão auto-contidas no access_token. O Resource Server tem posse da chave pública para a verificação do access_token. Percebe-se que é necessário a construção de uma abstração para as aplicações;
Client (APP 1): O Client é o consumidor do recurso e assume o papel de Resource Owner quando o "grant_type" é client_credentials, com isso, o Client precisa das credenciais client_id e client_secret gerados no momento do registro no Oauth Provider. Assumindo que o Client é o próprio Resource Owner não há a necessidade de delegação de acesso.
03. Exemplos de Utilização
Informações |
---|
A seguir serão demonstrados alguns trechos de códigos em JavaScript e TypeScript que exemplificam os conceitos gerais de Autenticação (para gerar o token) e Autorização (validação do token ao requisitar um endpoint). Lembrando que o código deve ser alterado de acordo com a linguagem de programação e regras específicas de segurança. |
b.Resource Owner Password CredentialsA proposta aborda a autorização entre usuário Resource Owner e Client. Nesse caso o Client assume o papel de Resource Server, com isso, ele hospeda os recursos.
Image Removed
Figura 2 - Modelo de acesso com Resource Owner Password Credentials
Abaixo estão listados os componentes do desenho acima:
03. EXEMPLO DE UTILIZAÇÃO
a. Otimização das Libs do Datasul
Para efetuar melhorias contínuas na manutenção, inovações, expedição do produto e otimização na utilização de memória do servidor Web (Tomcat), são utilizados conceitos de lib centralizadas.
Otimização do uso das libs do Datasul no Tomcat | Spike de validação do conceito de lib centralizada |
Gerar BuildOfMaterials (BOM) Datasul | Spike de utilização do conceito de BOM (Maven) para compilação do produto |
Compilação Maven para Libs Centralizadas | Instruções de trabalho para a geração dos artefatos conforme este novo conceito |
b. Configuração baseada no OAuth2
As configurações para utilização dos conceitos de login conforme OAuth2 são realizadas nas telas de Propriedades, disponíveis no produto.
CFG - OAuth2 | Configura os modelos (Grant Type) de autenticação do usuário propostos nesta documentação. |
CFG - JWT | Configura o modelo do Token JWT que será gerado caso a autenticação seja realizada com sucesso. |
c. Client Credentials - Autenticação
A autenticação é necessária para obter o token JWT, para isto foi desenvolvido um endpoint que retorna dados para futuras utilizações:
Método: POST
URL: http://{{host}}:{{port}}/totvs-login-oauth2/oauth2/token?grant_type=client_credentials
Authorization: Basic Auth (Informar as credenciais Id cliente, Senha cliente parametrizadas em Propriedades → OAuth2)
Aviso |
---|
|
O endpoint de autenticação permite o envio das credenciais por parâmetros, porém segundo a RFC6749 esta forma de envio não é recomendada e deve ser limitada somente a clientes incapazes de utilizar o esquema de autenticação HTTP Basic. https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1 Caso seja realmente necessário o envio por parâmetros, os mesmos só podem ser transmitidos no corpo da solicitação com o tipo: Content-Type: application/x-www-form-urlencoded |
Image Removed
Caso a autenticação seja realizada com sucesso, é retornado o token com o formato abaixo:
Bloco de código |
---|
language | ruby |
---|
title | Exemplo do retorno Body |
---|
linenumbers | true |
---|
|
{
"access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIwMjAwMTBzOGgyZ2ZpOTBoQ1duUG9WQXhnOERnNTUiLCJpYXQiOjE2NTY1MjM5MzYsImV4cCI6MTY1NjUyNDA1NiwiYXVkIjoiand0LmlvLmFwYWNoZS5leHRlcm5vIiwic2NvcGUiOlsiL2J0YiJdfQ.ZEMaRafOnFyUDkN198y5g2OkJuKfoS_zLDCXvP98XJ7hR--WTXnaQlEvTLmYf_Zhs6qmZHzpslE1hYRzzJRqPkRcuJ1LY_rAjiQJ8Zgk_NnHfT5HaAS0ut8G6rtJYIS9W_6FAAqal5PZE_iNwUd5mlVUT7_9SpNlSzhb3eH0r2Fe-Wceb6pJIrCI0UA_9UCAwvbQrDadcJXJGWjSqgf2l_B3K1HossFnCnAXsVCXsqVxofld4n9wnFD8B_qhy9UNSxbEayUjpOrJYmq4v5WvVFBG2XMk516ojFR3bT-q2PV-sWOqr8XyV-Qb7-cvkGNes9_DHKKkmUo3B77DP--Bjg",
"token_type": "Bearer",
"expires_in": 120,
"scope": "/btb"
} |
Nota |
---|
|
Neste conceito não ocorre a revogação do token JWT (logout / invalidate), o controle é realizado de acordo com o tempo de expiração do próprio token que pode ser parametrizado na tela de Propriedades → JWT. |
d. Client Credentials - Autorização
De posse com o token JWT gerado na etapa anterior, para acessar determinados recursos / endpoint, bastaria enviar o token na requisição com o formato Bearer Token:
Exemplo...
Método: GET
URL: http://{{host}}:{{port}}/api/btb/v1/properties/general
Authorization: Bearer (Informar o token JWT)
Dica |
---|
|
Nesta etapa são realizados diversas validações de autorização ao recurso / endpoint, tais como a integridade do Token JWT, validade, escopo e audiência, onde todas as informações necessárias já estariam presentes no próprio token. Possíveis status de retorno: - 200 (OK): Acesso permitido ao recurso com os dados retornados;
- 401 (Unauthorized): O token informado não é valido;
- 403 (Forbidden): O token é valido porém há restrição em seu uso (escopo ou audiência);
- 500 (Internal Server Error): Ocorreu um erro no servidor de aplicação Web (Tomcat) ou AppServer.
|
e. Resource Owner Password Credentials - Autenticação
Para utilizar o modelo de autenticação com o Resource Owner Password Credentials, foi desenvolvido um endpoint que retorna dados para futuras utilizações:
Image Removed
Método: POST
URL: http://{{host}}:{{port}}/totvs-login-oauth2/oauth2/token?grant_type=password
Authorization: Basic Auth
Aviso |
---|
|
O endpoint de autenticação permite o envio das credenciais por parâmetros, porém segundo a RFC6749 esta forma de envio não é recomendada e deve ser limitada somente a clientes incapazes de utilizar o esquema de autenticação HTTP Basic. https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1 Caso seja realmente necessário o envio por parâmetros, os mesmos só podem ser transmitidos no corpo da solicitação com o tipo: Content-Type: application/x-www-form-urlencoded |
Body:
- companyId (Opcional): Enviar como x-www-form-urlencoded, o código da empresa para direcionar a conexão.
Caso a autenticação seja realizada com sucesso, é retornado o token com o formato abaixo:
Bloco de código |
---|
language | ruby |
---|
title | Exemplo do retorno Body |
---|
linenumbers | true |
---|
|
{
"access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdXBlciIsImlhdCI6MTY1NjUyOTkzNCwiZXhwIjoxNjU2NTMwMDU0LCJhdWQiOiJqd3QuaW8uYXBhY2hlLmV4dGVybm8iLCJ0ZW5hbnRJZCI6ImY3N2Q4ZjM2LTQzYzYtOWJiMS05NzE0LWQyMTBhOGI1MzcwYSIsInNjb3BlIjpbIioiXX0.b43eHEra_xjGZqkSIC6h1m7ZamFxb1jcAKCDjyWvOh7VjWE5QZkwnozTtAudQSGE3CaT-R8A1xofERqhymnPKX-me1OnTbcMoRwFMSd76w1AF9mT9U262X8noZcqyQ89-wmav93w-CnFpCek_-MABp2PV48qtom03hyj5UkqhkdHgGJVij7yUJdQS2QiQAQKrsnRrfEaBY2kpMt4hYPwjPbUIVw3ZYhDX9ZKz56y_VB3MoteuxThxyhNZq7PoMHs4YrqMMubddPFrRm5Xgl4eCdTzC_XvfXw8zo2hWEAl0zGBPTQXgGdjsJwIaQcOu5GOe5zBW0zQfSIOkkNiJLgIg",
"token_type": "Bearer",
"expires_in": 120,
"scope": "*"
} |
Params:
- scope (Opcional): Há a possibilidade de enviar o parâmetro scope para receber o token com este parâmetro. Caso não for enviado, o resultado do scope sempre será "*".
Caso exista mais de um parâmetro dentro de scope, deverá ser feita a separação por vírgula, conforme abaixo:
Image Removed
Caso enviado, é retornado o token conforme exemplo abaixo:
Bloco de código |
---|
language | ruby |
---|
title | Exemplo do retorno Body |
---|
linenumbers | true |
---|
|
{
"access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjMjAzZjY2OS0yMTIzLTgyYWYtNDExNC05MDg5NzAxYTUxMTAiLCJpYXQiOjE3MTI2OTM4NjQsImlzc3VlciI6ImRhdGFzdWwiLCJpc3MiOiJkYXRhc3VsIiwianRpIjoiNmJmYzI2N2QtOWJjYS00ZjkxLWE0YzYtMWJlZmVmYjc5ZDYzIiwiZXhwIjoxNzEyNzAzODYzLCJhdWQiOiJKVk4wNjAxMDU2MzE6ODA4NiIsImNvbXBhbnlJZCI6ImEzNTQwYzliLTJjZTMtODE5OS1iMzE0LWJkMDE4MDc2MDhmMyIsInNjb3BlIjpbIi9hcGkiLCIvYXBpL2R0cyIsIi90b3R2cy1sb2dpbiJdfQ.MHmnHNBL3VGrJXBRsf1ip6m74QK6eVfpCX5_jgO8Zp1wbrS_MKQms3n0KQdx-AGJToDwOWC5kMFIqWy8Wkog_N_PBdf603zeg_NmqCyj9JSNw_SLFuqOClLXQdUwIVUr-hf5jslcPKbZxyn_Xfb1RgbIR-wh_2xABdoIduWqohPjzRSB3O5WCdtHmURIMakGYeKqIT1F7LOGAvF2xUdT8ODDsu0MzjTjexz1dwO95YCnWsgcpbGrXXc8l_pETQbCF7S3C5nPsscoNRmd8PjMo9tIjyiEbuR8Pi-xHWZF8hOMbjuexm3_rl2CLRTWAwJurOmINwc2ooRqK3Cjp8v0sQ",
"token_type": "Bearer",
"expires_in": 120,
"refresh_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjMjAzZjY2OS0yMTIzLTgyYWYtNDExNC05MDg5NzAxYTUxMTAiLCJpYXQiOjE3MTI2OTM4NjUsImlzc3VlciI6ImRhdGFzdWwiLCJqdGkiOiI5ZjZkMjZkNS0wZjliLTQ0YmMtYmViZC01MGE5ZDBlYTg3ZDYiLCJhY2Nlc3NUb2tlbiI6IjZiZmMyNjdkLTliY2EtNGY5MS1hNGM2LTFiZWZlZmI3OWQ2MyIsImV4cCI6MTcxMjcwMzg2NH0.f-R_TVj9qFLNnIUvj8yKh9NH0o1aYDXmyHAMr-MjuUU5Fj7XC3IlmCuKXGT46_5zsydQfWUsjfn9ngkip8Vf70pz6utwANFd-MUqOla1toDETtxPQ0nLbHhL_sqx-scfM6-vcz4VufCgAwabR6bTUn7oL0LMv4twNeKHUpXcHjcjjfpMik4E1o_Cbw0lbtqtAyM52uih_OttrIolZAHgmQLubukJa7WHZsehU0kLiaqZsIfgOM7v2F5nTz5AfbbwrlRp4loWcoVSD2B5GdNzlZwhgdRQUq17RZvpR3Ew-8f4MXwlxWglR7MQZGylZAsbLt-rfBs8_nBbakRbX4rPLQ",
"scope": "/api /api/dts /totvs-login"
} |
Caso o parâmetro scope não for enviado, é retornado o token conforme exemplo abaixo, com o valor de scope igual a "*":
Bloco de código |
---|
language | ruby |
---|
title | Exemplo do retorno Body |
---|
linenumbers | true |
---|
|
{
"access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjMjAzZjY2OS0yMTIzLTgyYWYtNDExNC05MDg5NzAxYTUxMTAiLCJpYXQiOjE3MTI2OTM4NjQsImlzc3VlciI6ImRhdGFzdWwiLCJpc3MiOiJkYXRhc3VsIiwianRpIjoiNmJmYzI2N2QtOWJjYS00ZjkxLWE0YzYtMWJlZmVmYjc5ZDYzIiwiZXhwIjoxNzEyNzAzODYzLCJhdWQiOiJKVk4wNjAxMDU2MzE6ODA4NiIsImNvbXBhbnlJZCI6ImEzNTQwYzliLTJjZTMtODE5OS1iMzE0LWJkMDE4MDc2MDhmMyIsInNjb3BlIjpbIi9hcGkiLCIvYXBpL2R0cyIsIi90b3R2cy1sb2dpbiJdfQ.MHmnHNBL3VGrJXBRsf1ip6m74QK6eVfpCX5_jgO8Zp1wbrS_MKQms3n0KQdx-AGJToDwOWC5kMFIqWy8Wkog_N_PBdf603zeg_NmqCyj9JSNw_SLFuqOClLXQdUwIVUr-hf5jslcPKbZxyn_Xfb1RgbIR-wh_2xABdoIduWqohPjzRSB3O5WCdtHmURIMakGYeKqIT1F7LOGAvF2xUdT8ODDsu0MzjTjexz1dwO95YCnWsgcpbGrXXc8l_pETQbCF7S3C5nPsscoNRmd8PjMo9tIjyiEbuR8Pi-xHWZF8hOMbjuexm3_rl2CLRTWAwJurOmINwc2ooRqK3Cjp8v0sQ",
"token_type": "Bearer",
"expires_in": 120,
"refresh_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjMjAzZjY2OS0yMTIzLTgyYWYtNDExNC05MDg5NzAxYTUxMTAiLCJpYXQiOjE3MTI2OTM4NjUsImlzc3VlciI6ImRhdGFzdWwiLCJqdGkiOiI5ZjZkMjZkNS0wZjliLTQ0YmMtYmViZC01MGE5ZDBlYTg3ZDYiLCJhY2Nlc3NUb2tlbiI6IjZiZmMyNjdkLTliY2EtNGY5MS1hNGM2LTFiZWZlZmI3OWQ2MyIsImV4cCI6MTcxMjcwMzg2NH0.f-R_TVj9qFLNnIUvj8yKh9NH0o1aYDXmyHAMr-MjuUU5Fj7XC3IlmCuKXGT46_5zsydQfWUsjfn9ngkip8Vf70pz6utwANFd-MUqOla1toDETtxPQ0nLbHhL_sqx-scfM6-vcz4VufCgAwabR6bTUn7oL0LMv4twNeKHUpXcHjcjjfpMik4E1o_Cbw0lbtqtAyM52uih_OttrIolZAHgmQLubukJa7WHZsehU0kLiaqZsIfgOM7v2F5nTz5AfbbwrlRp4loWcoVSD2B5GdNzlZwhgdRQUq17RZvpR3Ew-8f4MXwlxWglR7MQZGylZAsbLt-rfBs8_nBbakRbX4rPLQ",
"scope": "*"
} |
Informações |
---|
|
A partir da versão 12.1.2311, é retornado o refresh_token como parâmetro para que o token de acesso possa ser regerado sem a necessidade de efetuar uma nova autenticação. Bloco de código |
---|
| {
"access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJmMDkzNTQwOC1hZThjLTBlYWUtYWExNC03MzA2OGM3ZjQwZTAiLCJpYXQiOjE2OTI2NDczMTAsImlzc3VlciI6ImRhdGFzdWwiLCJpc3MiOiJkYXRhc3VsIiwianRpIjoiYTk1YTAzNmMtNjA1OS00YmZhLWJlNTYtYmUxZDk5NGNlM2I4IiwiZXhwIjoxNjkyNjQ3NDkwLCJhdWQiOiJ0ZXN0ZSIsInRlbmFudElkIjoiZjc3ZDhmMzYtNDNjNi05YmIxLTk3MTQtZDIxMGE4YjUzNzBhIiwic2NvcGUiOlsiKiJdfQ.grdplhwM5Q1B2F1G_JYq4UEaY7yHNhp7N60cr1YZwM4Z5qjpT0fqoKALZYnQqKH-YcboCcVrjZ5VFVdOgcMXu6s5w8cKEumLlDEidip67rncAOEyZPZ3tcA053QszaKuhDxBDrOwpmS9xRW6AV7oVGFBDQN2fDZDBl7uUin4Qv5hMXGZvxWtIYoha3pvMGviyupYae9GKA71ZZwvBIDpScbXIhkuroM03MsrdHwypzFYbLrPAmmTITEl_b-Y6v4MekbcE01SfSRrQuXU7tS4pxC3dXyysi_dWUeAFAw8Xdxv4VoNVKkFO2pnmQwGXSOGunES7bbd24DCnFGW0RZa7A",
"token_type": "Bearer",
"expires_in": 180,
"refresh_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJmMDkzNTQwOC1hZThjLTBlYWUtYWExNC03MzA2OGM3ZjQwZTAiLCJpYXQiOjE2OTI2NDczMTAsImlzc3VlciI6ImRhdGFzdWwiLCJqdGkiOiJhY2RjOWFlNC03MTRmLTRiMTYtYTdiYS00ODk1MjM2YjI2YTgiLCJhY2Nlc3NUb2tlbiI6ImE5NWEwMzZjLTYwNTktNGJmYS1iZTU2LWJlMWQ5OTRjZTNiOCIsImV4cCI6MTY5MjY0NzQ5MH0.QDtj1txFGd29humF_d6BmiC2f9ppoUXmFnpWDCuzIZn_VzV6EdMOQxv-rM0OujOuss-Z17HhcppL34wqtu_KWK6dupKr3E35cAkV7zcRfkgduBWyPFXSS4LCKIW5RXRoE8VucaDf0rwF1lcl6I3ZPdqzB8D3okDNirW7h1GO6G5TnWz0bHjdE-ZVFjW8x0JvLJE88TmObgLFaF7zLQTYZQ4VXRik_DueCw9dkBWNYJbr57C0wlYpVF7ZujESeX93IjNjzkw1CfDmLySaFGNCksc5VlRLt4NtoSFfFRhPStK7mmFRYveRu1PkF214xCnsSdK2ftqe4QfnqxsU8KAK8g",
"scope": "*"
} |
|
f. Resource Owner Password Credentials - Autorização
De posse com o token JWT gerado na etapa anterior, para acessar determinados recursos / endpoint, bastaria enviar o token de acesso (access_token) na requisição como Bearer na header Authorization.
Exemplo...
Método: GET
URL: http://{{host}}:{{port}}/api/btb/v1/properties/general
Authorization: Bearer (Informar o access_token)
Dica |
---|
|
Nesta etapa são realizados diversas validações de autorização ao recurso / endpoint, tais como a integridade do Token JWT, validade, escopo e audiência, onde todas as informações necessárias já estariam presentes no próprio token. Possíveis status de retorno: - 200 (OK): Acesso permitido ao recurso com os dados retornados;
- 401 (Unauthorized): O token informado não é valido;
- 403 (Forbidden): O token é valido porém há restrição em seu uso (escopo ou audiência);
- 500 (Internal Server Error): Ocorreu um erro no servidor de aplicação Web (Tomcat) ou AppServer.
|
g. Resource Owner Password Credentials - Exemplos de Utilização
O modelo Resource Owner Password Credentials pode ser utilizado em portais pois vincula o token com um usuário do ERP.
A seguir serão demonstrados alguns trechos de códigos em JavaScript e TypeScript para exemplificar uma utilização no produto. Lembrando que o código pode ser alterado de acordo com a linguagem de programação utilizada, pois é necessário seguir somente os conceitos gerais de Autenticação (para gerar o token) e Autorização (validação do token).
Login
Após efetuar a ação do login, o mesmo deve executar o endpoint de geração do token, onde seu resultado pode ser armazenado no localStorage do navegador para utilizações posteriores.
No trecho de código abaixo, caso o token seja gerado com sucesso, seu retorno é armazenado no localStorage com a chave token-service.token.
Bloco de código |
---|
|
function login_oauth2() {
var http = new XMLHttpRequest();
var url = '/totvs-login-oauth2/oauth2/token?grant_type=passwordrefresh_token';
var params = `refresh_token=${$scope.getRefreshToken()}`;
http.open('POST', url, true);
http.setRequestHeader('Authorization', "Basic " + btoa($txtUsername.val()+":"+$txtPassword.val()));
"Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
localStorage.setItem("token-service.token", http.responseText);= 200) {
}
}
} |
Geração dos tokens durante a utilização
Para limitar o uso indevido em caso de vazamentos, todos os tokens expiram (tempo parametrizável no ERP Datasul), por este motivo é importante que durante a utilização do portal os tokens sejam continuamente revalidados.
Com o intuito de facilitar a geração do token dentro do produto, é recomendado a utilização do refresh_token:
Image Removed
Método: POST
URL: http://{{host}}:{{port}}/totvs-login-oauth2/oauth2/token?grant_type=refresh_token
Authorization: Não informar pois é considerada somente a validação do token
Body (x-www-form-urlencoded):
- refresh_token (Obrigatório): Enviar como x-www-form-urlencoded, o refresh_token gerado no login do produto.
Nota |
---|
|
- O refresh_token não possui atributos de acesso (aud, tenantId, scope), portanto não deve ser utilizado para acessos aos recursos;
- Todo refresh_token é vinculado a um access_token, sendo deste token os atributos considerados para a nova geração;
- Por motivos de segurança, após a utilização do refresh_token, o mesmo é automaticamente invalidado;
- Para considerar um novo ciclo de geração, é necessário considerar os novos tokens gerados a partir do refresh_token.
|
No trecho de código abaixo é demonstrado a geração contínua de um token (com base no refresh_token), sendo executada em um ciclo continuo 60 segundos antes de sua expiração:
Bloco de código |
---|
$scope.refreshToken = function() {
var http = new XMLHttpRequest();
var url = '/totvs-login-oauth2/oauth2/token?grant_type=refresh_token';
var params = `refresh_token=${$scope.getRefreshToken()}`;
http.open('POST', url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
localStorage.setItem("token-service.token", http.responseText);
}
}
http.send(params);
};
$scope.getExpiresInToken = function() {
const tokenService = localStorage.getItem('token-service.token');
let jsonTokenService = JSON.parse(tokenService);
return jsonTokenService['expires_in'];
};
$scope.getRefreshToken = function() {
const tokenService = localStorage.getItem('token-service.token');
let jsonTokenService = JSON.parse(tokenService);
return jsonTokenService['refresh_token'];
};
var expireIn = $scope.getExpiresInToken() * 1000;
/**
* 1 minuto antes de expirar o token, tenta efetuar a renovacao
*/
setInterval(async() => {
await $scope.refreshToken()
}, (expireIn - (60 * 1000))); |
localStorage.setItem("token-client.token", http.responseText);
}
}
http.send(params);
};
$scope.getExpiresInToken = function() {
const tokenService = localStorage.getItem('token-client.token');
let jsonTokenService = JSON.parse(tokenService);
return jsonTokenService['expires_in'];
};
$scope.getRefreshToken = function() {
const tokenService = localStorage.getItem('token-client.token');
let jsonTokenService = JSON.parse(tokenService);
return jsonTokenService['refresh_token'];
};
var expireIn = $scope.getExpiresInToken() * 1000;
/**
* 1 minuto antes de expirar o token, tenta efetuar a renovacao
*/
setInterval(async() => {
await $scope.refreshToken()
}, (expireIn - (60 * 1000))); |