authentication-strategy.e2e-spec.ts 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import { ErrorCode } from '@vendure/common/lib/generated-shop-types';
  2. import { pick } from '@vendure/common/lib/pick';
  3. import { mergeConfig } from '@vendure/core';
  4. import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
  5. import gql from 'graphql-tag';
  6. import path from 'path';
  7. import { initialData } from '../../../e2e-common/e2e-initial-data';
  8. import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
  9. import { NativeAuthenticationStrategy } from '../src/config/auth/native-authentication-strategy';
  10. import { DefaultLogger } from '../src/config/logger/default-logger';
  11. import { TestAuthenticationStrategy, VALID_AUTH_TOKEN } from './fixtures/test-authentication-strategies';
  12. import { CURRENT_USER_FRAGMENT } from './graphql/fragments';
  13. import {
  14. Authenticate,
  15. CurrentUser,
  16. CurrentUserFragment,
  17. GetCustomerHistory,
  18. GetCustomers,
  19. GetCustomerUserAuth,
  20. HistoryEntryType,
  21. Me,
  22. } from './graphql/generated-e2e-admin-types';
  23. import { Register } from './graphql/generated-e2e-shop-types';
  24. import { GET_CUSTOMER_HISTORY, ME } from './graphql/shared-definitions';
  25. import { REGISTER_ACCOUNT } from './graphql/shop-definitions';
  26. import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
  27. describe('AuthenticationStrategy', () => {
  28. const { server, adminClient, shopClient } = createTestEnvironment(
  29. mergeConfig(testConfig, {
  30. authOptions: {
  31. shopAuthenticationStrategy: [
  32. new NativeAuthenticationStrategy(),
  33. new TestAuthenticationStrategy(),
  34. ],
  35. },
  36. }),
  37. );
  38. beforeAll(async () => {
  39. await server.init({
  40. initialData,
  41. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  42. customerCount: 1,
  43. });
  44. await adminClient.asSuperAdmin();
  45. }, TEST_SETUP_TIMEOUT_MS);
  46. afterAll(async () => {
  47. await server.destroy();
  48. });
  49. const currentUserGuard: ErrorResultGuard<CurrentUserFragment> = createErrorResultGuard<
  50. CurrentUserFragment
  51. >(input => input.identifier != null);
  52. describe('external auth', () => {
  53. const userData = {
  54. email: 'test@email.com',
  55. firstName: 'Cixin',
  56. lastName: 'Liu',
  57. };
  58. let newCustomerId: string;
  59. it('fails with a bad token', async () => {
  60. const { authenticate } = await shopClient.query(AUTHENTICATE, {
  61. input: {
  62. test_strategy: {
  63. token: 'bad-token',
  64. },
  65. },
  66. });
  67. expect(authenticate.message).toBe('The provided credentials are invalid');
  68. expect(authenticate.errorCode).toBe(ErrorCode.INVALID_CREDENTIALS_ERROR);
  69. });
  70. it('creates a new Customer with valid token', async () => {
  71. const { customers: before } = await adminClient.query<GetCustomers.Query>(GET_CUSTOMERS);
  72. expect(before.totalItems).toBe(1);
  73. const { authenticate } = await shopClient.query<Authenticate.Mutation>(AUTHENTICATE, {
  74. input: {
  75. test_strategy: {
  76. token: VALID_AUTH_TOKEN,
  77. userData,
  78. },
  79. },
  80. });
  81. currentUserGuard.assertSuccess(authenticate);
  82. expect(authenticate.identifier).toEqual(userData.email);
  83. const { customers: after } = await adminClient.query<GetCustomers.Query>(GET_CUSTOMERS);
  84. expect(after.totalItems).toBe(2);
  85. expect(after.items.map(i => i.emailAddress)).toEqual([
  86. 'hayden.zieme12@hotmail.com',
  87. userData.email,
  88. ]);
  89. newCustomerId = after.items[1].id;
  90. });
  91. it('creates customer history entry', async () => {
  92. const { customer } = await adminClient.query<
  93. GetCustomerHistory.Query,
  94. GetCustomerHistory.Variables
  95. >(GET_CUSTOMER_HISTORY, {
  96. id: newCustomerId,
  97. });
  98. expect(
  99. customer?.history.items.sort((a, b) => (a.id > b.id ? 1 : -1)).map(pick(['type', 'data'])),
  100. ).toEqual([
  101. {
  102. type: HistoryEntryType.CUSTOMER_REGISTERED,
  103. data: {
  104. strategy: 'test_strategy',
  105. },
  106. },
  107. {
  108. type: HistoryEntryType.CUSTOMER_VERIFIED,
  109. data: {
  110. strategy: 'test_strategy',
  111. },
  112. },
  113. ]);
  114. });
  115. it('user authenticationMethod populated', async () => {
  116. const { customer } = await adminClient.query<
  117. GetCustomerUserAuth.Query,
  118. GetCustomerUserAuth.Variables
  119. >(GET_CUSTOMER_USER_AUTH, {
  120. id: newCustomerId,
  121. });
  122. expect(customer?.user?.authenticationMethods.length).toBe(1);
  123. expect(customer?.user?.authenticationMethods[0].strategy).toBe('test_strategy');
  124. });
  125. it('creates authenticated session', async () => {
  126. const { me } = await shopClient.query<Me.Query>(ME);
  127. expect(me?.identifier).toBe(userData.email);
  128. });
  129. it('log out', async () => {
  130. await shopClient.asAnonymousUser();
  131. });
  132. it('logging in again re-uses created User & Customer', async () => {
  133. const { authenticate } = await shopClient.query<Authenticate.Mutation>(AUTHENTICATE, {
  134. input: {
  135. test_strategy: {
  136. token: VALID_AUTH_TOKEN,
  137. userData,
  138. },
  139. },
  140. });
  141. currentUserGuard.assertSuccess(authenticate);
  142. expect(authenticate.identifier).toEqual(userData.email);
  143. const { customers: after } = await adminClient.query<GetCustomers.Query>(GET_CUSTOMERS);
  144. expect(after.totalItems).toBe(2);
  145. expect(after.items.map(i => i.emailAddress)).toEqual([
  146. 'hayden.zieme12@hotmail.com',
  147. userData.email,
  148. ]);
  149. });
  150. it('registerCustomerAccount with external email', async () => {
  151. const successErrorGuard: ErrorResultGuard<{ success: boolean }> = createErrorResultGuard<{
  152. success: boolean;
  153. }>(input => input.success != null);
  154. const { registerCustomerAccount } = await shopClient.query<Register.Mutation, Register.Variables>(
  155. REGISTER_ACCOUNT,
  156. {
  157. input: {
  158. emailAddress: userData.email,
  159. },
  160. },
  161. );
  162. successErrorGuard.assertSuccess(registerCustomerAccount);
  163. expect(registerCustomerAccount.success).toBe(true);
  164. const { customer } = await adminClient.query<
  165. GetCustomerUserAuth.Query,
  166. GetCustomerUserAuth.Variables
  167. >(GET_CUSTOMER_USER_AUTH, {
  168. id: newCustomerId,
  169. });
  170. expect(customer?.user?.authenticationMethods.length).toBe(2);
  171. expect(customer?.user?.authenticationMethods[1].strategy).toBe('native');
  172. const { customer: customer2 } = await adminClient.query<
  173. GetCustomerHistory.Query,
  174. GetCustomerHistory.Variables
  175. >(GET_CUSTOMER_HISTORY, {
  176. id: newCustomerId,
  177. options: {
  178. skip: 2,
  179. },
  180. });
  181. expect(customer2?.history.items.map(pick(['type', 'data']))).toEqual([
  182. {
  183. type: HistoryEntryType.CUSTOMER_REGISTERED,
  184. data: {
  185. strategy: 'native',
  186. },
  187. },
  188. ]);
  189. });
  190. });
  191. });
  192. const AUTHENTICATE = gql`
  193. mutation Authenticate($input: AuthenticationInput!) {
  194. authenticate(input: $input) {
  195. ...CurrentUser
  196. ... on ErrorResult {
  197. errorCode
  198. message
  199. }
  200. }
  201. }
  202. ${CURRENT_USER_FRAGMENT}
  203. `;
  204. const GET_CUSTOMERS = gql`
  205. query GetCustomers {
  206. customers {
  207. totalItems
  208. items {
  209. id
  210. emailAddress
  211. }
  212. }
  213. }
  214. `;
  215. const GET_CUSTOMER_USER_AUTH = gql`
  216. query GetCustomerUserAuth($id: ID!) {
  217. customer(id: $id) {
  218. id
  219. user {
  220. id
  221. verified
  222. authenticationMethods {
  223. id
  224. strategy
  225. }
  226. }
  227. }
  228. }
  229. `;