@usync/oauth2 0.1.0 → 0.1.2
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,14 +1,14 @@
|
|
|
1
1
|
import { nanoid as U } from "nanoid";
|
|
2
2
|
const R = 1, a = 2, d = 3;
|
|
3
3
|
class i extends Error {
|
|
4
|
-
constructor(e,
|
|
5
|
-
super(
|
|
4
|
+
constructor(e, s) {
|
|
5
|
+
super(s || `OAuth2Error: code=${e}`), this.code = e;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
function O(r) {
|
|
9
9
|
let e = "";
|
|
10
|
-
for (const
|
|
11
|
-
e += String.fromCharCode(
|
|
10
|
+
for (const s of r)
|
|
11
|
+
e += String.fromCharCode(s);
|
|
12
12
|
return btoa(e).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
13
13
|
}
|
|
14
14
|
function _() {
|
|
@@ -18,15 +18,15 @@ function k() {
|
|
|
18
18
|
return U(64);
|
|
19
19
|
}
|
|
20
20
|
async function u(r) {
|
|
21
|
-
const e = "S256",
|
|
21
|
+
const e = "S256", s = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(r));
|
|
22
22
|
return {
|
|
23
|
-
codeChallenge: O(new Uint8Array(
|
|
23
|
+
codeChallenge: O(new Uint8Array(s)),
|
|
24
24
|
codeChallengeMethod: e
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
class w {
|
|
28
|
-
constructor(e,
|
|
29
|
-
this.options = e, this._accessToken = null, this._refreshToken = null,
|
|
28
|
+
constructor(e, s) {
|
|
29
|
+
this.options = e, this._accessToken = null, this._refreshToken = null, s && (this.setRefreshToken(s.refreshToken), this.setAccessToken(s.accessToken), this.session = s.session);
|
|
30
30
|
}
|
|
31
31
|
_getValidToken(e) {
|
|
32
32
|
return e && (!e.expiresAt || Date.now() < e.expiresAt) ? e.token : void 0;
|
|
@@ -61,41 +61,41 @@ const b = "https://www.dropbox.com/oauth2/authorize", A = "https://api.dropbox.c
|
|
|
61
61
|
state: _(),
|
|
62
62
|
codeVerifier: k()
|
|
63
63
|
};
|
|
64
|
-
const { codeChallenge: e, codeChallengeMethod:
|
|
64
|
+
const { codeChallenge: e, codeChallengeMethod: s } = await u(
|
|
65
65
|
this.session.codeVerifier
|
|
66
|
-
),
|
|
66
|
+
), o = new URL(b);
|
|
67
67
|
return Object.entries({
|
|
68
68
|
client_id: this.options.clientId,
|
|
69
69
|
code_challenge: e,
|
|
70
|
-
code_challenge_method:
|
|
70
|
+
code_challenge_method: s,
|
|
71
71
|
redirect_uri: this.options.redirectUrl,
|
|
72
72
|
response_type: "code",
|
|
73
73
|
token_access_type: "offline",
|
|
74
74
|
scope: this.options.scope,
|
|
75
75
|
state: this.session.state
|
|
76
76
|
}).forEach(([n, t]) => {
|
|
77
|
-
t &&
|
|
78
|
-
}),
|
|
77
|
+
t && o.searchParams.set(n, t);
|
|
78
|
+
}), o.href;
|
|
79
79
|
}
|
|
80
80
|
async finishAuth(e) {
|
|
81
81
|
if (!this.session || this.session.state !== e.searchParams.get("state"))
|
|
82
82
|
throw new i(a, "state doesn't match");
|
|
83
|
-
const
|
|
84
|
-
if (!
|
|
85
|
-
const
|
|
83
|
+
const s = e.searchParams.get("code");
|
|
84
|
+
if (!s) throw new i(a, "Invalid code");
|
|
85
|
+
const o = new URLSearchParams();
|
|
86
86
|
Object.entries({
|
|
87
87
|
client_id: this.options.clientId,
|
|
88
88
|
client_secret: this.options.clientSecret,
|
|
89
|
-
code:
|
|
89
|
+
code: s,
|
|
90
90
|
code_verifier: this.session.codeVerifier,
|
|
91
91
|
grant_type: "authorization_code",
|
|
92
92
|
redirect_uri: this.options.redirectUrl
|
|
93
93
|
}).forEach(([c, h]) => {
|
|
94
|
-
h != null &&
|
|
94
|
+
h != null && o.append(c, h);
|
|
95
95
|
});
|
|
96
96
|
const n = await fetch(A, {
|
|
97
97
|
method: "POST",
|
|
98
|
-
body:
|
|
98
|
+
body: o
|
|
99
99
|
}), t = await n.json();
|
|
100
100
|
if (!n.ok) throw { status: n.status, data: t };
|
|
101
101
|
if (!t.refresh_token)
|
|
@@ -109,20 +109,20 @@ const b = "https://www.dropbox.com/oauth2/authorize", A = "https://api.dropbox.c
|
|
|
109
109
|
}), t.access_token;
|
|
110
110
|
}
|
|
111
111
|
async refreshToken() {
|
|
112
|
-
const e = new URLSearchParams(),
|
|
112
|
+
const e = new URLSearchParams(), s = this.getRefreshToken();
|
|
113
113
|
Object.entries({
|
|
114
114
|
client_id: this.options.clientId,
|
|
115
115
|
client_secret: this.options.clientSecret,
|
|
116
116
|
grant_type: "refresh_token",
|
|
117
|
-
refresh_token:
|
|
117
|
+
refresh_token: s
|
|
118
118
|
}).forEach(([t, c]) => {
|
|
119
119
|
c != null && e.append(t, c);
|
|
120
120
|
});
|
|
121
|
-
const
|
|
121
|
+
const o = await fetch(A, {
|
|
122
122
|
method: "POST",
|
|
123
123
|
body: e
|
|
124
|
-
}), n = await
|
|
125
|
-
if (!
|
|
124
|
+
}), n = await o.json();
|
|
125
|
+
if (!o.ok) throw { status: o.status, data: n };
|
|
126
126
|
return this._updateAccessToken({
|
|
127
127
|
token: n.access_token,
|
|
128
128
|
expiresAt: Date.now() + n.expires_in * 1e3
|
|
@@ -139,14 +139,14 @@ const S = "https://accounts.google.com/o/oauth2/v2/auth", y = "https://oauth2.go
|
|
|
139
139
|
state: _(),
|
|
140
140
|
codeVerifier: k()
|
|
141
141
|
};
|
|
142
|
-
const { codeChallenge: e, codeChallengeMethod:
|
|
142
|
+
const { codeChallenge: e, codeChallengeMethod: s } = await u(
|
|
143
143
|
this.session.codeVerifier
|
|
144
|
-
),
|
|
144
|
+
), o = new URL(S);
|
|
145
145
|
return Object.entries({
|
|
146
146
|
access_type: "offline",
|
|
147
147
|
client_id: this.options.clientId,
|
|
148
148
|
code_challenge: e,
|
|
149
|
-
code_challenge_method:
|
|
149
|
+
code_challenge_method: s,
|
|
150
150
|
include_granted_scopes: "true",
|
|
151
151
|
prompt: "consent",
|
|
152
152
|
redirect_uri: this.options.redirectUrl,
|
|
@@ -154,28 +154,28 @@ const S = "https://accounts.google.com/o/oauth2/v2/auth", y = "https://oauth2.go
|
|
|
154
154
|
scope: this.options.scope,
|
|
155
155
|
state: this.session.state
|
|
156
156
|
}).forEach(([n, t]) => {
|
|
157
|
-
t &&
|
|
158
|
-
}),
|
|
157
|
+
t && o.searchParams.set(n, t);
|
|
158
|
+
}), o.href;
|
|
159
159
|
}
|
|
160
160
|
async finishAuth(e) {
|
|
161
161
|
if (!this.session || this.session.state !== e.searchParams.get("state"))
|
|
162
162
|
throw new i(a, "state doesn't match");
|
|
163
|
-
const
|
|
164
|
-
if (!
|
|
165
|
-
const
|
|
163
|
+
const s = e.searchParams.get("code");
|
|
164
|
+
if (!s) throw new i(a, "Invalid code");
|
|
165
|
+
const o = new URLSearchParams();
|
|
166
166
|
Object.entries({
|
|
167
167
|
client_id: this.options.clientId,
|
|
168
168
|
client_secret: this.options.clientSecret,
|
|
169
|
-
code:
|
|
169
|
+
code: s,
|
|
170
170
|
code_verifier: this.session.codeVerifier,
|
|
171
171
|
grant_type: "authorization_code",
|
|
172
172
|
redirect_uri: this.options.redirectUrl
|
|
173
173
|
}).forEach(([c, h]) => {
|
|
174
|
-
h != null &&
|
|
174
|
+
h != null && o.append(c, h);
|
|
175
175
|
});
|
|
176
176
|
const n = await fetch(y, {
|
|
177
177
|
method: "POST",
|
|
178
|
-
body:
|
|
178
|
+
body: o
|
|
179
179
|
}), t = await n.json();
|
|
180
180
|
if (!n.ok) throw { status: n.status, data: t };
|
|
181
181
|
if (!t.refresh_token)
|
|
@@ -189,21 +189,21 @@ const S = "https://accounts.google.com/o/oauth2/v2/auth", y = "https://oauth2.go
|
|
|
189
189
|
}), t.access_token;
|
|
190
190
|
}
|
|
191
191
|
async refreshToken() {
|
|
192
|
-
const e = new URLSearchParams(),
|
|
192
|
+
const e = new URLSearchParams(), s = this.getRefreshToken();
|
|
193
193
|
Object.entries({
|
|
194
194
|
client_id: this.options.clientId,
|
|
195
195
|
client_secret: this.options.clientSecret,
|
|
196
196
|
grant_type: "refresh_token",
|
|
197
|
-
refresh_token:
|
|
197
|
+
refresh_token: s,
|
|
198
198
|
scope: this.options.scope
|
|
199
199
|
}).forEach(([t, c]) => {
|
|
200
200
|
c != null && e.append(t, c);
|
|
201
201
|
});
|
|
202
|
-
const
|
|
202
|
+
const o = await fetch(y, {
|
|
203
203
|
method: "POST",
|
|
204
204
|
body: e
|
|
205
|
-
}), n = await
|
|
206
|
-
if (!
|
|
205
|
+
}), n = await o.json();
|
|
206
|
+
if (!o.ok) throw { status: o.status, data: n };
|
|
207
207
|
return this._updateAccessToken({
|
|
208
208
|
token: n.access_token,
|
|
209
209
|
expiresAt: Date.now() + n.expires_in * 1e3
|
|
@@ -225,42 +225,42 @@ const m = class m extends w {
|
|
|
225
225
|
state: _(),
|
|
226
226
|
codeVerifier: k()
|
|
227
227
|
};
|
|
228
|
-
const { codeChallenge: e, codeChallengeMethod:
|
|
228
|
+
const { codeChallenge: e, codeChallengeMethod: s } = await u(
|
|
229
229
|
this.session.codeVerifier
|
|
230
|
-
),
|
|
230
|
+
), o = new URL(this.oauth2Url("authorize"));
|
|
231
231
|
return Object.entries({
|
|
232
232
|
client_id: this.options.clientId,
|
|
233
233
|
code_challenge: e,
|
|
234
|
-
code_challenge_method:
|
|
234
|
+
code_challenge_method: s,
|
|
235
235
|
redirect_uri: this.options.redirectUrl,
|
|
236
236
|
response_mode: "query",
|
|
237
237
|
response_type: "code",
|
|
238
238
|
scope: this.options.scope,
|
|
239
239
|
state: this.session.state
|
|
240
240
|
}).forEach(([n, t]) => {
|
|
241
|
-
t &&
|
|
242
|
-
}),
|
|
241
|
+
t && o.searchParams.set(n, t);
|
|
242
|
+
}), o.href;
|
|
243
243
|
}
|
|
244
244
|
async finishAuth(e) {
|
|
245
245
|
if (!this.session || this.session.state !== e.searchParams.get("state"))
|
|
246
246
|
throw new i(a, "state doesn't match");
|
|
247
|
-
const
|
|
248
|
-
if (!
|
|
249
|
-
const
|
|
247
|
+
const s = e.searchParams.get("code");
|
|
248
|
+
if (!s) throw new i(a, "Invalid code");
|
|
249
|
+
const o = new URLSearchParams();
|
|
250
250
|
Object.entries({
|
|
251
251
|
client_id: this.options.clientId,
|
|
252
252
|
client_secret: this.options.clientSecret,
|
|
253
|
-
code:
|
|
253
|
+
code: s,
|
|
254
254
|
code_verifier: this.session.codeVerifier,
|
|
255
255
|
grant_type: "authorization_code",
|
|
256
256
|
redirect_uri: this.options.redirectUrl,
|
|
257
257
|
scope: this.options.scope
|
|
258
258
|
}).forEach(([c, h]) => {
|
|
259
|
-
h != null &&
|
|
259
|
+
h != null && o.append(c, h);
|
|
260
260
|
});
|
|
261
261
|
const n = await fetch(this.oauth2Url("token"), {
|
|
262
262
|
method: "POST",
|
|
263
|
-
body:
|
|
263
|
+
body: o
|
|
264
264
|
}), t = await n.json();
|
|
265
265
|
if (!n.ok) throw { status: n.status, data: t };
|
|
266
266
|
if (!t.refresh_token)
|
|
@@ -274,21 +274,21 @@ const m = class m extends w {
|
|
|
274
274
|
}), t.access_token;
|
|
275
275
|
}
|
|
276
276
|
async refreshToken() {
|
|
277
|
-
const e = new URLSearchParams(),
|
|
277
|
+
const e = new URLSearchParams(), s = this.getRefreshToken();
|
|
278
278
|
Object.entries({
|
|
279
279
|
client_id: this.options.clientId,
|
|
280
280
|
client_secret: this.options.clientSecret,
|
|
281
281
|
grant_type: "refresh_token",
|
|
282
|
-
refresh_token:
|
|
282
|
+
refresh_token: s,
|
|
283
283
|
scope: this.options.scope
|
|
284
284
|
}).forEach(([t, c]) => {
|
|
285
285
|
c != null && e.append(t, c);
|
|
286
286
|
});
|
|
287
|
-
const
|
|
287
|
+
const o = await fetch(this.oauth2Url("token"), {
|
|
288
288
|
method: "POST",
|
|
289
289
|
body: e
|
|
290
|
-
}), n = await
|
|
291
|
-
if (!
|
|
290
|
+
}), n = await o.json();
|
|
291
|
+
if (!o.ok) throw { status: o.status, data: n };
|
|
292
292
|
return this._updateAccessToken({
|
|
293
293
|
token: n.access_token,
|
|
294
294
|
expiresAt: Date.now() + n.expires_in * 1e3
|
|
@@ -310,28 +310,28 @@ function x(r, e) {
|
|
|
310
310
|
return new E[e.provider](r);
|
|
311
311
|
}
|
|
312
312
|
async function I(r, e) {
|
|
313
|
-
let
|
|
313
|
+
let s;
|
|
314
314
|
try {
|
|
315
|
-
|
|
316
|
-
} catch (
|
|
317
|
-
if (!(
|
|
318
|
-
throw
|
|
319
|
-
switch (
|
|
315
|
+
s = r.getAccessToken();
|
|
316
|
+
} catch (o) {
|
|
317
|
+
if (!(o instanceof i))
|
|
318
|
+
throw o;
|
|
319
|
+
switch (o.code) {
|
|
320
320
|
case d: {
|
|
321
|
-
if (!e) throw
|
|
321
|
+
if (!e) throw o;
|
|
322
322
|
const n = await r.buildAuthUrl(), t = await e(n);
|
|
323
|
-
|
|
323
|
+
s = await r.finishAuth(new URL(t));
|
|
324
324
|
break;
|
|
325
325
|
}
|
|
326
326
|
case R: {
|
|
327
|
-
|
|
327
|
+
s = await r.refreshToken();
|
|
328
328
|
break;
|
|
329
329
|
}
|
|
330
330
|
default:
|
|
331
|
-
throw
|
|
331
|
+
throw o;
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
|
-
return
|
|
334
|
+
return s;
|
|
335
335
|
}
|
|
336
336
|
export {
|
|
337
337
|
p as DropboxAuthorizer,
|
package/dist/providers/base.d.ts
CHANGED
|
@@ -6,9 +6,17 @@ export declare abstract class OAuth2Authorizer {
|
|
|
6
6
|
abstract refreshToken(): Promise<string>;
|
|
7
7
|
protected _accessToken: TokenData | null;
|
|
8
8
|
protected _refreshToken: TokenData | null;
|
|
9
|
+
session: {
|
|
10
|
+
state: string;
|
|
11
|
+
codeVerifier: string;
|
|
12
|
+
} | undefined;
|
|
9
13
|
constructor(options: IOAuth2Options, initialData?: {
|
|
10
14
|
accessToken?: TokenData;
|
|
11
15
|
refreshToken?: TokenData;
|
|
16
|
+
session?: {
|
|
17
|
+
state: string;
|
|
18
|
+
codeVerifier: string;
|
|
19
|
+
};
|
|
12
20
|
});
|
|
13
21
|
protected _getValidToken(value?: TokenData | null): string | undefined;
|
|
14
22
|
protected _updateAccessToken(value: TokenData | null): void;
|
|
@@ -3,7 +3,6 @@ import { OAuth2Authorizer } from "./base.ts";
|
|
|
3
3
|
* Ref: https://developers.google.com/identity/protocols/oauth2/web-server
|
|
4
4
|
*/
|
|
5
5
|
export declare class GoogleAuthorizer extends OAuth2Authorizer {
|
|
6
|
-
private session;
|
|
7
6
|
/**
|
|
8
7
|
* Ref: https://developers.google.com/identity/protocols/oauth2/scopes
|
|
9
8
|
*/
|
|
@@ -3,7 +3,6 @@ import { OAuth2Authorizer } from "./base.ts";
|
|
|
3
3
|
* Ref: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow
|
|
4
4
|
*/
|
|
5
5
|
export declare class MicrosoftAuthorizer extends OAuth2Authorizer {
|
|
6
|
-
private session;
|
|
7
6
|
static Scopes: {
|
|
8
7
|
/** Ref: https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth */
|
|
9
8
|
imap: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usync/oauth2",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist"
|
|
6
6
|
],
|
|
@@ -23,6 +23,6 @@
|
|
|
23
23
|
"clean": "del-cli dist tsconfig.tsbuildinfo",
|
|
24
24
|
"build:types": "tsc",
|
|
25
25
|
"build:js": "vite build",
|
|
26
|
-
"build": "pnpm clean && pnpm
|
|
26
|
+
"build": "pnpm clean && pnpm build:js && pnpm build:types"
|
|
27
27
|
}
|
|
28
28
|
}
|