Skip to content

Commit

Permalink
Check access token expires before we use it. (#1444)
Browse files Browse the repository at this point in the history
* Check access token expires before we use it.If we found access token expires, we proactive call refresh token.So that we can avoid uncessary invalid auth error in backend.

* Move expires  calc to fetchToken() and refresToken()

* Address code review comment
  • Loading branch information
awarecan authored and balloob committed Jul 16, 2018
1 parent b5ff52f commit 348b284
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 9 deletions.
4 changes: 3 additions & 1 deletion src/common/auth/fetch_token.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export default function fetchToken(clientId, code) {
body: data,
}).then((resp) => {
if (!resp.ok) throw new Error('Unable to fetch tokens');
return resp.json();
const tokens = resp.json();
tokens.expires = (tokens.expires_in * 1000) + Date.now();
return tokens;
});
}
4 changes: 3 additions & 1 deletion src/common/auth/refresh_token.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export default function refreshAccessToken(clientId, refreshToken) {
body: data,
}).then((resp) => {
if (!resp.ok) throw new Error('Unable to fetch tokens');
return resp.json();
const tokens = resp.json();
tokens.expires = (tokens.expires_in * 1000) + Date.now();
return tokens;
});
}
9 changes: 8 additions & 1 deletion src/entrypoints/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,20 @@ class HomeAssistant extends LocalizeMixin(PolymerElement) {
const host = window.location.protocol + '//' + window.location.host;
const auth = conn.options;
try {
// Refresh token if it will expire in 30 seconds
if (auth.accessToken && Date.now() + 30000 > auth.expires) {
const accessToken = await window.refreshToken();
conn.options.accessToken = accessToken.access_token;
conn.options.expires = accessToken.expires;
}
return await hassCallApi(host, auth, method, path, parameters);
} catch (err) {
if (!err || err.status_code !== 401 || !auth.accessToken) throw err;

// If we connect with access token and get 401, refresh token and try again
const accessToken = await window.refreshToken();
conn.options.accessToken = accessToken;
conn.options.accessToken = accessToken.access_token;
conn.options.expires = accessToken.expires;
return await hassCallApi(host, auth, method, path, parameters);
}
},
Expand Down
29 changes: 23 additions & 6 deletions src/entrypoints/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const init = window.createHassConnection = function (password, accessToken) {
if (password) {
options.authToken = password;
} else if (accessToken) {
options.accessToken = accessToken;
options.accessToken = accessToken.access_token;
options.expires = accessToken.expires;
}
return createConnection(url, options)
.then(function (conn) {
Expand All @@ -40,7 +41,10 @@ window.refreshToken = () =>
refreshToken_(clientId(), window.tokens.refresh_token).then((accessTokenResp) => {
window.tokens.access_token = accessTokenResp.access_token;
localStorage.tokens = JSON.stringify(window.tokens);
return accessTokenResp.access_token;
return {
access_token: accessTokenResp.access_token,
expires: window.tokens.expires
};
}, () => redirectLogin());

function resolveCode(code) {
Expand All @@ -66,11 +70,24 @@ function main() {
}
if (localStorage.tokens) {
window.tokens = JSON.parse(localStorage.tokens);
window.hassConnection = init(null, window.tokens.access_token).catch((err) => {
if (err !== ERR_INVALID_AUTH) throw err;
if (window.tokens.expires === undefined) {
// for those tokens got from previous version
window.tokens.expires = Date.now() - 1;
}
if (Date.now() + 30000 > window.tokens.expires) {
// refresh access token if it will expire in 30 seconds to avoid invalid auth event
window.hassConnection = window.refreshToken().then(accessToken => init(null, accessToken));
} else {
const accessTokenObject = {
access_token: window.tokens.access_token,
expires: window.tokens.expires
};
window.hassConnection = init(null, accessTokenObject).catch((err) => {
if (err !== ERR_INVALID_AUTH) throw err;

return window.refreshToken().then(accessToken => init(null, accessToken));
});
return window.refreshToken().then(accessToken => init(null, accessToken));
});
}
return;
}
redirectLogin();
Expand Down

0 comments on commit 348b284

Please sign in to comment.