From a71d42252826041d45cd093bb5239694c21537bd Mon Sep 17 00:00:00 2001 From: Yury Shkoda Date: Thu, 20 Apr 2023 16:13:22 +0300 Subject: [PATCH 1/3] fix(refreshTokensForViya): fixed FormData logic --- src/auth/getTokens.ts | 3 +++ src/auth/refreshTokensForViya.ts | 7 +++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/auth/getTokens.ts b/src/auth/getTokens.ts index 9dc0c1c..340331a 100644 --- a/src/auth/getTokens.ts +++ b/src/auth/getTokens.ts @@ -29,9 +29,12 @@ export async function getTokens( const error = 'Unable to obtain new access token. Your refresh token has expired.' logger.error(error) + throw new Error(error) } + logger.info('Refreshing access and refresh tokens.') + const tokens = serverType === ServerType.SasViya ? await refreshTokensForViya( diff --git a/src/auth/refreshTokensForViya.ts b/src/auth/refreshTokensForViya.ts index e10d15c..ecb2c4d 100644 --- a/src/auth/refreshTokensForViya.ts +++ b/src/auth/refreshTokensForViya.ts @@ -2,6 +2,7 @@ import { SasAuthResponse } from '@sasjs/utils/types' import { prefixMessage } from '@sasjs/utils/error' import * as NodeFormData from 'form-data' import { RequestClient } from '../request/RequestClient' +import { isNode } from '../utils' /** * Exchanges the refresh token for an access token for the given client. @@ -17,8 +18,7 @@ export async function refreshTokensForViya( refreshToken: string ) { const url = '/SASLogon/oauth/token' - let token - token = + const token = typeof Buffer === 'undefined' ? btoa(clientId + ':' + clientSecret) : Buffer.from(clientId + ':' + clientSecret).toString('base64') @@ -27,8 +27,7 @@ export async function refreshTokensForViya( Authorization: 'Basic ' + token } - const formData = - typeof FormData === 'undefined' ? new NodeFormData() : new FormData() + const formData = isNode() ? new NodeFormData() : new FormData() formData.append('grant_type', 'refresh_token') formData.append('refresh_token', refreshToken) From 836051940825bbadc8f1d4cf3cf362da06a0322d Mon Sep 17 00:00:00 2001 From: Yury Shkoda Date: Fri, 21 Apr 2023 11:03:41 +0300 Subject: [PATCH 2/3] fix(refreshTokensForViya): added throw error if not Node --- src/auth/refreshTokensForViya.ts | 6 +++++- src/auth/spec/refreshTokensForViya.spec.ts | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/auth/refreshTokensForViya.ts b/src/auth/refreshTokensForViya.ts index ecb2c4d..fe5f2b7 100644 --- a/src/auth/refreshTokensForViya.ts +++ b/src/auth/refreshTokensForViya.ts @@ -17,6 +17,10 @@ export async function refreshTokensForViya( clientSecret: string, refreshToken: string ) { + if (!isNode()) { + throw new Error(`Method 'refreshTokensForViya' can only be used by Node.`) + } + const url = '/SASLogon/oauth/token' const token = typeof Buffer === 'undefined' @@ -27,7 +31,7 @@ export async function refreshTokensForViya( Authorization: 'Basic ' + token } - const formData = isNode() ? new NodeFormData() : new FormData() + const formData = new NodeFormData() formData.append('grant_type', 'refresh_token') formData.append('refresh_token', refreshToken) diff --git a/src/auth/spec/refreshTokensForViya.spec.ts b/src/auth/spec/refreshTokensForViya.spec.ts index 49b8f19..e18b983 100644 --- a/src/auth/spec/refreshTokensForViya.spec.ts +++ b/src/auth/spec/refreshTokensForViya.spec.ts @@ -3,6 +3,7 @@ import * as NodeFormData from 'form-data' import { generateToken, mockAuthResponse } from './mockResponses' import { RequestClient } from '../../request/RequestClient' import { refreshTokensForViya } from '../refreshTokensForViya' +import * as IsNodeModule from '../../utils/isNode' const requestClient = new (>RequestClient)() @@ -70,6 +71,18 @@ describe('refreshTokensForViya', () => { expect(error).toEqual(`Error while refreshing tokens: ${tokenError}`) }) + + it('should throw an error if environment is not Node', async () => { + jest.spyOn(IsNodeModule, 'isNode').mockImplementation(() => false) + + const expectedError = new Error( + `Method 'refreshTokensForViya' can only be used by Node.` + ) + + expect( + refreshTokensForViya(requestClient, 'client', 'secret', 'token') + ).rejects.toEqual(expectedError) + }) }) const setupMocks = () => { From a29b7f3b92eab1b69cd75570363973cf527c9fa8 Mon Sep 17 00:00:00 2001 From: Yury Shkoda Date: Fri, 21 Apr 2023 11:06:48 +0300 Subject: [PATCH 3/3] docs(refreshTokensForViya): added notes about limitation --- src/SASViyaApiClient.ts | 1 + src/auth/getTokens.ts | 1 + src/auth/refreshTokensForViya.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index 643bf74..ea5cdb0 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -548,6 +548,7 @@ export class SASViyaApiClient { /** * Exchanges the refresh token for an access token for the given client. + * This method can only be used by Node. * @param clientId - the client ID to authenticate with. * @param clientSecret - the client secret to authenticate with. * @param refreshToken - the refresh token received from the server. diff --git a/src/auth/getTokens.ts b/src/auth/getTokens.ts index 340331a..b4557e2 100644 --- a/src/auth/getTokens.ts +++ b/src/auth/getTokens.ts @@ -10,6 +10,7 @@ import { refreshTokensForSasjs } from './refreshTokensForSasjs' /** * Returns the auth configuration, refreshing the tokens if necessary. + * This function can only be used by Node, if a server type is SASVIYA. * @param requestClient - the pre-configured HTTP request client * @param authConfig - an object containing a client ID, secret, access token and refresh token * @param serverType - server type for which refreshing the tokens, defaults to SASVIYA diff --git a/src/auth/refreshTokensForViya.ts b/src/auth/refreshTokensForViya.ts index fe5f2b7..4fb8f80 100644 --- a/src/auth/refreshTokensForViya.ts +++ b/src/auth/refreshTokensForViya.ts @@ -6,6 +6,7 @@ import { isNode } from '../utils' /** * Exchanges the refresh token for an access token for the given client. + * This function can only be used by Node. * @param requestClient - the pre-configured HTTP request client * @param clientId - the client ID to authenticate with. * @param clientSecret - the client secret to authenticate with.