From 18ecca5d3b27a110d16dbe4d18cb471e6dd27c32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robson=20Ten=C3=B3rio?= Date: Mon, 16 Apr 2018 09:50:56 -0300 Subject: [PATCH] feat(oauth2): support authorization code grant and refresh token (#145) --- docs/schemes/oauth2.md | 4 ++++ lib/core/auth.js | 23 +++++++++++++++++++++++ lib/module/defaults.js | 6 ++++++ lib/schemes/oauth2.js | 25 +++++++++++++++++++++---- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/docs/schemes/oauth2.md b/docs/schemes/oauth2.md index f2c197cf5..a9b258388 100644 --- a/docs/schemes/oauth2.md +++ b/docs/schemes/oauth2.md @@ -60,6 +60,10 @@ Should be same as login page or relative path to welcome screen. ([example](http By default is set to `token_key: 'access_token'`. If you need to use the IdToken instead of the AccessToken, set this option to `token_key: 'id_token'`. +### `refresh_token_key` + +By default is set to `refresh_token_key: 'refresh_token'`. It automatically store the refresh_token, if it exists. + ## Usage ```js diff --git a/lib/core/auth.js b/lib/core/auth.js index 69fd1c1e9..07f928964 100644 --- a/lib/core/auth.js +++ b/lib/core/auth.js @@ -147,6 +147,7 @@ export default class Auth { if (!this.strategy.reset) { this.setUser(null) this.setToken(this.$state.strategy, null) + this.setRefreshToken(this.$state.strategy, null) return Promise.resolve() } @@ -178,6 +179,28 @@ export default class Auth { return this.$storage.syncUniversal(_key) } + // --------------------------------------------------------------- + // Refresh token helpers + // --------------------------------------------------------------- + + getRefreshToken (strategy) { + const _key = this.options.refresh_token.prefix + strategy + + return this.$storage.getUniversal(_key) + } + + setRefreshToken (strategy, refreshToken) { + const _key = this.options.refresh_token.prefix + strategy + + return this.$storage.setUniversal(_key, refreshToken) + } + + syncToken (strategy) { + const _key = this.options.refresh_token.prefix + strategy + + return this.$storage.syncUniversal(_key) + } + // --------------------------------------------------------------- // User helpers // --------------------------------------------------------------- diff --git a/lib/module/defaults.js b/lib/module/defaults.js index 157c27690..75a81dcd9 100644 --- a/lib/module/defaults.js +++ b/lib/module/defaults.js @@ -47,6 +47,12 @@ module.exports = { prefix: '_token.' }, + // -- Refresh token -- + + refresh_token: { + prefix: '_refresh_token.' + }, + // -- Strategies -- defaultStrategy: undefined /* will be auto set at module level */, diff --git a/lib/schemes/oauth2.js b/lib/schemes/oauth2.js index 48db472f7..9bef344fd 100644 --- a/lib/schemes/oauth2.js +++ b/lib/schemes/oauth2.js @@ -91,19 +91,30 @@ export default class Oauth2Scheme { // accessToken/idToken let token = parsedQuery[this.options.token_key || 'access_token'] + // refresh token + let refreshToken = parsedQuery[this.options.refresh_token_key || 'refresh_token'] + // -- Authorization Code Grant -- if (this.options.response_type === 'code' && parsedQuery.code) { const data = await this.$auth.request({ method: 'post', - url: window.location.origin + this.options.access_token_endpoint, - data: { - code: parsedQuery.code - } + url: this.options.access_token_endpoint, + data: encodeQuery({ + code: parsedQuery.code, + client_id: this.options.client_id, + redirect_uri: this._redirectURI, + response_type: this.options.response_type, + grant_type: this.options.grant_type + }) }) if (data.access_token) { token = data.access_token } + + if (data.refresh_token) { + refreshToken = data.refresh_token + } } if (!token || !token.length) { @@ -125,6 +136,12 @@ export default class Oauth2Scheme { // Store token this.$auth.setToken(this.name, token) + // Store refresh token + if (refreshToken && refreshToken.length) { + refreshToken = this.options.token_type + ' ' + refreshToken + this.$auth.setRefreshToken(this.name, refreshToken) + } + // Redirect to home this.$auth.redirect('home', true)