Skip to content

Commit

Permalink
fix merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
yunakim714 committed Sep 25, 2024
2 parents 0ba4da2 + b587cbf commit 69166fc
Show file tree
Hide file tree
Showing 2 changed files with 287 additions and 1 deletion.
148 changes: 148 additions & 0 deletions src/static/helpers/slasHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ const authenticateCustomerMock = jest.fn(() => ({url}));
const getAccessTokenMock = jest.fn(() => expectedTokenResponse);
const logoutCustomerMock = jest.fn(() => expectedTokenResponse);
const generateCodeChallengeMock = jest.fn(() => 'code_challenge');
const authorizePasswordlessCustomerMock = jest.fn();
const getPasswordLessAccessTokenMock = jest.fn();

const createMockSlasClient = () =>
({
Expand All @@ -73,6 +75,8 @@ const createMockSlasClient = () =>
getAccessToken: getAccessTokenMock,
logoutCustomer: logoutCustomerMock,
generateCodeChallenge: generateCodeChallengeMock,
authorizePasswordlessCustomer: authorizePasswordlessCustomerMock,
getPasswordLessAccessToken: getPasswordLessAccessTokenMock,
} as unknown as ShopperLogin<{
shortCode: string;
organizationId: string;
Expand Down Expand Up @@ -490,6 +494,150 @@ describe('Social login user flow', () => {
});
});

describe('authorizePasswordless is working', () => {
test('Correct parameters are used to call SLAS Client authorize', async () => {
const mockSlasClient = createMockSlasClient();
const {clientId, organizationId, siteId} =
mockSlasClient.clientConfig.parameters;

const parametersAuthorizePasswordless = {
callbackURI: 'www.something.com/callback',
usid: 'a_usid',
userid: 'a_userid',
locale: 'a_locale',
mode: 'callback',
};
const authHeaderExpected = `Basic ${slasHelper.stringToBase64(
`${clientId}:${credentialsPrivate.clientSecret}`
)}`;
await slasHelper.authorizePasswordless(
mockSlasClient,
credentialsPrivate,
parametersAuthorizePasswordless
);
const expectedReqOptions = {
headers: {
Authorization: authHeaderExpected,
},
parameters: {
organizationId,
},
body: {
user_id: parametersAuthorizePasswordless.userid,
mode: parametersAuthorizePasswordless.mode,
locale: parametersAuthorizePasswordless.locale,
channel_id: siteId,
callback_uri: parametersAuthorizePasswordless.callbackURI,
usid: parametersAuthorizePasswordless.usid,
},
};
expect(authorizePasswordlessCustomerMock).toBeCalledWith(
expectedReqOptions,
true
);
});
test('Throw when required parameters missing', async () => {
const mockSlasClient = {
clientConfig: {
parameters: {
shortCode: 'short_code',
organizationId: 'organization_id',
clientId: 'client_id',
},
},
authorizePasswordlessCustomer: authorizePasswordlessCustomerMock,
getPasswordLessAccessToken: getPasswordLessAccessTokenMock,
} as unknown as ShopperLogin<{
shortCode: string;
organizationId: string;
clientId: string;
siteId: string;
}>;
const parametersAuthorizePasswordless = {
callbackURI: 'www.something.com/callback',
usid: 'a_usid',
userid: 'a_userid',
locale: 'a_locale',
mode: 'callback',
};
await expect(
slasHelper.authorizePasswordless(
mockSlasClient,
credentialsPrivate,
parametersAuthorizePasswordless
)
).rejects.toThrow(
'Required argument channel_id is not provided through clientConfig.parameters.siteId'
);
});
});

describe('getPasswordLessAccessToken is working', () => {
test('Correct parameters are used to call SLAS Client helper', async () => {
const mockSlasClient = createMockSlasClient();
const {clientId, organizationId} = mockSlasClient.clientConfig.parameters;

const parametersPasswordlessToken = {
pwdlessLoginToken: '123456',
dnt: '1',
};
const authHeaderExpected = `Basic ${slasHelper.stringToBase64(
`${clientId}:${credentialsPrivate.clientSecret}`
)}`;
await slasHelper.getPasswordLessAccessToken(
mockSlasClient,
credentialsPrivate,
parametersPasswordlessToken
);
const expectedReqOptions = {
headers: {
Authorization: authHeaderExpected,
},
parameters: {
organizationId,
},
body: {
dnt: parametersPasswordlessToken.dnt,
code_verifier: expect.stringMatching(/./) as string,
grant_type: 'client_credentials',
hint: 'pwdless_login',
pwdless_login_token: parametersPasswordlessToken.pwdlessLoginToken,
},
};
expect(getPasswordLessAccessTokenMock).toBeCalledWith(expectedReqOptions);
});
test('Throw when required parameters missing', async () => {
const mockSlasClient = {
clientConfig: {
parameters: {
shortCode: 'short_code',
clientId: 'client_id',
},
},
authorizePasswordlessCustomer: authorizePasswordlessCustomerMock,
getPasswordLessAccessToken: getPasswordLessAccessTokenMock,
} as unknown as ShopperLogin<{
shortCode: string;
organizationId: string;
clientId: string;
siteId: string;
}>;
const parametersPasswordlessToken = {
pwdlessLoginToken: '123456',
dnt: '1',
};
await expect(
slasHelper.getPasswordLessAccessToken(
mockSlasClient,
credentialsPrivate,
parametersPasswordlessToken
)
).rejects.toThrow(
'Required argument organizationId is not provided through clientConfig.parameters.organizationId'
);
});
});

