@usync/oauth2 0.0.5 → 0.1.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/dist/index.js CHANGED
@@ -1,43 +1,32 @@
1
- import { nanoid as y } from "nanoid";
2
- const R = 1, h = 2, d = 3;
3
- class r extends Error {
4
- constructor(e, n) {
5
- super(n || `OAuth2Error: code=${e}`), this.code = e;
1
+ import { nanoid as U } from "nanoid";
2
+ const R = 1, a = 2, d = 3;
3
+ class i extends Error {
4
+ constructor(e, o) {
5
+ super(o || `OAuth2Error: code=${e}`), this.code = e;
6
6
  }
7
7
  }
8
- var U = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", A;
9
- function S() {
10
- return A ||= U.slice(0, -2) + "-_", A;
11
- }
12
- function b(i, e, n) {
13
- let s = "", o = 0;
14
- for (; o < i.length; ) {
15
- let t = i[o++], c = i[o++], a = i[o++];
16
- if (s += e[t >> 2], s += e[(t & 3) << 4 | (c || 0) >> 4], c == null || (s += e[(c & 15) << 2 | (a || 0) >> 6]), a == null)
17
- break;
18
- s += e[a & 63];
19
- }
20
- return s;
21
- }
22
- function O(i) {
23
- return b(i, S(), !1);
8
+ function O(r) {
9
+ let e = "";
10
+ for (const o of r)
11
+ e += String.fromCharCode(o);
12
+ return btoa(e).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
24
13
  }
25
14
  function _() {
26
- return y(8);
15
+ return U(8);
27
16
  }
28
17
  function k() {
29
- return y(64);
18
+ return U(64);
30
19
  }
31
- async function u(i) {
32
- const e = "S256", n = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(i));
20
+ async function u(r) {
21
+ const e = "S256", o = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(r));
33
22
  return {
34
- codeChallenge: O(new Uint8Array(n)),
23
+ codeChallenge: O(new Uint8Array(o)),
35
24
  codeChallengeMethod: e
36
25
  };
37
26
  }
38
27
  class w {
39
- constructor(e, n) {
40
- this.options = e, this._accessToken = null, this._refreshToken = null, n && (this.setRefreshToken(n.refreshToken), this.setAccessToken(n.accessToken));
28
+ constructor(e, o) {
29
+ this.options = e, this._accessToken = null, this._refreshToken = null, o && (this.setRefreshToken(o.refreshToken), this.setAccessToken(o.accessToken));
41
30
  }
42
31
  _getValidToken(e) {
43
32
  return e && (!e.expiresAt || Date.now() < e.expiresAt) ? e.token : void 0;
@@ -49,14 +38,14 @@ class w {
49
38
  this.setRefreshToken(e), this.options.onSetRefreshToken?.(e);
50
39
  }
51
40
  getAccessToken() {
52
- if (!this._accessToken) throw new r(d);
41
+ if (!this._accessToken) throw new i(d);
53
42
  const e = this._getValidToken(this._accessToken);
54
- if (!e) throw new r(R);
43
+ if (!e) throw new i(R);
55
44
  return e;
56
45
  }
57
46
  getRefreshToken() {
58
47
  const e = this._getValidToken(this._refreshToken);
59
- if (!e) throw new r(d, "Invalid refresh token");
48
+ if (!e) throw new i(d, "Invalid refresh token");
60
49
  return e;
61
50
  }
62
51
  setAccessToken(e) {
@@ -66,51 +55,51 @@ class w {
66
55
  this._refreshToken = e ?? null;
67
56
  }
68
57
  }
69
- const g = class g extends w {
58
+ const b = "https://www.dropbox.com/oauth2/authorize", A = "https://api.dropbox.com/oauth2/token", T = class T extends w {
70
59
  async buildAuthUrl() {
71
60
  this.session = {
72
61
  state: _(),
73
62
  codeVerifier: k()
74
63
  };
75
- const { codeChallenge: e, codeChallengeMethod: n } = await u(
64
+ const { codeChallenge: e, codeChallengeMethod: o } = await u(
76
65
  this.session.codeVerifier
77
- ), s = new URL("https://www.dropbox.com/oauth2/authorize");
66
+ ), s = new URL(b);
78
67
  return Object.entries({
79
68
  client_id: this.options.clientId,
80
69
  code_challenge: e,
81
- code_challenge_method: n,
70
+ code_challenge_method: o,
82
71
  redirect_uri: this.options.redirectUrl,
83
72
  response_type: "code",
84
73
  token_access_type: "offline",
85
74
  scope: this.options.scope,
86
75
  state: this.session.state
87
- }).forEach(([o, t]) => {
88
- t && s.searchParams.set(o, t);
76
+ }).forEach(([n, t]) => {
77
+ t && s.searchParams.set(n, t);
89
78
  }), s.href;
90
79
  }
91
80
  async finishAuth(e) {
92
81
  if (!this.session || this.session.state !== e.searchParams.get("state"))
93
- throw new r(h, "state doesn't match");
94
- const n = e.searchParams.get("code");
95
- if (!n) throw new r(h, "Invalid code");
82
+ throw new i(a, "state doesn't match");
83
+ const o = e.searchParams.get("code");
84
+ if (!o) throw new i(a, "Invalid code");
96
85
  const s = new URLSearchParams();
97
86
  Object.entries({
98
87
  client_id: this.options.clientId,
99
88
  client_secret: this.options.clientSecret,
100
- code: n,
89
+ code: o,
101
90
  code_verifier: this.session.codeVerifier,
102
91
  grant_type: "authorization_code",
103
92
  redirect_uri: this.options.redirectUrl
104
- }).forEach(([c, a]) => {
105
- s.append(c, a);
93
+ }).forEach(([c, h]) => {
94
+ h != null && s.append(c, h);
106
95
  });
107
- const o = await fetch("https://api.dropbox.com/oauth2/token", {
96
+ const n = await fetch(A, {
108
97
  method: "POST",
109
98
  body: s
110
- }), t = await o.json();
111
- if (!o.ok) throw { status: o.status, data: t };
99
+ }), t = await n.json();
100
+ if (!n.ok) throw { status: n.status, data: t };
112
101
  if (!t.refresh_token)
113
- throw new r(h, "Failed to get refresh_token");
102
+ throw new i(a, "Failed to get refresh_token");
114
103
  return this._updateRefreshToken({
115
104
  token: t.refresh_token,
116
105
  scope: t.scope
@@ -120,77 +109,77 @@ const g = class g extends w {
120
109
  }), t.access_token;
121
110
  }
122
111
  async refreshToken() {
123
- const e = new URLSearchParams(), n = this.getRefreshToken();
112
+ const e = new URLSearchParams(), o = this.getRefreshToken();
124
113
  Object.entries({
125
114
  client_id: this.options.clientId,
126
115
  client_secret: this.options.clientSecret,
127
116
  grant_type: "refresh_token",
128
- refresh_token: n
117
+ refresh_token: o
129
118
  }).forEach(([t, c]) => {
130
- e.append(t, c);
119
+ c != null && e.append(t, c);
131
120
  });
132
- const s = await fetch("https://api.dropbox.com/oauth2/token", {
121
+ const s = await fetch(A, {
133
122
  method: "POST",
134
123
  body: e
135
- }), o = await s.json();
136
- if (!s.ok) throw { status: s.status, data: o };
124
+ }), n = await s.json();
125
+ if (!s.ok) throw { status: s.status, data: n };
137
126
  return this._updateAccessToken({
138
- token: o.access_token,
139
- expiresAt: Date.now() + o.expires_in * 1e3
140
- }), o.access_token;
127
+ token: n.access_token,
128
+ expiresAt: Date.now() + n.expires_in * 1e3
129
+ }), n.access_token;
141
130
  }
142
131
  };
143
- g.Scopes = {
132
+ T.Scopes = {
144
133
  account: "account_info.read"
145
134
  };
146
- let p = g;
147
- const T = class T extends w {
135
+ let p = T;
136
+ const S = "https://accounts.google.com/o/oauth2/v2/auth", y = "https://oauth2.googleapis.com/token", g = class g extends w {
148
137
  async buildAuthUrl() {
149
138
  this.session = {
150
139
  state: _(),
151
140
  codeVerifier: k()
152
141
  };
153
- const { codeChallenge: e, codeChallengeMethod: n } = await u(
142
+ const { codeChallenge: e, codeChallengeMethod: o } = await u(
154
143
  this.session.codeVerifier
155
- ), s = new URL("https://accounts.google.com/o/oauth2/v2/auth");
144
+ ), s = new URL(S);
156
145
  return Object.entries({
157
146
  access_type: "offline",
158
147
  client_id: this.options.clientId,
159
148
  code_challenge: e,
160
- code_challenge_method: n,
149
+ code_challenge_method: o,
161
150
  include_granted_scopes: "true",
162
151
  prompt: "consent",
163
152
  redirect_uri: this.options.redirectUrl,
164
153
  response_type: "code",
165
154
  scope: this.options.scope,
166
155
  state: this.session.state
167
- }).forEach(([o, t]) => {
168
- t && s.searchParams.set(o, t);
156
+ }).forEach(([n, t]) => {
157
+ t && s.searchParams.set(n, t);
169
158
  }), s.href;
170
159
  }
171
160
  async finishAuth(e) {
172
161
  if (!this.session || this.session.state !== e.searchParams.get("state"))
173
- throw new r(h, "state doesn't match");
174
- const n = e.searchParams.get("code");
175
- if (!n) throw new r(h, "Invalid code");
162
+ throw new i(a, "state doesn't match");
163
+ const o = e.searchParams.get("code");
164
+ if (!o) throw new i(a, "Invalid code");
176
165
  const s = new URLSearchParams();
177
166
  Object.entries({
178
167
  client_id: this.options.clientId,
179
168
  client_secret: this.options.clientSecret,
180
- code: n,
169
+ code: o,
181
170
  code_verifier: this.session.codeVerifier,
182
171
  grant_type: "authorization_code",
183
172
  redirect_uri: this.options.redirectUrl
184
- }).forEach(([c, a]) => {
185
- s.append(c, a);
173
+ }).forEach(([c, h]) => {
174
+ h != null && s.append(c, h);
186
175
  });
187
- const o = await fetch("https://oauth2.googleapis.com/token", {
176
+ const n = await fetch(y, {
188
177
  method: "POST",
189
178
  body: s
190
- }), t = await o.json();
191
- if (!o.ok) throw { status: o.status, data: t };
179
+ }), t = await n.json();
180
+ if (!n.ok) throw { status: n.status, data: t };
192
181
  if (!t.refresh_token)
193
- throw new r(h, "Failed to get refresh_token");
182
+ throw new i(a, "Failed to get refresh_token");
194
183
  return this._updateRefreshToken({
195
184
  token: t.refresh_token,
196
185
  scope: t.scope
@@ -200,79 +189,82 @@ const T = class T extends w {
200
189
  }), t.access_token;
201
190
  }
202
191
  async refreshToken() {
203
- const e = new URLSearchParams(), n = this.getRefreshToken();
192
+ const e = new URLSearchParams(), o = this.getRefreshToken();
204
193
  Object.entries({
205
194
  client_id: this.options.clientId,
206
195
  client_secret: this.options.clientSecret,
207
196
  grant_type: "refresh_token",
208
- refresh_token: n,
197
+ refresh_token: o,
209
198
  scope: this.options.scope
210
199
  }).forEach(([t, c]) => {
211
200
  c != null && e.append(t, c);
212
201
  });
213
- const s = await fetch("https://oauth2.googleapis.com/token", {
202
+ const s = await fetch(y, {
214
203
  method: "POST",
215
204
  body: e
216
- }), o = await s.json();
217
- if (!s.ok) throw { status: s.status, data: o };
205
+ }), n = await s.json();
206
+ if (!s.ok) throw { status: s.status, data: n };
218
207
  return this._updateAccessToken({
219
- token: o.access_token,
220
- expiresAt: Date.now() + o.expires_in * 1e3
221
- }), o.access_token;
208
+ token: n.access_token,
209
+ expiresAt: Date.now() + n.expires_in * 1e3
210
+ }), n.access_token;
222
211
  }
223
212
  };
224
- T.Scopes = {
213
+ g.Scopes = {
225
214
  account: "https://www.googleapis.com/auth/userinfo.profile",
226
215
  "drive.appdata": "https://www.googleapis.com/auth/drive.appdata",
227
216
  imap: "https://mail.google.com/"
228
217
  };
229
- let f = T;
218
+ let l = g;
230
219
  const m = class m extends w {
220
+ oauth2Url(e) {
221
+ return `https://login.microsoftonline.com/${this.options.provider?.microsoft?.accountType ?? "common"}/oauth2/v2.0/${e}`;
222
+ }
231
223
  async buildAuthUrl() {
232
224
  this.session = {
233
225
  state: _(),
234
226
  codeVerifier: k()
235
227
  };
236
- const { codeChallenge: e, codeChallengeMethod: n } = await u(
228
+ const { codeChallenge: e, codeChallengeMethod: o } = await u(
237
229
  this.session.codeVerifier
238
- ), s = new URL("https://login.microsoftonline.com/common/oauth2/v2.0/authorize");
230
+ ), s = new URL(this.oauth2Url("authorize"));
239
231
  return Object.entries({
240
232
  client_id: this.options.clientId,
241
233
  code_challenge: e,
242
- code_challenge_method: n,
234
+ code_challenge_method: o,
243
235
  redirect_uri: this.options.redirectUrl,
244
236
  response_mode: "query",
245
237
  response_type: "code",
246
238
  scope: this.options.scope,
247
239
  state: this.session.state
248
- }).forEach(([o, t]) => {
249
- t && s.searchParams.set(o, t);
240
+ }).forEach(([n, t]) => {
241
+ t && s.searchParams.set(n, t);
250
242
  }), s.href;
251
243
  }
252
244
  async finishAuth(e) {
253
245
  if (!this.session || this.session.state !== e.searchParams.get("state"))
254
- throw new r(h, "state doesn't match");
255
- const n = e.searchParams.get("code");
256
- if (!n) throw new r(h, "Invalid code");
246
+ throw new i(a, "state doesn't match");
247
+ const o = e.searchParams.get("code");
248
+ if (!o) throw new i(a, "Invalid code");
257
249
  const s = new URLSearchParams();
258
250
  Object.entries({
259
251
  client_id: this.options.clientId,
260
252
  client_secret: this.options.clientSecret,
261
- code: n,
253
+ code: o,
262
254
  code_verifier: this.session.codeVerifier,
263
255
  grant_type: "authorization_code",
264
256
  redirect_uri: this.options.redirectUrl,
265
257
  scope: this.options.scope
266
- }).forEach(([c, a]) => {
267
- a && s.append(c, a);
258
+ }).forEach(([c, h]) => {
259
+ h != null && s.append(c, h);
268
260
  });
269
- const o = await fetch("https://login.microsoftonline.com/common/oauth2/v2.0/token", {
261
+ const n = await fetch(this.oauth2Url("token"), {
270
262
  method: "POST",
271
263
  body: s
272
- }), t = await o.json();
273
- if (!o.ok) throw { status: o.status, data: t };
264
+ }), t = await n.json();
265
+ if (!n.ok) throw { status: n.status, data: t };
274
266
  if (!t.refresh_token)
275
- throw new r(h, "Failed to get refresh_token");
267
+ throw new i(a, "Failed to get refresh_token");
276
268
  return this._updateRefreshToken({
277
269
  token: t.refresh_token,
278
270
  scope: t.scope
@@ -282,25 +274,25 @@ const m = class m extends w {
282
274
  }), t.access_token;
283
275
  }
284
276
  async refreshToken() {
285
- const e = new URLSearchParams(), n = this.getRefreshToken();
277
+ const e = new URLSearchParams(), o = this.getRefreshToken();
286
278
  Object.entries({
287
279
  client_id: this.options.clientId,
288
280
  client_secret: this.options.clientSecret,
289
281
  grant_type: "refresh_token",
290
- refresh_token: n,
282
+ refresh_token: o,
291
283
  scope: this.options.scope
292
284
  }).forEach(([t, c]) => {
293
- c && e.append(t, c);
285
+ c != null && e.append(t, c);
294
286
  });
295
- const s = await fetch("https://login.microsoftonline.com/common/oauth2/v2.0/token", {
287
+ const s = await fetch(this.oauth2Url("token"), {
296
288
  method: "POST",
297
289
  body: e
298
- }), o = await s.json();
299
- if (!s.ok) throw { status: s.status, data: o };
290
+ }), n = await s.json();
291
+ if (!s.ok) throw { status: s.status, data: n };
300
292
  return this._updateAccessToken({
301
- token: o.access_token,
302
- expiresAt: Date.now() + o.expires_in * 1e3
303
- }), o.access_token;
293
+ token: n.access_token,
294
+ expiresAt: Date.now() + n.expires_in * 1e3
295
+ }), n.access_token;
304
296
  }
305
297
  };
306
298
  m.Scopes = {
@@ -308,49 +300,49 @@ m.Scopes = {
308
300
  imap: "offline_access https://outlook.office.com/IMAP.AccessAsUser.All",
309
301
  onedrive: "openid profile Files.ReadWrite.AppFolder offline_access"
310
302
  };
311
- let l = m;
312
- const x = {
303
+ let f = m;
304
+ const E = {
313
305
  dropbox: p,
314
- google: f,
315
- microsoft: l
306
+ google: l,
307
+ microsoft: f
316
308
  };
317
- function E(i, e) {
318
- return new x[e.provider](i);
309
+ function x(r, e) {
310
+ return new E[e.provider](r);
319
311
  }
320
- async function j(i, e) {
321
- let n;
312
+ async function I(r, e) {
313
+ let o;
322
314
  try {
323
- n = i.getAccessToken();
315
+ o = r.getAccessToken();
324
316
  } catch (s) {
325
- if (!(s instanceof r))
317
+ if (!(s instanceof i))
326
318
  throw s;
327
319
  switch (s.code) {
328
320
  case d: {
329
321
  if (!e) throw s;
330
- const o = await i.buildAuthUrl(), t = await e(o);
331
- n = await i.finishAuth(new URL(t));
322
+ const n = await r.buildAuthUrl(), t = await e(n);
323
+ o = await r.finishAuth(new URL(t));
332
324
  break;
333
325
  }
334
326
  case R: {
335
- n = await i.refreshToken();
327
+ o = await r.refreshToken();
336
328
  break;
337
329
  }
338
330
  default:
339
331
  throw s;
340
332
  }
341
333
  }
342
- return n;
334
+ return o;
343
335
  }
344
336
  export {
345
337
  p as DropboxAuthorizer,
346
- f as GoogleAuthorizer,
347
- l as MicrosoftAuthorizer,
348
- h as OAUTH2_AUTH_ERROR,
338
+ l as GoogleAuthorizer,
339
+ f as MicrosoftAuthorizer,
340
+ a as OAUTH2_AUTH_ERROR,
349
341
  R as OAUTH2_NEED_REFRESH,
350
342
  d as OAUTH2_UNAUTHORIZED,
351
343
  w as OAuth2Authorizer,
352
- x as OAuth2Authorizers,
353
- r as OAuth2Error,
354
- j as ensureAccessToken,
355
- E as getAuthorizer
344
+ E as OAuth2Authorizers,
345
+ i as OAuth2Error,
346
+ I as ensureAccessToken,
347
+ x as getAuthorizer
356
348
  };
@@ -9,6 +9,7 @@ export declare class MicrosoftAuthorizer extends OAuth2Authorizer {
9
9
  imap: string;
10
10
  onedrive: string;
11
11
  };
12
+ private oauth2Url;
12
13
  buildAuthUrl(): Promise<string>;
13
14
  finishAuth(url: URL): Promise<string>;
14
15
  refreshToken(): Promise<string>;
package/dist/types.d.ts CHANGED
@@ -6,9 +6,21 @@ export interface TokenData {
6
6
  }
7
7
  export interface IOAuth2Options {
8
8
  clientId: string;
9
- clientSecret: string;
9
+ /** clientSecret may be absent for client-side apps. */
10
+ clientSecret?: string;
10
11
  redirectUrl: string;
11
12
  scope?: string;
13
+ provider?: {
14
+ microsoft?: {
15
+ /**
16
+ * Must match the account type of the application registered in https://portal.azure.com/.
17
+ * `common` for all accounts, `consumers` for personal accounts only.
18
+ *
19
+ * Default as `common`.
20
+ */
21
+ accountType?: "common" | "consumers";
22
+ };
23
+ };
12
24
  onSetAccessToken?: (value: TokenData | null) => void;
13
25
  onSetRefreshToken?: (value: TokenData | null) => void;
14
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usync/oauth2",
3
- "version": "0.0.5",
3
+ "version": "0.1.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],