/// import { ConfigurationError } from './error'; import { WebApiClient } from '../web-api/web-api-client'; import { WebApiConfiguration } from './web-api-configuration'; /** * @export * @class AccessTokenProvider * @implements {AccessTokenProviderInterface} */ export class AccessTokenProvider implements AccessTokenProviderInterface { private token: AccessToken; private client: WebApiClient; private code: string; private secret: string; /** * Set access token given in initialization * @param {WebApiConfiguration} config */ constructor(config: WebApiConfiguration) { this.client = new AccessTokenProviderClient(config); if (config.oauth2 && config.oauth2.clientSecret) { this.secret = config.oauth2.clientSecret; } } /** * Set token and expiration properties of a given tokeng * @param {AccessToken|string} token * @returns {void} */ useAccessToken(token: AccessToken | string): void { if (typeof token === 'string') { this.token = { token: token, tokenType: 'bearer', expiresIn: Date.now() } return; } this.token = token; this.token.expiresIn = Date.now() + ((token).expiresIn * 1000) - 5000; } /** * @param {string} code */ useCode(code: string) { this.code = code; } /** * @returns {string} */ getCode(): string { return this.code; } /** * @returns {Promise} */ getAccessToken(): Promise { return new Promise((resolve, reject) => { // Resolve with saved access token if it's not expired else call refreshAccessToken method if (this.token && (Date.now() < this.token.expiresIn) || !this.secret) { resolve(this.token); } else if (this.token) { this.refreshAccessToken(); } else { if (!this.code) { throw new ConfigurationError('Code has to be set before getting access token. Use ProcessRedirect function for parsing redirect url with code or useCode function to set the code'); } var data = { grant_type: 'authorization_code', code: this.code, client_id: this.client.config.oauth2.clientId, client_secret: this.client.config.oauth2.clientSecret, redirect_uri: this.client.config.oauth2.redirectUri, expires_in: '3600', } this.client.callApi(`${this.client.config.environment.oAuth2ContextBaseUrl}/token`, 'POST', null, this.joinAndEncodeData(data), { 'Content-Type': 'application/x-www-form-urlencoded', 'web-api-key': '', }) .then(token => { this.useAccessToken({ token: token.access_token, tokenType: token.token_type, expiresIn: token.expires_in }); resolve(this.token); }); } }); } /** * Refresh access token and return it in promise * @returns {Promise} */ refreshAccessToken(): Promise { if (!this.secret) { throw new ConfigurationError('Access token cannot be refreshed if you use implicit flow'); } // Throw ConfigurationError if client is not set if (!this.client) { throw new ConfigurationError('WebApiClient has to be set on AccessTokenProvider if you want use it'); } if (!this.client.config.oauth2.clientId || !this.client.config.oauth2.redirectUri) { throw new ConfigurationError('clientId and redirectUri has to be set if you want to get access token'); } return new Promise((resolve, reject) => { var data = { refresh_token: this.token.refreshToken, code: this.code, client_id: this.client.config.oauth2.clientId, client_secret: this.client.config.oauth2.clientSecret, redirect_uri: this.client.config.oauth2.redirectUri, grant_type: 'refresh_token' } // Call client's makeCall method to perform call on the API server this.client.callApi( `${this.client.config.environment.oAuth2ContextBaseUrl}/token`, 'POST', null, this.joinAndEncodeData(data), { "Content-Type": "application/x-www-form-urlencoded" } ).then(token => { // If call is successful then set token and resolve this.useAccessToken({ token: token.access_token, tokenType: token.token_type, expiresIn: token.expires_in }); resolve(this.token); }) .catch(error => { // reject with error if call is unsuccessful reject(error); }); }); } /** * Helper method to join and encode data * @private * @param {any} data * @returns {string} */ private joinAndEncodeData(data: any): string { var arr = []; for (var prop in data) { arr.push(`${prop}=${data[prop]}`); } return encodeURI(arr.join('&')); } } /** * @export * @interface AccessTokenProviderInterface */ export interface AccessTokenProviderInterface { /** * Returns access token */ getAccessToken(): Promise; /** * Calls the API in order to refresh token and returns */ refreshAccessToken(): Promise; /** * Sets access token on */ useAccessToken(token: AccessToken | string): void; useCode(string): void; getCode(): string; } /** * @export * @interface AccessToken */ export interface AccessToken { token: string; expiresIn: number; tokenType: string; refreshToken?: string; } /** * @export * @class AccessTokenProviderClient * @extends {WebApiClient} */ export class AccessTokenProviderClient extends WebApiClient { constructor(config) { super(config, ''); } }