describe('Refresh Token', () => {
test('refreshes the token with slas public client', () => {
const expectedBody = {
Expand Down
140 changes: 139 additions & 1 deletion src/static/helpers/slasHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,144 @@ export async function loginIDPUser(
return slasClient.getAccessToken({body: tokenBody});
}

/* Function to send passwordless login token
* **Note** At the moment, passwordless is only supported on private client
* @param slasClient a configured instance of the ShopperLogin SDK client.
* @param credentials - the id and password and clientSecret (if applicable) to login with.
* @param credentials.clientSecret? - secret associated with client ID
* @param parameters - parameters to pass in the API calls.
* @param parameters.callbackURI? - URI to send the passwordless login token to. Must be listed in your SLAS configuration. Required when mode is callback
* @param parameters.usid? - Unique Shopper Identifier to enable personalization.
* @param parameters.userid - User Id for login
* @param parameters.locale - The locale of the template. Not needed for the callback mode
* @param parameters.mode - Medium of sending login token
* @returns Promise of Response
*/
export async function authorizePasswordless(
slasClient: ShopperLogin<{
shortCode: string;
organizationId: string;
clientId: string;
siteId: string;
}>,
credentials: {
clientSecret: string;
},
parameters: {
callbackURI?: string;
usid?: string;
userid: string;
locale?: string;
mode: string;
}
): Promise<Response> {
if (!credentials.clientSecret) {
throw new Error('Required argument client secret is not provided');
}
if (!slasClient.clientConfig.parameters.siteId) {
throw new Error(
'Required argument channel_id is not provided through clientConfig.parameters.siteId'
);
}
if (!parameters.mode) {
throw new Error(
'Required argument mode is not provided through parameters'
);
}
if (!parameters.userid) {
throw new Error(
'Required argument userid is not provided through parameters'
);
}
const authHeaderIdSecret = `Basic ${stringToBase64(
`${slasClient.clientConfig.parameters.clientId}:${credentials.clientSecret}`
)}`;
const tokenBody = {
user_id: parameters.userid,
mode: parameters.mode,
...(parameters.locale && {locale: parameters.locale}),
...(parameters.usid && {usid: parameters.usid}),
channel_id: slasClient.clientConfig.parameters.siteId,
...(parameters.callbackURI && {callback_uri: parameters.callbackURI}),
};

return slasClient.authorizePasswordlessCustomer(
{
headers: {
Authorization: authHeaderIdSecret,
},
parameters: {
organizationId: slasClient.clientConfig.parameters.organizationId,
},
body: tokenBody,
},
true
);
}

/**
* Function to login user with passwordless login token
* **Note** At the moment, passwordless is only supported on private client
* @param slasClient a configured instance of the ShopperLogin SDK client.
* @param credentials - the id and password and clientSecret (if applicable) to login with.
* @param credentials.clientSecret? - secret associated with client ID
* @param parameters - parameters to pass in the API calls.
* @param parameters.callbackURI? - URI to send the passwordless login token to. Must be listed in your SLAS configuration. Required when mode is callback
* @param parameters.pwdlessLoginToken - Passwordless login token
* @param parameters.dnt? - Optional parameter to enable Do Not Track (DNT) for the user.
* @returns Promise of Response or Object
*/
export async function getPasswordLessAccessToken(
slasClient: ShopperLogin<{
shortCode: string;
organizationId: string;
clientId: string;
siteId: string;
}>,
credentials: {
clientSecret: string;
},
parameters: {
pwdlessLoginToken: string;
dnt?: string;
}
): Promise<TokenResponse> {
if (!credentials.clientSecret) {
throw new Error('Required argument client secret is not provided');
}
if (!slasClient.clientConfig.parameters.organizationId) {
throw new Error(
'Required argument organizationId is not provided through clientConfig.parameters.organizationId'
);
}
if (!parameters.pwdlessLoginToken) {
throw new Error(
'Required argument pwdlessLoginToken is not provided through parameters'
);
}
const codeVerifier = createCodeVerifier();
const authHeaderIdSecret = `Basic ${stringToBase64(
`${slasClient.clientConfig.parameters.clientId}:${credentials.clientSecret}`
)}`;

const tokenBody = {
grant_type: 'client_credentials',
hint: 'pwdless_login',
pwdless_login_token: parameters.pwdlessLoginToken,
code_verifier: codeVerifier,
...(parameters.dnt && {dnt: parameters.dnt}),
};
return slasClient.getPasswordLessAccessToken({
headers: {
Authorization: authHeaderIdSecret,
},
parameters: {
organizationId: slasClient.clientConfig.parameters.organizationId,
},
body: tokenBody,
});
}

/**
* Exchange a refresh token for a new access token.
* **Note**: this func can run on client side. Only use private slas when the slas client secret is secured.
Expand Down Expand Up @@ -519,4 +657,4 @@ export function logout(
channel_id: slasClient.clientConfig.parameters.siteId,
},
});
}
}

Check warning on line 660 in src/static/helpers/slasHelper.ts

View workflow job for this annotation

GitHub Actions / linux-tests (12)

Insert `⏎`

Check warning on line 660 in src/static/helpers/slasHelper.ts

View workflow job for this annotation

GitHub Actions / linux-tests (14)

Insert `⏎`

Check warning on line 660 in src/static/helpers/slasHelper.ts

View workflow job for this annotation

GitHub Actions / linux-tests (16)

Insert `⏎`

Check warning on line 660 in src/static/helpers/slasHelper.ts

View workflow job for this annotation

GitHub Actions / linux-tests (18)

Insert `⏎`

0 comments on commit 69166fc

Please sign in to comment.