diff --git a/package.json b/package.json index 6c64c33..eb2cc86 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@al/core", - "version": "1.2.40", + "version": "1.2.41", "description": "Node Enterprise Packages for Alert Logic (NEPAL) Core Library", "main": "./dist/index.cjs.js", "types": "./dist/index.d.ts", diff --git a/src/aims-client/types/types.ts b/src/aims-client/types/types.ts index 61750e6..b867f76 100644 --- a/src/aims-client/types/types.ts +++ b/src/aims-client/types/types.ts @@ -39,6 +39,7 @@ export interface AIMSAccount { fortra_authenticated?: boolean; fortra_required_after?: number; idle_session_timeout?: number; + stateramp_required?: boolean; created: AlChangeStamp; modified: AlChangeStamp; } diff --git a/src/client/al-api-client.ts b/src/client/al-api-client.ts index d7f7743..b0ad841 100644 --- a/src/client/al-api-client.ts +++ b/src/client/al-api-client.ts @@ -480,13 +480,17 @@ export class AlApiClient implements AlValidationSchemaProvider * Under ordinary circumstances, you should *not* be calling this directly -- instead, you should use the top-level * `authenticate` method on @al/session's ALSession instance. */ - async authenticate( user: string, pass: string, mfa?:string, ignoreWarning?:boolean ):Promise { + /* tslint:disable:variable-name */ + async authenticate( user: string, pass: string, mfa_code?:string, ignoreWarning?:boolean, payloadExtras?:any ):Promise { if ( ! ignoreWarning ) { console.warn("Warning: this low level authentication method is intended only for use by other services, and will not create a reusable session. Are you sure you intended to use it?" ); } - let payload = {}; - if (mfa) { - payload = { mfa_code: mfa }; + let payload:any = {}; + if ( payloadExtras && typeof( payloadExtras ) === 'object' ) { + payload = { ...payload, ...payloadExtras }; + } + if (mfa_code) { + payload.mfa_code = mfa_code; } return this.post( { service_stack: AlLocation.GlobalAPI, @@ -501,13 +505,17 @@ export class AlApiClient implements AlValidationSchemaProvider }); } - async authenticateViaGestalt( user:string, pass:string, ignoreWarning?:boolean ):Promise { + async authenticateViaGestalt( user:string, pass:string, ignoreWarning?:boolean, payloadExtras?:any ):Promise { + let data:any = { + authorization: `Basic ${this.base64Encode(`${user}:${pass}`)}` + }; + if ( payloadExtras && typeof( payloadExtras ) === 'object' ) { + data.payloadExtras = payloadExtras; + } return this.post( { + data, url: this.getGestaltAuthenticationURL(), withCredentials: true, - data: { - authorization: `Basic ${this.base64Encode(`${user}:${pass}`)}` - }, responseType: "json" } ); } diff --git a/src/session/utilities/al-authentication.utility.ts b/src/session/utilities/al-authentication.utility.ts index 4d4b994..0a415f1 100644 --- a/src/session/utilities/al-authentication.utility.ts +++ b/src/session/utilities/al-authentication.utility.ts @@ -70,11 +70,11 @@ export class AlAuthenticationUtility { /** * Primary authentication method -- attempts to authenticate using a username and password. */ - public async authenticate( userName:string, passPhrase:string ):Promise { + public async authenticate( userName:string, passPhrase:string, payloadExtras?:any ):Promise { let useGestalt = AlRuntimeConfiguration.getOption( ConfigOption.GestaltAuthenticate, false ); if ( useGestalt ) { try { - let session = await AlDefaultClient.authenticateViaGestalt( userName, passPhrase, true ); + let session = await AlDefaultClient.authenticateViaGestalt( userName, passPhrase, true, payloadExtras ); return await this.finalizeSession( session ); } catch( e ) { if ( this.handleAuthenticationFailure( e ) ) { @@ -84,7 +84,7 @@ export class AlAuthenticationUtility { } try { - let session = await AlDefaultClient.authenticate( userName, passPhrase, undefined, true ); + let session = await AlDefaultClient.authenticate( userName, passPhrase, undefined, true, payloadExtras ); return await this.finalizeSession( session ); } catch( e ) { if ( this.handleAuthenticationFailure( e ) ) { @@ -103,21 +103,6 @@ export class AlAuthenticationUtility { /* * This doesn't exist yet, and may never need to */ - /* - let useGestalt = AlRuntimeConfiguration.getOption( ConfigOption.GestaltAuthenticate, false ); - if ( useGestalt && AlLocatorService.getCurrentEnvironment() !== 'development' ) { - try { - let session = await this.authenticateViaGestaltFromFortra( fortraSession ); - return await this.finalizeSession( session ); - } catch( e ) { - if ( this.handleAuthenticationFailure( e ) ) { - return this.state.result; - } - throw e; - } - } - */ - try { let session = await this.authenticateViaAIMSFromFortra( fortraSession ); return await this.finalizeSession( session ); diff --git a/test/client/al-api-client.spec.ts b/test/client/al-api-client.spec.ts index 25a9a0a..333cd72 100644 --- a/test/client/al-api-client.spec.ts +++ b/test/client/al-api-client.spec.ts @@ -326,14 +326,21 @@ describe("AlDefaultClient", () => { expect(JSON.parse(req.body())).to.deep.equals({mfa_code: mfaCode}); return res.status(200).body(defaultAuthResponse); }); - try { - const sessionDescriptor = await AlDefaultClient.authenticate(username, password, mfaCode, true ); - expect( sessionDescriptor ).to.deep.equals( defaultAuthResponse ); - } catch( e ) { - console.error("Got error...", e ); - } + const sessionDescriptor = await AlDefaultClient.authenticate(username, password, mfaCode, true ); + expect( sessionDescriptor ).to.deep.equals( defaultAuthResponse ); }); }); + describe('and with extra payload content', () => { + it( 'should perform the authenticate request and include the extra payload content in the request body', async () => { + xhrMock.post('https://api.global-integration.product.dev.alertlogic.com/aims/v1/authenticate', ( req, res ) => { + expect(req.header('Authorization')).to.equal(`Basic ${btoa(unescape(encodeURIComponent(`${username}:${password}`)))}`); + expect(JSON.parse(req.body())).to.deep.equals({ seen_stateramp_banner: true }); + return res.status(200).body(defaultAuthResponse); + } ); + const sessionDescriptor = await AlDefaultClient.authenticate( username, password, undefined, true, { seen_stateramp_banner: true } ); + expect( sessionDescriptor ).to.deep.equals( defaultAuthResponse ); + } ); + } ); }); describe('When authenticating a user with a session token and mfa code', () => {