diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts
index c9ae9bf..ae8f8d3 100644
--- a/src/SASViyaApiClient.ts
+++ b/src/SASViyaApiClient.ts
@@ -18,7 +18,6 @@ import { ContextManager } from './ContextManager'
import { timestampToYYYYMMDDHHMMSS } from '@sasjs/utils/time'
import { Logger, LogLevel } from '@sasjs/utils/logger'
import { isAuthorizeFormRequired } from './auth/isAuthorizeFormRequired'
-import { parseAndSubmitAuthorizeForm } from './auth'
import { RequestClient } from './request/RequestClient'
import { NotFoundError } from './types/NotFoundError'
@@ -632,10 +631,7 @@ export class SASViyaApiClient {
.then(async (response) => {
let code = ''
if (isAuthorizeFormRequired(response)) {
- const formResponse: any = await parseAndSubmitAuthorizeForm(
- response,
- this.serverUrl
- )
+ const formResponse: any = await this.requestClient.authorize(response)
const responseBody = formResponse
.split('
')[1]
diff --git a/src/SASjs.ts b/src/SASjs.ts
index c3b27ff..d411a9e 100644
--- a/src/SASjs.ts
+++ b/src/SASjs.ts
@@ -716,6 +716,7 @@ export default class SASjs {
this.authManager = new AuthManager(
this.sasjsConfig.serverUrl,
this.sasjsConfig.serverType!,
+ this.requestClient,
this.resendWaitingRequests
)
diff --git a/src/auth/AuthManager.ts b/src/auth/AuthManager.ts
index 1d1f315..e40c7ed 100644
--- a/src/auth/AuthManager.ts
+++ b/src/auth/AuthManager.ts
@@ -1,19 +1,18 @@
import { ServerType } from '@sasjs/utils/types'
-import axios, { AxiosInstance } from 'axios'
-import { isAuthorizeFormRequired, parseAndSubmitAuthorizeForm } from '.'
+import { isAuthorizeFormRequired } from '.'
+import { RequestClient } from '../request/RequestClient'
import { serialize } from '../utils'
export class AuthManager {
public userName = ''
private loginUrl: string
private logoutUrl: string
- private httpClient: AxiosInstance
constructor(
private serverUrl: string,
private serverType: ServerType,
+ private requestClient: RequestClient,
private loginCallback: () => Promise
) {
- this.httpClient = axios.create({ baseURL: this.serverUrl })
this.loginUrl = `/SASLogon/login`
this.logoutUrl =
this.serverType === ServerType.Sas9
@@ -50,21 +49,21 @@ export class AuthManager {
}
const loginParamsStr = serialize(loginParams)
- const loginResponse = await this.httpClient
- .post(this.loginUrl, loginParamsStr, {
- withCredentials: true,
- responseType: 'text',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- Accept: '*/*'
- }
- })
- .then((response) => response.data)
+ const { result: loginResponse } = await this.requestClient.post(
+ this.loginUrl,
+ loginParamsStr,
+ undefined,
+ 'text/plain',
+ {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ Accept: '*/*'
+ }
+ )
let loggedIn
if (isAuthorizeFormRequired(loginResponse)) {
- await parseAndSubmitAuthorizeForm(loginResponse, this.serverUrl)
+ await this.requestClient.authorize(loginResponse)
} else {
loggedIn = isLogInSuccess(loginResponse)
}
@@ -89,16 +88,12 @@ export class AuthManager {
* @returns - a promise which resolves with an object containing two values - a boolean `isLoggedIn`, and a string `userName`.
*/
public async checkSession() {
- const loginResponse = await this.httpClient.get(
+ const { result: loginResponse } = await this.requestClient.get(
this.loginUrl.replace('.do', ''),
- {
- responseType: 'text',
- headers: {
- Accept: '*/*'
- }
- }
+ undefined,
+ 'text/plain'
)
- const responseText = loginResponse?.data
+ const responseText = loginResponse
const isLoggedIn = / true)
+ this.requestClient.clearCsrfTokens()
+ return this.requestClient.get(this.logoutUrl, undefined).then(() => true)
}
}
diff --git a/src/auth/index.ts b/src/auth/index.ts
index 9641d3f..b2d09d0 100644
--- a/src/auth/index.ts
+++ b/src/auth/index.ts
@@ -1,6 +1,3 @@
-import { AuthManager } from './AuthManager'
-
export * from './AuthManager'
export * from './isAuthorizeFormRequired'
export * from './isLoginRequired'
-export * from './parseAndSubmitAuthorizeForm'
diff --git a/src/auth/parseAndSubmitAuthorizeForm.ts b/src/auth/parseAndSubmitAuthorizeForm.ts
deleted file mode 100644
index 28f342a..0000000
--- a/src/auth/parseAndSubmitAuthorizeForm.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import axios from 'axios'
-
-export const parseAndSubmitAuthorizeForm = async (
- response: string,
- serverUrl: string
-) => {
- let authUrl: string | null = null
- const params: any = {}
-
- const responseBody = response.split('')[1].split('')[0]
- const bodyElement = document.createElement('div')
- bodyElement.innerHTML = responseBody
-
- const form = bodyElement.querySelector('#application_authorization')
- authUrl = form ? serverUrl + form.getAttribute('action') : null
-
- const inputs: any = form?.querySelectorAll('input')
-
- for (const input of inputs) {
- if (input.name === 'user_oauth_approval') {
- input.value = 'true'
- }
-
- params[input.name] = input.value
- }
-
- const formData = new FormData()
-
- for (const key in params) {
- if (params.hasOwnProperty(key)) {
- formData.append(key, params[key])
- }
- }
-
- if (!authUrl) {
- throw new Error('Auth Form URL is null or undefined.')
- }
-
- return await axios
- .post(authUrl, formData, {
- withCredentials: true,
- responseType: 'text',
- headers: {
- Accept: '*/*'
- }
- })
- .then((res) => res.data)
-}
diff --git a/src/auth/spec/AuthManager.spec.ts b/src/auth/spec/AuthManager.spec.ts
index 111319e..71d5c2d 100644
--- a/src/auth/spec/AuthManager.spec.ts
+++ b/src/auth/spec/AuthManager.spec.ts
@@ -1,6 +1,5 @@
import { AuthManager } from '../AuthManager'
import * as dotenv from 'dotenv'
-import * as authModule from '..'
import { ServerType } from '@sasjs/utils/types'
import axios from 'axios'
import {
@@ -8,8 +7,8 @@ import {
mockLoginSuccessResponse
} from './mockResponses'
import { serialize } from '../../utils'
+import { RequestClient } from '../../request/RequestClient'
jest.mock('axios')
-jest.mock('../parseAndSubmitAuthorizeForm')
const mockedAxios = axios as jest.Mocked
describe('AuthManager', () => {
@@ -18,6 +17,7 @@ describe('AuthManager', () => {
const serverType = ServerType.SasViya
const userName = 'test-username'
const password = 'test-password'
+ const requestClient = new RequestClient(serverUrl)
beforeAll(() => {
dotenv.config()
@@ -25,12 +25,16 @@ describe('AuthManager', () => {
})
it('should instantiate and set the correct URLs for a Viya server', () => {
- const authManager = new AuthManager(serverUrl, serverType, authCallback)
+ const authManager = new AuthManager(
+ serverUrl,
+ serverType,
+ requestClient,
+ authCallback
+ )
expect(authManager).toBeTruthy()
expect((authManager as any).serverUrl).toEqual(serverUrl)
expect((authManager as any).serverType).toEqual(serverType)
- expect((authManager as any).httpClient).toBeTruthy()
expect((authManager as any).loginUrl).toEqual(`/SASLogon/login`)
expect((authManager as any).logoutUrl).toEqual('/SASLogon/logout.do?')
})
@@ -39,18 +43,27 @@ describe('AuthManager', () => {
const authCallback = () => Promise.resolve()
const serverType = ServerType.Sas9
- const authManager = new AuthManager(serverUrl, serverType, authCallback)
+ const authManager = new AuthManager(
+ serverUrl,
+ serverType,
+ requestClient,
+ authCallback
+ )
expect(authManager).toBeTruthy()
expect((authManager as any).serverUrl).toEqual(serverUrl)
expect((authManager as any).serverType).toEqual(serverType)
- expect((authManager as any).httpClient).toBeTruthy()
expect((authManager as any).loginUrl).toEqual(`/SASLogon/login`)
expect((authManager as any).logoutUrl).toEqual('/SASLogon/logout?')
})
it('should call the auth callback and return when already logged in', async (done) => {
- const authManager = new AuthManager(serverUrl, serverType, authCallback)
+ const authManager = new AuthManager(
+ serverUrl,
+ serverType,
+ requestClient,
+ authCallback
+ )
jest.spyOn(authManager, 'checkSession').mockImplementation(() =>
Promise.resolve({
isLoggedIn: true,
@@ -68,7 +81,12 @@ describe('AuthManager', () => {
})
it('should post a login request to the server if not logged in', async (done) => {
- const authManager = new AuthManager(serverUrl, serverType, authCallback)
+ const authManager = new AuthManager(
+ serverUrl,
+ serverType,
+ requestClient,
+ authCallback
+ )
jest.spyOn(authManager, 'checkSession').mockImplementation(() =>
Promise.resolve({
isLoggedIn: false,
@@ -96,7 +114,6 @@ describe('AuthManager', () => {
loginParams,
{
withCredentials: true,
- responseType: 'text',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Accept: '*/*'
@@ -108,9 +125,14 @@ describe('AuthManager', () => {
})
it('should parse and submit the authorisation form when necessary', async (done) => {
- const authManager = new AuthManager(serverUrl, serverType, authCallback)
+ const authManager = new AuthManager(
+ serverUrl,
+ serverType,
+ requestClient,
+ authCallback
+ )
jest
- .spyOn(authModule, 'parseAndSubmitAuthorizeForm')
+ .spyOn(requestClient, 'authorize')
.mockImplementation(() => Promise.resolve())
jest.spyOn(authManager, 'checkSession').mockImplementation(() =>
Promise.resolve({
@@ -125,15 +147,19 @@ describe('AuthManager', () => {
await authManager.logIn(userName, password)
- expect(authModule.parseAndSubmitAuthorizeForm).toHaveBeenCalledWith(
- mockLoginAuthoriseRequiredResponse,
- serverUrl
+ expect(requestClient.authorize).toHaveBeenCalledWith(
+ mockLoginAuthoriseRequiredResponse
)
done()
})
it('should check and return session information if logged in', async (done) => {
- const authManager = new AuthManager(serverUrl, serverType, authCallback)
+ const authManager = new AuthManager(
+ serverUrl,
+ serverType,
+ requestClient,
+ authCallback
+ )
mockedAxios.get.mockImplementation(() =>
Promise.resolve({ data: '