Last active
February 3, 2023 14:02
-
-
Save robsontenorio/d1e56c5bc5bc391ba0791be77419a68c to your computer and use it in GitHub Desktop.
[OAUTH2][KEYCLOAK] Auto refresh token for @nuxtjs/auth module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const strategy = 'keycloak' | |
export default function ({ app }) { | |
const { $axios, $auth } = app | |
if (!$auth.loggedIn || !$auth.strategies[strategy]) | |
return | |
const options = $auth.strategies.keycloak.options | |
let token = $auth.getToken(strategy) | |
let refreshToken = $auth.getRefreshToken(strategy) | |
if (!token || !refreshToken) | |
return | |
// calculate timeout before token expiration (75% from expiration time) | |
const tokenParsed = decodeToken.call(this, token) | |
let refreshInterval = (tokenParsed.exp * 1000 - Date.now()) * 0.75 | |
// Limit 10 seconds (avoid self attack) | |
if (refreshInterval < 10000) { | |
refreshInterval = 10000 | |
} | |
// keep refreshing token before expiration time | |
let refresher = setInterval(async function () { | |
try { | |
const response = await $axios.post(options.access_token_endpoint, | |
encodeQuery({ | |
refresh_token: refreshToken.replace(options.token_type + ' ', ''), | |
client_id: options.client_id, | |
grant_type: 'refresh_token' | |
}) | |
) | |
token = options.token_type + ' ' + response.data.access_token | |
refreshToken = options.token_type + ' ' + response.data.refresh_token | |
$auth.setToken(strategy, token) | |
$auth.setRefreshToken(strategy, refreshToken) | |
$axios.setToken(token) | |
} catch (error) { | |
$auth.logout() | |
throw new Error('Erro while refreshing token') | |
} | |
}, refreshInterval) | |
} | |
// Properly encode data | |
function encodeQuery (queryObject) { | |
return Object.keys(queryObject) | |
.map( | |
key => | |
encodeURIComponent(key) + '=' + encodeURIComponent(queryObject[key]) | |
) | |
.join('&') | |
} | |
// Decode JWT token | |
function decodeToken (str) { | |
str = str.split('.')[1]; | |
str = str.replace('/-/g', '+'); | |
str = str.replace('/_/g', '/'); | |
switch (str.length % 4) { | |
case 0: | |
break; | |
case 2: | |
str += '=='; | |
break; | |
case 3: | |
str += '='; | |
break; | |
default: | |
throw 'Invalid token'; | |
} | |
str = (str + '===').slice(0, str.length + (str.length % 4)); | |
str = str.replace(/-/g, '+').replace(/_/g, '/'); | |
str = decodeURIComponent(escape(atob(str))); | |
str = JSON.parse(str); | |
return str; | |
} |
@mejiamanuel57, it's using setInterval()
so the function will be executed repeatedly at the defined interval. You don't need to assign the result to a variable to achieve that. It seems that the reference to the result, refresher
, isn't used in this code but the reference is probably only needed to stop the code from running (refresher.close()
).
Note: You can import some JWT library to decode/encode data. But, just used plain JS.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @robsontenorio, where is let refresher called?