| | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } |
| |
|
| | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } |
| |
|
| | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } |
| |
|
| | import { getTokenExpiresAtDate, isBrowserEnv, createBrowserSafeString, OAuth2AuthorizationUrl, OAuth2TokenUrl, isWorkerEnv } from './utils.js'; |
| | import { parseResponse } from './response.js'; |
| | var fetch; |
| | var crypto; |
| | var Encoder; |
| |
|
| | var TokenExpirationBuffer = 300 * 1000; |
| | var PKCELength = 128; |
| | var TokenAccessTypes = ['legacy', 'offline', 'online']; |
| | var GrantTypes = ['code', 'token']; |
| | var IncludeGrantedScopes = ['none', 'user', 'team']; |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | var DropboxAuth = function () { |
| | function DropboxAuth(options) { |
| | _classCallCheck(this, DropboxAuth); |
| |
|
| | options = options || {}; |
| |
|
| | if (isBrowserEnv()) { |
| | fetch = window.fetch.bind(window); |
| | crypto = window.crypto || window.msCrypto; |
| | } else if (isWorkerEnv()) { |
| | |
| | fetch = self.fetch.bind(self); |
| | crypto = self.crypto; |
| | |
| | } else { |
| | fetch = require('node-fetch'); |
| |
|
| | crypto = require('crypto'); |
| | } |
| |
|
| | if (typeof TextEncoder === 'undefined') { |
| | Encoder = require('util').TextEncoder; |
| | } else { |
| | Encoder = TextEncoder; |
| | } |
| |
|
| | this.fetch = options.fetch || fetch; |
| | this.accessToken = options.accessToken; |
| | this.accessTokenExpiresAt = options.accessTokenExpiresAt; |
| | this.refreshToken = options.refreshToken; |
| | this.clientId = options.clientId; |
| | this.clientSecret = options.clientSecret; |
| | this.domain = options.domain; |
| | this.domainDelimiter = options.domainDelimiter; |
| | this.customHeaders = options.customHeaders; |
| | this.dataOnBody = options.dataOnBody; |
| | } |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | _createClass(DropboxAuth, [{ |
| | key: "setAccessToken", |
| | value: function setAccessToken(accessToken) { |
| | this.accessToken = accessToken; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "getAccessToken", |
| | value: function getAccessToken() { |
| | return this.accessToken; |
| | } |
| | |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "setClientId", |
| | value: function setClientId(clientId) { |
| | this.clientId = clientId; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "getClientId", |
| | value: function getClientId() { |
| | return this.clientId; |
| | } |
| | |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "setClientSecret", |
| | value: function setClientSecret(clientSecret) { |
| | this.clientSecret = clientSecret; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "getClientSecret", |
| | value: function getClientSecret() { |
| | return this.clientSecret; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "getRefreshToken", |
| | value: function getRefreshToken() { |
| | return this.refreshToken; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "setRefreshToken", |
| | value: function setRefreshToken(refreshToken) { |
| | this.refreshToken = refreshToken; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "getAccessTokenExpiresAt", |
| | value: function getAccessTokenExpiresAt() { |
| | return this.accessTokenExpiresAt; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "setAccessTokenExpiresAt", |
| | value: function setAccessTokenExpiresAt(accessTokenExpiresAt) { |
| | this.accessTokenExpiresAt = accessTokenExpiresAt; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "setCodeVerifier", |
| | value: function setCodeVerifier(codeVerifier) { |
| | this.codeVerifier = codeVerifier; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "getCodeVerifier", |
| | value: function getCodeVerifier() { |
| | return this.codeVerifier; |
| | } |
| | }, { |
| | key: "generateCodeChallenge", |
| | value: function generateCodeChallenge() { |
| | var _this = this; |
| |
|
| | var encoder = new Encoder(); |
| | var codeData = encoder.encode(this.codeVerifier); |
| | var codeChallenge; |
| |
|
| | if (isBrowserEnv() || isWorkerEnv()) { |
| | return crypto.subtle.digest('SHA-256', codeData).then(function (digestedHash) { |
| | var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(digestedHash))); |
| | codeChallenge = createBrowserSafeString(base64String).substr(0, 128); |
| | _this.codeChallenge = codeChallenge; |
| | }); |
| | } |
| |
|
| | var digestedHash = crypto.createHash('sha256').update(codeData).digest(); |
| | codeChallenge = createBrowserSafeString(digestedHash); |
| | this.codeChallenge = codeChallenge; |
| | return Promise.resolve(); |
| | } |
| | }, { |
| | key: "generatePKCECodes", |
| | value: function generatePKCECodes() { |
| | var codeVerifier; |
| |
|
| | if (isBrowserEnv() || isWorkerEnv()) { |
| | var array = new Uint8Array(PKCELength); |
| | var randomValueArray = crypto.getRandomValues(array); |
| | var base64String = btoa(randomValueArray); |
| | codeVerifier = createBrowserSafeString(base64String).substr(0, 128); |
| | } else { |
| | var randomBytes = crypto.randomBytes(PKCELength); |
| | codeVerifier = createBrowserSafeString(randomBytes).substr(0, 128); |
| | } |
| |
|
| | this.codeVerifier = codeVerifier; |
| | return this.generateCodeChallenge(); |
| | } |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "getAuthenticationUrl", |
| | value: function getAuthenticationUrl(redirectUri, state) { |
| | var _this2 = this; |
| |
|
| | var authType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'token'; |
| | var tokenAccessType = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; |
| | var scope = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; |
| | var includeGrantedScopes = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'none'; |
| | var usePKCE = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false; |
| | var clientId = this.getClientId(); |
| | var baseUrl = OAuth2AuthorizationUrl(this.domain); |
| |
|
| | if (!clientId) { |
| | throw new Error('A client id is required. You can set the client id using .setClientId().'); |
| | } |
| |
|
| | if (authType !== 'code' && !redirectUri) { |
| | throw new Error('A redirect uri is required.'); |
| | } |
| |
|
| | if (!GrantTypes.includes(authType)) { |
| | throw new Error('Authorization type must be code or token'); |
| | } |
| |
|
| | if (tokenAccessType && !TokenAccessTypes.includes(tokenAccessType)) { |
| | throw new Error('Token Access Type must be legacy, offline, or online'); |
| | } |
| |
|
| | if (scope && !(scope instanceof Array)) { |
| | throw new Error('Scope must be an array of strings'); |
| | } |
| |
|
| | if (!IncludeGrantedScopes.includes(includeGrantedScopes)) { |
| | throw new Error('includeGrantedScopes must be none, user, or team'); |
| | } |
| |
|
| | var authUrl; |
| |
|
| | if (authType === 'code') { |
| | authUrl = "".concat(baseUrl, "?response_type=code&client_id=").concat(clientId); |
| | } else { |
| | authUrl = "".concat(baseUrl, "?response_type=token&client_id=").concat(clientId); |
| | } |
| |
|
| | if (redirectUri) { |
| | authUrl += "&redirect_uri=".concat(redirectUri); |
| | } |
| |
|
| | if (state) { |
| | authUrl += "&state=".concat(state); |
| | } |
| |
|
| | if (tokenAccessType) { |
| | authUrl += "&token_access_type=".concat(tokenAccessType); |
| | } |
| |
|
| | if (scope) { |
| | authUrl += "&scope=".concat(scope.join(' ')); |
| | } |
| |
|
| | if (includeGrantedScopes !== 'none') { |
| | authUrl += "&include_granted_scopes=".concat(includeGrantedScopes); |
| | } |
| |
|
| | if (usePKCE) { |
| | return this.generatePKCECodes().then(function () { |
| | authUrl += '&code_challenge_method=S256'; |
| | authUrl += "&code_challenge=".concat(_this2.codeChallenge); |
| | return authUrl; |
| | }); |
| | } |
| |
|
| | return Promise.resolve(authUrl); |
| | } |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "getAccessTokenFromCode", |
| | value: function getAccessTokenFromCode(redirectUri, code) { |
| | var clientId = this.getClientId(); |
| | var clientSecret = this.getClientSecret(); |
| |
|
| | if (!clientId) { |
| | throw new Error('A client id is required. You can set the client id using .setClientId().'); |
| | } |
| |
|
| | var path = OAuth2TokenUrl(this.domain, this.domainDelimiter); |
| | path += '?grant_type=authorization_code'; |
| | path += "&code=".concat(code); |
| | path += "&client_id=".concat(clientId); |
| |
|
| | if (clientSecret) { |
| | path += "&client_secret=".concat(clientSecret); |
| | } else { |
| | if (!this.codeVerifier) { |
| | throw new Error('You must use PKCE when generating the authorization URL to not include a client secret'); |
| | } |
| |
|
| | path += "&code_verifier=".concat(this.codeVerifier); |
| | } |
| |
|
| | if (redirectUri) { |
| | path += "&redirect_uri=".concat(redirectUri); |
| | } |
| |
|
| | var fetchOptions = { |
| | method: 'POST', |
| | headers: { |
| | 'Content-Type': 'application/x-www-form-urlencoded' |
| | } |
| | }; |
| | return this.fetch(path, fetchOptions).then(function (res) { |
| | return parseResponse(res); |
| | }); |
| | } |
| | |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "checkAndRefreshAccessToken", |
| | value: function checkAndRefreshAccessToken() { |
| | var canRefresh = this.getRefreshToken() && this.getClientId(); |
| | var needsRefresh = !this.getAccessTokenExpiresAt() || new Date(Date.now() + TokenExpirationBuffer) >= this.getAccessTokenExpiresAt(); |
| | var needsToken = !this.getAccessToken(); |
| |
|
| | if ((needsRefresh || needsToken) && canRefresh) { |
| | return this.refreshAccessToken(); |
| | } |
| |
|
| | return Promise.resolve(); |
| | } |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | }, { |
| | key: "refreshAccessToken", |
| | value: function refreshAccessToken() { |
| | var _this3 = this; |
| |
|
| | var scope = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; |
| | var clientId = this.getClientId(); |
| | var clientSecret = this.getClientSecret(); |
| |
|
| | if (!clientId) { |
| | throw new Error('A client id is required. You can set the client id using .setClientId().'); |
| | } |
| |
|
| | if (scope && !(scope instanceof Array)) { |
| | throw new Error('Scope must be an array of strings'); |
| | } |
| |
|
| | var refreshUrl = OAuth2TokenUrl(this.domain, this.domainDelimiter); |
| | var fetchOptions = { |
| | headers: { |
| | 'Content-Type': 'application/json' |
| | }, |
| | method: 'POST' |
| | }; |
| |
|
| | if (this.dataOnBody) { |
| | var body = { |
| | grant_type: 'refresh_token', |
| | client_id: clientId, |
| | refresh_token: this.getRefreshToken() |
| | }; |
| |
|
| | if (clientSecret) { |
| | body.client_secret = clientSecret; |
| | } |
| |
|
| | if (scope) { |
| | body.scope = scope.join(' '); |
| | } |
| |
|
| | fetchOptions.body = body; |
| | } else { |
| | refreshUrl += "?grant_type=refresh_token&refresh_token=".concat(this.getRefreshToken()); |
| | refreshUrl += "&client_id=".concat(clientId); |
| |
|
| | if (clientSecret) { |
| | refreshUrl += "&client_secret=".concat(clientSecret); |
| | } |
| |
|
| | if (scope) { |
| | refreshUrl += "&scope=".concat(scope.join(' ')); |
| | } |
| | } |
| |
|
| | return this.fetch(refreshUrl, fetchOptions).then(function (res) { |
| | return parseResponse(res); |
| | }).then(function (res) { |
| | _this3.setAccessToken(res.result.access_token); |
| |
|
| | _this3.setAccessTokenExpiresAt(getTokenExpiresAtDate(res.result.expires_in)); |
| | }); |
| | } |
| | }]); |
| |
|
| | return DropboxAuth; |
| | }(); |
| |
|
| | export { DropboxAuth as default }; |