@authorizerdev/authorizer-js 0.1.0-beta.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -1,93 +1,132 @@
1
1
  // Note: write gql query in single line to reduce bundle size
2
2
  import nodeFetch from 'node-fetch';
3
3
 
4
- type ConfigType = {
4
+ export type ConfigType = {
5
5
  authorizerURL: string;
6
- redirectURL?: string;
6
+ redirectURL: string;
7
7
  };
8
8
 
9
- type User = {
9
+ export type User = {
10
10
  id: string;
11
11
  email: string;
12
- firstName?: string | null;
13
- lastName?: string | null;
14
- image?: string | null;
15
- signupMethod?: string | null;
16
- emailVerifiedAt?: number | null;
12
+ preferred_username: string;
13
+ email_verified: boolean;
14
+ signup_methods: string;
15
+ given_name?: string | null;
16
+ family_name?: string | null;
17
+ middle_name?: string | null;
18
+ picture?: string | null;
19
+ gender?: string | null;
20
+ birthdate?: string | null;
21
+ phone_number?: string | null;
22
+ phone_number_verified?: boolean | null;
23
+ roles?: string[];
24
+ created_at: number;
25
+ updated_at: number;
17
26
  };
18
27
 
19
- type AuthToken = {
28
+ export type AuthToken = {
20
29
  message?: string;
21
- accessToken: string;
22
- accessTokenExpiresAt: number;
30
+ access_token: string;
31
+ expires_at: number;
23
32
  user?: User;
24
33
  };
25
34
 
26
- type Response = {
35
+ export type Response = {
27
36
  message: string;
28
37
  };
29
38
 
30
- type Headers = Record<string, string>;
39
+ export type Headers = Record<string, string>;
31
40
 
32
- type LoginInput = { email: string; password: string };
41
+ export type LoginInput = { email: string; password: string; roles?: string[] };
33
42
 
34
- type SignupInput = {
43
+ export type SignupInput = {
35
44
  email: string;
36
45
  password: string;
37
- confirmPassword: string;
38
- firstName?: string;
39
- lastName?: string;
46
+ confirm_password: string;
47
+ given_name?: string;
48
+ family_name?: string;
49
+ middle_name?: string;
50
+ picture?: string;
51
+ gender?: string;
52
+ birthdate?: string;
53
+ phone_number?: string;
54
+ roles?: string[];
40
55
  };
41
56
 
42
- type VerifyEmailInput = { token: string };
57
+ export type MagicLinkLoginInput = {
58
+ email: string;
59
+ roles?: string[];
60
+ };
43
61
 
44
- type GraphqlQueryInput = {
62
+ export type VerifyEmailInput = { token: string };
63
+
64
+ export type GraphqlQueryInput = {
45
65
  query: string;
46
66
  variables?: Record<string, any>;
47
67
  headers?: Headers;
48
68
  };
49
69
 
50
- type MetaData = {
70
+ export type MetaData = {
51
71
  version: string;
52
- isGoogleLoginEnabled: boolean;
53
- isFacebookLoginEnabled: boolean;
54
- isTwitterLoginEnabled: boolean;
55
- isGithubLoginEnabled: boolean;
56
- isEmailVerificationEnabled: boolean;
57
- isBasicAuthenticationEnabled: boolean;
72
+ is_google_login_enabled: boolean;
73
+ is_facebook_login_enabled: boolean;
74
+ is_github_login_enabled: boolean;
75
+ is_email_verification_enabled: boolean;
76
+ is_basic_authentication_enabled: boolean;
77
+ is_magic_link_login_enabled: boolean;
58
78
  };
59
79
 
60
- type UpdateProfileInput = {
61
- oldPassword?: string;
62
- newPassword?: string;
63
- confirmNewPassword?: string;
64
- firstName?: string;
65
- lastName?: string;
66
- image?: string;
80
+ export type UpdateProfileInput = {
81
+ old_password?: string;
82
+ new_password?: string;
83
+ confirm_new_password?: string;
67
84
  email?: string;
85
+ given_name?: string;
86
+ family_name?: string;
87
+ middle_name?: string;
88
+ nickname?: string;
89
+ gender?: string;
90
+ birthdate?: string;
91
+ phone_number?: string;
92
+ picture?: string;
68
93
  };
69
94
 
70
- type ForgotPasswordInput = {
95
+ export type ForgotPasswordInput = {
71
96
  email: string;
72
97
  };
73
98
 
74
- type ResetPasswordInput = {
99
+ export type ResetPasswordInput = {
75
100
  token: string;
76
101
  password: string;
77
- confirmPassword: string;
102
+ confirm_password: string;
78
103
  };
79
104
 
80
- enum OAuthProviders {
105
+ export enum OAuthProviders {
81
106
  Github = 'github',
82
107
  Google = 'google',
108
+ Facebook = 'facebook',
83
109
  }
84
110
 
85
111
  const hasWindow = (): boolean => typeof window !== 'undefined';
86
112
 
87
113
  // re-usable gql response fragment
88
- const userTokenFragment = `message accessToken accessTokenExpiresAt user { id email firstName lastName image }`;
114
+ const userFragment = `id email email_verified given_name family_name middle_name nickname preferred_username picture signup_methods gender birthdate phone_number phone_number_verified roles created_at updated_at `;
115
+ const authTokenFragment = `message access_token expires_at user { ${userFragment} }`;
116
+
117
+ const trimURL = (url: string): string => {
118
+ let trimmedData = url.trim();
119
+ const lastChar = trimmedData[trimmedData.length - 1];
120
+ if (lastChar === '/') {
121
+ trimmedData = trimmedData.slice(0, -1);
122
+ } else {
123
+ trimmedData = trimmedData;
124
+ }
89
125
 
90
- export default class Authorizer {
126
+ return trimmedData;
127
+ };
128
+
129
+ export class Authorizer {
91
130
  // class variable
92
131
  config: ConfigType;
93
132
 
@@ -97,20 +136,16 @@ export default class Authorizer {
97
136
  throw new Error(`Configuration is required`);
98
137
  }
99
138
  this.config = config;
100
- if (!config.authorizerURL.trim()) {
139
+ if (!config.authorizerURL && !config.authorizerURL.trim()) {
101
140
  throw new Error(`Invalid authorizerURL`);
102
141
  }
103
142
  if (config.authorizerURL) {
104
- const trimmedData = config.authorizerURL.trim();
105
- const lastChar = trimmedData[trimmedData.length - 1];
106
- if (lastChar === '/') {
107
- this.config.authorizerURL = trimmedData.slice(0, -1);
108
- } else {
109
- this.config.authorizerURL = trimmedData;
110
- }
143
+ this.config.authorizerURL = trimURL(config.authorizerURL);
111
144
  }
112
- if (!config.redirectURL) {
145
+ if (!config.redirectURL && !config.redirectURL.trim()) {
113
146
  throw new Error(`Invalid redirectURL`);
147
+ } else {
148
+ this.config.redirectURL = trimURL(config.redirectURL);
114
149
  }
115
150
  }
116
151
 
@@ -146,7 +181,7 @@ export default class Authorizer {
146
181
  getMetaData = async (): Promise<MetaData | void> => {
147
182
  try {
148
183
  const res = await this.graphqlQuery({
149
- query: `query { meta { version isGoogleLoginEnabled isGithubLoginEnabled isBasicAuthenticationEnabled isEmailVerificationEnabled isFacebookLoginEnabled isTwitterLoginEnabled } }`,
184
+ query: `query { meta { version is_google_login_enabled is_facebook_login_enabled is_github_login_enabled is_email_verification_enabled is_basic_authentication_enabled is_magic_link_login_enabled } }`,
150
185
  });
151
186
 
152
187
  return res.meta;
@@ -156,13 +191,34 @@ export default class Authorizer {
156
191
  };
157
192
 
158
193
  // this is used to verify / get session using cookie by default. If using nodejs pass authorization header
159
- getSession = async (headers?: Headers): Promise<AuthToken> => {
194
+ getSession = async (
195
+ headers?: Headers,
196
+ roles?: string[],
197
+ ): Promise<AuthToken> => {
160
198
  try {
161
199
  const res = await this.graphqlQuery({
162
- query: `query {token { ${userTokenFragment} } }`,
200
+ query: `query getSession($roles: [String!]){session(roles: $roles) { ${authTokenFragment} } }`,
163
201
  headers,
202
+ variables: {
203
+ roles,
204
+ },
164
205
  });
165
- return res.token;
206
+ return res.session;
207
+ } catch (err) {
208
+ throw err;
209
+ }
210
+ };
211
+
212
+ magicLinkLogin = async (data: MagicLinkLoginInput): Promise<Response> => {
213
+ try {
214
+ const res = await this.graphqlQuery({
215
+ query: `
216
+ mutation magicLinkLogin($data: MagicLinkLoginInput!) { magic_link_login(params: $data) { message }}
217
+ `,
218
+ variables: { data },
219
+ });
220
+
221
+ return res.magic_link_login;
166
222
  } catch (err) {
167
223
  throw err;
168
224
  }
@@ -172,13 +228,14 @@ export default class Authorizer {
172
228
  try {
173
229
  const res = await this.graphqlQuery({
174
230
  query: `
175
- mutation signup($data: SignUpInput!) { signup(params: $data) { ${userTokenFragment}}}`,
231
+ mutation signup($data: SignUpInput!) { signup(params: $data) { ${authTokenFragment}}}
232
+ `,
176
233
  variables: { data },
177
234
  });
178
235
 
179
236
  return res.signup;
180
237
  } catch (err) {
181
- console.error(err);
238
+ throw err;
182
239
  }
183
240
  };
184
241
 
@@ -186,13 +243,14 @@ export default class Authorizer {
186
243
  try {
187
244
  const res = await this.graphqlQuery({
188
245
  query: `
189
- mutation verifyEmail($data: VerifyEmailInput!) { verifyEmail(params: $data) { ${userTokenFragment}}}`,
246
+ mutation verifyEmail($data: VerifyEmailInput!) { verify_email(params: $data) { ${authTokenFragment}}}
247
+ `,
190
248
  variables: { data },
191
249
  });
192
250
 
193
- return res.verifyEmail;
251
+ return res.verify_email;
194
252
  } catch (err) {
195
- console.error(err);
253
+ throw err;
196
254
  }
197
255
  };
198
256
 
@@ -200,20 +258,21 @@ export default class Authorizer {
200
258
  try {
201
259
  const res = await this.graphqlQuery({
202
260
  query: `
203
- mutation login($data: LoginInput!) { login(params: $data) { ${userTokenFragment}}}`,
261
+ mutation login($data: LoginInput!) { login(params: $data) { ${authTokenFragment}}}
262
+ `,
204
263
  variables: { data },
205
264
  });
206
265
 
207
266
  return res.login;
208
267
  } catch (err) {
209
- console.error(err);
268
+ throw err;
210
269
  }
211
270
  };
212
271
 
213
272
  getProfile = async (headers?: Headers): Promise<User | void> => {
214
273
  try {
215
274
  const profileRes = await this.graphqlQuery({
216
- query: `query { profile { id email image firstName lastName emailVerifiedAt signupMethod } }`,
275
+ query: `query { profile { ${userFragment} } }`,
217
276
  headers,
218
277
  });
219
278
 
@@ -229,14 +288,14 @@ export default class Authorizer {
229
288
  ): Promise<Response | void> => {
230
289
  try {
231
290
  const updateProfileRes = await this.graphqlQuery({
232
- query: `mutation updateProfile($data: UpdateProfileInput!) { updateProfile(params: $data) { message } }`,
291
+ query: `mutation updateProfile($data: UpdateProfileInput!) { update_profile(params: $data) { message } }`,
233
292
  headers,
234
293
  variables: {
235
294
  data,
236
295
  },
237
296
  });
238
297
 
239
- return updateProfileRes.updateProfile;
298
+ return updateProfileRes.update_profile;
240
299
  } catch (error) {
241
300
  throw error;
242
301
  }
@@ -247,13 +306,13 @@ export default class Authorizer {
247
306
  ): Promise<Response | void> => {
248
307
  try {
249
308
  const forgotPasswordRes = await this.graphqlQuery({
250
- query: `mutation forgotPassword($data: ForgotPasswordInput!) { forgotPassword(params: $data) { message } }`,
309
+ query: `mutation forgotPassword($data: ForgotPasswordInput!) { forgot_password(params: $data) { message } }`,
251
310
  variables: {
252
311
  data,
253
312
  },
254
313
  });
255
314
 
256
- return forgotPasswordRes.forgotPassword;
315
+ return forgotPasswordRes.forgot_password;
257
316
  } catch (error) {
258
317
  throw error;
259
318
  }
@@ -264,24 +323,24 @@ export default class Authorizer {
264
323
  ): Promise<Response | void> => {
265
324
  try {
266
325
  const resetPasswordRes = await this.graphqlQuery({
267
- query: `mutation resetPassword($data: ResetPasswordInput!) { resetPassword(params: $data) { message } }`,
326
+ query: `mutation resetPassword($data: ResetPasswordInput!) { reset_password(params: $data) { message } }`,
268
327
  variables: {
269
328
  data,
270
329
  },
271
330
  });
272
- return resetPasswordRes.resetPassword;
331
+ return resetPasswordRes.reset_password;
273
332
  } catch (error) {
274
333
  throw error;
275
334
  }
276
335
  };
277
336
 
278
- fingertipLogin = async (): Promise<AuthToken | void> => {
337
+ browserLogin = async (): Promise<AuthToken | void> => {
279
338
  try {
280
339
  const token = await this.getSession();
281
340
  return token;
282
341
  } catch (err) {
283
342
  if (!hasWindow()) {
284
- throw new Error(`fingertipLogin is only supported for browsers`);
343
+ throw new Error(`browserLogin is only supported for browsers`);
285
344
  }
286
345
  window.location.href = `${this.config.authorizerURL}/app?state=${btoa(
287
346
  JSON.stringify(this.config),
@@ -289,7 +348,10 @@ export default class Authorizer {
289
348
  }
290
349
  };
291
350
 
292
- oauthLogin = async (oauthProvider: string): Promise<void> => {
351
+ oauthLogin = async (
352
+ oauthProvider: string,
353
+ roles?: string[],
354
+ ): Promise<void> => {
293
355
  // @ts-ignore
294
356
  if (!Object.values(OAuthProviders).includes(oauthProvider)) {
295
357
  throw new Error(
@@ -301,7 +363,11 @@ export default class Authorizer {
301
363
  if (!hasWindow()) {
302
364
  throw new Error(`oauthLogin is only supported for browsers`);
303
365
  }
304
- window.location.href = `${this.config.authorizerURL}/oauth_login/${oauthProvider}`;
366
+ window.location.href = `${
367
+ this.config.authorizerURL
368
+ }/oauth_login/${oauthProvider}?redirectURL=${
369
+ this.config.redirectURL || window.location.origin
370
+ }${roles && roles.length ? `&roles=${roles.join(',')}` : ``}`;
305
371
  };
306
372
 
307
373
  logout = async (headers?: Headers): Promise<Response | void> => {
@@ -312,6 +378,7 @@ export default class Authorizer {
312
378
  });
313
379
  return res.logout;
314
380
  } catch (err) {
381
+ console.log(`logout err:`, err);
315
382
  console.error(err);
316
383
  }
317
384
  };