@shware/security 0.4.9 → 1.0.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/auth/index.cjs +84 -22
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +8 -2
- package/dist/auth/index.d.ts +8 -2
- package/dist/auth/index.mjs +85 -23
- package/dist/auth/index.mjs.map +1 -1
- package/dist/auth/types.cjs.map +1 -1
- package/dist/auth/types.d.cts +10 -3
- package/dist/auth/types.d.ts +10 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/oauth2/client.cjs +40 -6
- package/dist/oauth2/client.cjs.map +1 -1
- package/dist/oauth2/client.d.cts +29 -6
- package/dist/oauth2/client.d.ts +29 -6
- package/dist/oauth2/client.mjs +40 -6
- package/dist/oauth2/client.mjs.map +1 -1
- package/dist/oauth2/error.cjs.map +1 -1
- package/dist/oauth2/error.d.cts +1 -1
- package/dist/oauth2/error.d.ts +1 -1
- package/dist/oauth2/error.mjs.map +1 -1
- package/dist/oauth2/provider/apple.cjs +21 -5
- package/dist/oauth2/provider/apple.cjs.map +1 -1
- package/dist/oauth2/provider/apple.d.cts +12 -4
- package/dist/oauth2/provider/apple.d.ts +12 -4
- package/dist/oauth2/provider/apple.mjs +19 -4
- package/dist/oauth2/provider/apple.mjs.map +1 -1
- package/dist/oauth2/provider/common.cjs +5 -13
- package/dist/oauth2/provider/common.cjs.map +1 -1
- package/dist/oauth2/provider/common.d.cts +6 -11
- package/dist/oauth2/provider/common.d.ts +6 -11
- package/dist/oauth2/provider/common.mjs +5 -13
- package/dist/oauth2/provider/common.mjs.map +1 -1
- package/dist/oauth2/provider/facebook.cjs +19 -3
- package/dist/oauth2/provider/facebook.cjs.map +1 -1
- package/dist/oauth2/provider/facebook.d.cts +17 -3
- package/dist/oauth2/provider/facebook.d.ts +17 -3
- package/dist/oauth2/provider/facebook.mjs +18 -3
- package/dist/oauth2/provider/facebook.mjs.map +1 -1
- package/dist/oauth2/provider/github.cjs +6 -3
- package/dist/oauth2/provider/github.cjs.map +1 -1
- package/dist/oauth2/provider/github.d.cts +11 -3
- package/dist/oauth2/provider/github.d.ts +11 -3
- package/dist/oauth2/provider/github.mjs +5 -3
- package/dist/oauth2/provider/github.mjs.map +1 -1
- package/dist/oauth2/provider/google.cjs +17 -1
- package/dist/oauth2/provider/google.cjs.map +1 -1
- package/dist/oauth2/provider/google.d.cts +11 -4
- package/dist/oauth2/provider/google.d.ts +11 -4
- package/dist/oauth2/provider/google.mjs +16 -1
- package/dist/oauth2/provider/google.mjs.map +1 -1
- package/dist/oauth2/provider/x.cjs +16 -4
- package/dist/oauth2/provider/x.cjs.map +1 -1
- package/dist/oauth2/provider/x.d.cts +11 -3
- package/dist/oauth2/provider/x.d.ts +11 -3
- package/dist/oauth2/provider/x.mjs +15 -4
- package/dist/oauth2/provider/x.mjs.map +1 -1
- package/dist/oauth2/types.cjs +20 -0
- package/dist/oauth2/types.cjs.map +1 -1
- package/dist/oauth2/types.d.cts +73 -12
- package/dist/oauth2/types.d.ts +73 -12
- package/dist/oauth2/types.mjs +13 -0
- package/dist/oauth2/types.mjs.map +1 -1
- package/dist/session/redis-session.cjs +21 -0
- package/dist/session/redis-session.cjs.map +1 -1
- package/dist/session/redis-session.d.cts +4 -0
- package/dist/session/redis-session.d.ts +4 -0
- package/dist/session/redis-session.mjs +21 -0
- package/dist/session/redis-session.mjs.map +1 -1
- package/dist/session/types.cjs.map +1 -1
- package/dist/session/types.d.cts +3 -0
- package/dist/session/types.d.ts +3 -0
- package/package.json +1 -1
- package/dist/oidc/index.cjs +0 -39
- package/dist/oidc/index.cjs.map +0 -1
- package/dist/oidc/index.d.cts +0 -10
- package/dist/oidc/index.d.ts +0 -10
- package/dist/oidc/index.mjs +0 -14
- package/dist/oidc/index.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth2/provider/apple.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from './common';\n\n// ref: https://account.apple.com/.well-known/openid-configuration\nexport function
|
|
1
|
+
{"version":3,"sources":["../../../src/oauth2/provider/apple.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { NativeCredentials, LoginOAuth2NativeParams, OAuth2Token, Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from './common';\n\n// ref: https://account.apple.com/.well-known/openid-configuration\nexport function createAppleProvider(): Provider {\n return {\n // important notice: response_mode=form_post is required for apple\n authorizationUri: 'https://appleid.apple.com/auth/authorize?response_mode=form_post',\n tokenUri: 'https://appleid.apple.com/auth/token',\n jwkSetUri: 'https://appleid.apple.com/auth/keys',\n userNameAttribute: 'sub',\n defaultScope: ['openid', 'name', 'email'],\n createAuthorizationUri({ pkce, ...params }) {\n return createAuthorizationUri({\n ...params,\n scope: params.scope ?? this.defaultScope,\n authorizationUri: this.authorizationUri,\n });\n },\n async exchangeAuthorizationCode({ pkce, ...params }) {\n const response = await exchangeAuthorizationCode({ ...params, tokenUri: this.tokenUri });\n if (!response.ok) {\n const { error } = (await response.json()) as AppleErrorResponse;\n throw new OAuth2Error(response.status, error);\n }\n return (await response.json()) as AppleToken;\n },\n async getUserInfo({ id_token }) {\n invariant(id_token, 'id_token is required');\n invariant(this.jwkSetUri, 'jwkSetUri is required');\n const data = await verifyIdToken<AppleUserInfo>(id_token, this.jwkSetUri);\n return {\n data,\n claims: {\n sub: data.sub,\n name: data.name,\n email: data.email,\n email_verified: true,\n picture: data.picture,\n given_name: data.user?.name.firstName,\n family_name: data.user?.name.lastName,\n },\n };\n },\n async loginOAuth2Native({ pkce, credentials, ...params }: LoginOAuth2NativeParams) {\n invariant(credentials.code, 'code is required');\n const { tokenUri } = this;\n const { code } = credentials;\n const response = await exchangeAuthorizationCode({ code, tokenUri, ...params });\n if (!response.ok) {\n const { error } = (await response.json()) as AppleErrorResponse;\n throw new OAuth2Error(response.status, error);\n }\n const token = (await response.json()) as AppleToken;\n const userInfo = await this.getUserInfo(token);\n return { token, userInfo };\n },\n };\n}\n\nexport const apple = createAppleProvider();\n\n// https://developer.apple.com/documentation/sign_in_with_apple/authenticating-users-with-sign-in-with-apple\nexport interface AppleUserInfo {\n sub: string;\n email: string;\n email_verified: true | 'true';\n is_private_email: boolean;\n real_user_status: number;\n name: string;\n picture: string;\n user?: {\n name: { firstName: string; lastName: string };\n email: string;\n };\n}\n\n// https://developer.apple.com/documentation/devicemanagement/implementing-the-oauth2-authentication-user-enrollment-flow\n// https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens\nexport interface AppleToken extends OAuth2Token {\n access_token: string;\n token_type: string;\n expires_in: number;\n refresh_token: string;\n id_token: string;\n}\n\nexport interface AppleNativeCredentials extends NativeCredentials {\n state: string;\n code: string;\n id_token: string;\n // no standard fields\n user: string;\n email?: string;\n}\n\n// https://developer.apple.com/documentation/sign_in_with_apple/errorresponse\nexport interface AppleErrorResponse {\n error:\n | 'invalid_request'\n | 'invalid_client'\n | 'invalid_grant'\n | 'unauthorized_client'\n | 'unsupported_grant_type'\n | 'invalid_scope';\n}\n"],"mappings":";AAAA,OAAO,eAAe;AAEtB,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB,2BAA2B,qBAAqB;AAG1E,SAAS,sBAAgC;AAC9C,SAAO;AAAA;AAAA,IAEL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,cAAc,CAAC,UAAU,QAAQ,OAAO;AAAA,IACxC,uBAAuB,EAAE,MAAM,GAAG,OAAO,GAAG;AAC1C,aAAO,uBAAuB;AAAA,QAC5B,GAAG;AAAA,QACH,OAAO,OAAO,SAAS,KAAK;AAAA,QAC5B,kBAAkB,KAAK;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,IACA,MAAM,0BAA0B,EAAE,MAAM,GAAG,OAAO,GAAG;AACnD,YAAM,WAAW,MAAM,0BAA0B,EAAE,GAAG,QAAQ,UAAU,KAAK,SAAS,CAAC;AACvF,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,EAAE,MAAM,IAAK,MAAM,SAAS,KAAK;AACvC,cAAM,IAAI,YAAY,SAAS,QAAQ,KAAK;AAAA,MAC9C;AACA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAAA,IACA,MAAM,YAAY,EAAE,SAAS,GAAG;AAC9B,gBAAU,UAAU,sBAAsB;AAC1C,gBAAU,KAAK,WAAW,uBAAuB;AACjD,YAAM,OAAO,MAAM,cAA6B,UAAU,KAAK,SAAS;AACxE,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,UACN,KAAK,KAAK;AAAA,UACV,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,gBAAgB;AAAA,UAChB,SAAS,KAAK;AAAA,UACd,YAAY,KAAK,MAAM,KAAK;AAAA,UAC5B,aAAa,KAAK,MAAM,KAAK;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM,kBAAkB,EAAE,MAAM,aAAa,GAAG,OAAO,GAA4B;AACjF,gBAAU,YAAY,MAAM,kBAAkB;AAC9C,YAAM,EAAE,SAAS,IAAI;AACrB,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,WAAW,MAAM,0BAA0B,EAAE,MAAM,UAAU,GAAG,OAAO,CAAC;AAC9E,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,EAAE,MAAM,IAAK,MAAM,SAAS,KAAK;AACvC,cAAM,IAAI,YAAY,SAAS,QAAQ,KAAK;AAAA,MAC9C;AACA,YAAM,QAAS,MAAM,SAAS,KAAK;AACnC,YAAM,WAAW,MAAM,KAAK,YAAY,KAAK;AAC7C,aAAO,EAAE,OAAO,SAAS;AAAA,IAC3B;AAAA,EACF;AACF;AAEO,IAAM,QAAQ,oBAAoB;","names":[]}
|
|
@@ -37,7 +37,6 @@ __export(common_exports, {
|
|
|
37
37
|
verifyIdToken: () => verifyIdToken
|
|
38
38
|
});
|
|
39
39
|
module.exports = __toCommonJS(common_exports);
|
|
40
|
-
var import_crypto = require("crypto");
|
|
41
40
|
var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
|
|
42
41
|
var import_error = require("../error.cjs");
|
|
43
42
|
function createAuthorizationUri(options) {
|
|
@@ -47,10 +46,9 @@ function createAuthorizationUri(options) {
|
|
|
47
46
|
url.searchParams.append("state", options.state);
|
|
48
47
|
url.searchParams.append("scope", options.scope.join(" "));
|
|
49
48
|
url.searchParams.append("redirect_uri", options.redirectUri);
|
|
50
|
-
if (options.
|
|
51
|
-
|
|
52
|
-
url.searchParams.append("
|
|
53
|
-
url.searchParams.append("code_challenge", codeChallenge);
|
|
49
|
+
if (options.pkce) {
|
|
50
|
+
url.searchParams.append("code_challenge_method", options.pkce.code_challenge_method);
|
|
51
|
+
url.searchParams.append("code_challenge", options.pkce.code_challenge);
|
|
54
52
|
}
|
|
55
53
|
return url;
|
|
56
54
|
}
|
|
@@ -59,7 +57,7 @@ async function exchangeAuthorizationCode(params) {
|
|
|
59
57
|
body.append("code", params.code);
|
|
60
58
|
body.append("redirect_uri", params.redirectUri);
|
|
61
59
|
body.append("grant_type", "authorization_code");
|
|
62
|
-
if (params.
|
|
60
|
+
if (params.pkce) body.append("code_verifier", params.pkce.code_verifier);
|
|
63
61
|
const headers = {
|
|
64
62
|
Accept: "application/json",
|
|
65
63
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
@@ -88,13 +86,7 @@ async function refreshAccessToken(params) {
|
|
|
88
86
|
body.append("client_id", params.clientId);
|
|
89
87
|
body.append("client_secret", params.clientSecret);
|
|
90
88
|
}
|
|
91
|
-
|
|
92
|
-
if (!response.ok) {
|
|
93
|
-
const error = await response.json();
|
|
94
|
-
console.error("Refresh token error:", error);
|
|
95
|
-
throw new import_error.OAuth2Error(response.status, "invalid_request", "Failed to refresh token");
|
|
96
|
-
}
|
|
97
|
-
return await response.json();
|
|
89
|
+
return fetch(params.tokenUri, { method: "POST", headers, body });
|
|
98
90
|
}
|
|
99
91
|
async function revokeToken(params) {
|
|
100
92
|
const body = new URLSearchParams();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth2/provider/common.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../src/oauth2/provider/common.ts"],"sourcesContent":["import jwt from 'jsonwebtoken';\nimport { OAuth2Error } from '../error';\nimport { ExchangeCodeParams, PkceParameters, RefreshTokenParams } from '../types';\n\nexport function createAuthorizationUri(options: {\n state: string;\n scope: string[];\n clientId: string;\n redirectUri: string;\n authorizationUri: string;\n pkce?: Omit<PkceParameters, 'code_verifier'>;\n}) {\n const url = new URL(options.authorizationUri);\n url.searchParams.append('response_type', 'code');\n url.searchParams.append('client_id', options.clientId);\n url.searchParams.append('state', options.state);\n url.searchParams.append('scope', options.scope.join(' '));\n url.searchParams.append('redirect_uri', options.redirectUri);\n if (options.pkce) {\n url.searchParams.append('code_challenge_method', options.pkce.code_challenge_method);\n url.searchParams.append('code_challenge', options.pkce.code_challenge);\n }\n return url;\n}\n\nexport async function exchangeAuthorizationCode(\n params: ExchangeCodeParams & {\n tokenUri: string;\n authentication?: 'basic' | 'post';\n }\n) {\n const body = new URLSearchParams();\n body.append('code', params.code);\n body.append('redirect_uri', params.redirectUri);\n body.append('grant_type', 'authorization_code');\n if (params.pkce) body.append('code_verifier', params.pkce.code_verifier);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n return fetch(params.tokenUri, { method: 'POST', headers, body });\n}\n\nexport async function refreshAccessToken(\n params: RefreshTokenParams & {\n tokenUri: string;\n authentication?: 'basic' | 'post';\n }\n) {\n const body = new URLSearchParams();\n body.append('grant_type', 'refresh_token');\n body.append('refresh_token', params.refreshToken);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n return fetch(params.tokenUri, { method: 'POST', headers, body });\n}\n\ninterface RevokeTokenParams {\n token: string;\n clientId: string;\n clientSecret: string;\n tokenRevokeUri: string;\n authentication?: 'basic' | 'post';\n}\n\nexport async function revokeToken(params: RevokeTokenParams) {\n const body = new URLSearchParams();\n body.append('token', params.token);\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n const response = await fetch(params.tokenRevokeUri, { method: 'POST', headers, body });\n if (!response.ok) {\n const error = await response.json();\n console.error('Refresh token error:', error);\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to revoke token');\n }\n}\n\ninterface JWKSet {\n keys: { kty: string; kid: string; use: string; alg: string; n: string; e: string }[];\n}\n\nconst cache = new Map<string, JWKSet>();\n\nasync function getJWK(kid: string, jwkSetUri: string) {\n let jwkSet: JWKSet;\n if (cache.has(jwkSetUri)) {\n jwkSet = cache.get(jwkSetUri)!;\n } else {\n const response = await fetch(jwkSetUri);\n if (!response.ok) throw new OAuth2Error(response.status, 'server_error', 'Failed to fetch JWK');\n jwkSet = (await response.json()) as JWKSet;\n cache.set(jwkSetUri, jwkSet);\n }\n\n const jwk = jwkSet.keys.find((key) => key.kid === kid);\n if (!jwk) throw new OAuth2Error(400, 'invalid_request', `JWK not found for kid: ${kid}`);\n return jwk;\n}\n\nexport async function verifyIdToken<T>(idToken: string, jwkSetUri: string) {\n const header = jwt.decode(idToken, { complete: true });\n if (!header?.header.kid) {\n throw new OAuth2Error(400, 'invalid_request', 'kid not found in id_token header');\n }\n try {\n const key = await getJWK(header.header.kid, jwkSetUri);\n return jwt.verify(idToken, { key, format: 'jwk' }) as T;\n } catch (e) {\n throw new OAuth2Error(400, 'invalid_request', 'Failed to verify id_token');\n }\n}\n"],"mappings":"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","names":["jwt"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as url from 'url';
|
|
2
|
-
import {
|
|
2
|
+
import { PkceParameters, ExchangeCodeParams, RefreshTokenParams } from '../types.cjs';
|
|
3
3
|
|
|
4
4
|
declare function createAuthorizationUri(options: {
|
|
5
5
|
state: string;
|
|
@@ -7,21 +7,16 @@ declare function createAuthorizationUri(options: {
|
|
|
7
7
|
clientId: string;
|
|
8
8
|
redirectUri: string;
|
|
9
9
|
authorizationUri: string;
|
|
10
|
-
|
|
10
|
+
pkce?: Omit<PkceParameters, 'code_verifier'>;
|
|
11
11
|
}): url.URL;
|
|
12
|
-
|
|
12
|
+
declare function exchangeAuthorizationCode(params: ExchangeCodeParams & {
|
|
13
13
|
tokenUri: string;
|
|
14
14
|
authentication?: 'basic' | 'post';
|
|
15
|
-
}
|
|
16
|
-
declare function
|
|
17
|
-
interface RefreshTokenParams {
|
|
15
|
+
}): Promise<Response>;
|
|
16
|
+
declare function refreshAccessToken(params: RefreshTokenParams & {
|
|
18
17
|
tokenUri: string;
|
|
19
|
-
clientId: string;
|
|
20
|
-
clientSecret: string;
|
|
21
|
-
refreshToken: string;
|
|
22
18
|
authentication?: 'basic' | 'post';
|
|
23
|
-
}
|
|
24
|
-
declare function refreshAccessToken(params: RefreshTokenParams): Promise<OAuth2Token>;
|
|
19
|
+
}): Promise<Response>;
|
|
25
20
|
interface RevokeTokenParams {
|
|
26
21
|
token: string;
|
|
27
22
|
clientId: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as url from 'url';
|
|
2
|
-
import {
|
|
2
|
+
import { PkceParameters, ExchangeCodeParams, RefreshTokenParams } from '../types.js';
|
|
3
3
|
|
|
4
4
|
declare function createAuthorizationUri(options: {
|
|
5
5
|
state: string;
|
|
@@ -7,21 +7,16 @@ declare function createAuthorizationUri(options: {
|
|
|
7
7
|
clientId: string;
|
|
8
8
|
redirectUri: string;
|
|
9
9
|
authorizationUri: string;
|
|
10
|
-
|
|
10
|
+
pkce?: Omit<PkceParameters, 'code_verifier'>;
|
|
11
11
|
}): url.URL;
|
|
12
|
-
|
|
12
|
+
declare function exchangeAuthorizationCode(params: ExchangeCodeParams & {
|
|
13
13
|
tokenUri: string;
|
|
14
14
|
authentication?: 'basic' | 'post';
|
|
15
|
-
}
|
|
16
|
-
declare function
|
|
17
|
-
interface RefreshTokenParams {
|
|
15
|
+
}): Promise<Response>;
|
|
16
|
+
declare function refreshAccessToken(params: RefreshTokenParams & {
|
|
18
17
|
tokenUri: string;
|
|
19
|
-
clientId: string;
|
|
20
|
-
clientSecret: string;
|
|
21
|
-
refreshToken: string;
|
|
22
18
|
authentication?: 'basic' | 'post';
|
|
23
|
-
}
|
|
24
|
-
declare function refreshAccessToken(params: RefreshTokenParams): Promise<OAuth2Token>;
|
|
19
|
+
}): Promise<Response>;
|
|
25
20
|
interface RevokeTokenParams {
|
|
26
21
|
token: string;
|
|
27
22
|
clientId: string;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// src/oauth2/provider/common.ts
|
|
2
|
-
import { createHash } from "crypto";
|
|
3
2
|
import jwt from "jsonwebtoken";
|
|
4
3
|
import { OAuth2Error } from "../error.mjs";
|
|
5
4
|
function createAuthorizationUri(options) {
|
|
@@ -9,10 +8,9 @@ function createAuthorizationUri(options) {
|
|
|
9
8
|
url.searchParams.append("state", options.state);
|
|
10
9
|
url.searchParams.append("scope", options.scope.join(" "));
|
|
11
10
|
url.searchParams.append("redirect_uri", options.redirectUri);
|
|
12
|
-
if (options.
|
|
13
|
-
|
|
14
|
-
url.searchParams.append("
|
|
15
|
-
url.searchParams.append("code_challenge", codeChallenge);
|
|
11
|
+
if (options.pkce) {
|
|
12
|
+
url.searchParams.append("code_challenge_method", options.pkce.code_challenge_method);
|
|
13
|
+
url.searchParams.append("code_challenge", options.pkce.code_challenge);
|
|
16
14
|
}
|
|
17
15
|
return url;
|
|
18
16
|
}
|
|
@@ -21,7 +19,7 @@ async function exchangeAuthorizationCode(params) {
|
|
|
21
19
|
body.append("code", params.code);
|
|
22
20
|
body.append("redirect_uri", params.redirectUri);
|
|
23
21
|
body.append("grant_type", "authorization_code");
|
|
24
|
-
if (params.
|
|
22
|
+
if (params.pkce) body.append("code_verifier", params.pkce.code_verifier);
|
|
25
23
|
const headers = {
|
|
26
24
|
Accept: "application/json",
|
|
27
25
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
@@ -50,13 +48,7 @@ async function refreshAccessToken(params) {
|
|
|
50
48
|
body.append("client_id", params.clientId);
|
|
51
49
|
body.append("client_secret", params.clientSecret);
|
|
52
50
|
}
|
|
53
|
-
|
|
54
|
-
if (!response.ok) {
|
|
55
|
-
const error = await response.json();
|
|
56
|
-
console.error("Refresh token error:", error);
|
|
57
|
-
throw new OAuth2Error(response.status, "invalid_request", "Failed to refresh token");
|
|
58
|
-
}
|
|
59
|
-
return await response.json();
|
|
51
|
+
return fetch(params.tokenUri, { method: "POST", headers, body });
|
|
60
52
|
}
|
|
61
53
|
async function revokeToken(params) {
|
|
62
54
|
const body = new URLSearchParams();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth2/provider/common.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../src/oauth2/provider/common.ts"],"sourcesContent":["import jwt from 'jsonwebtoken';\nimport { OAuth2Error } from '../error';\nimport { ExchangeCodeParams, PkceParameters, RefreshTokenParams } from '../types';\n\nexport function createAuthorizationUri(options: {\n state: string;\n scope: string[];\n clientId: string;\n redirectUri: string;\n authorizationUri: string;\n pkce?: Omit<PkceParameters, 'code_verifier'>;\n}) {\n const url = new URL(options.authorizationUri);\n url.searchParams.append('response_type', 'code');\n url.searchParams.append('client_id', options.clientId);\n url.searchParams.append('state', options.state);\n url.searchParams.append('scope', options.scope.join(' '));\n url.searchParams.append('redirect_uri', options.redirectUri);\n if (options.pkce) {\n url.searchParams.append('code_challenge_method', options.pkce.code_challenge_method);\n url.searchParams.append('code_challenge', options.pkce.code_challenge);\n }\n return url;\n}\n\nexport async function exchangeAuthorizationCode(\n params: ExchangeCodeParams & {\n tokenUri: string;\n authentication?: 'basic' | 'post';\n }\n) {\n const body = new URLSearchParams();\n body.append('code', params.code);\n body.append('redirect_uri', params.redirectUri);\n body.append('grant_type', 'authorization_code');\n if (params.pkce) body.append('code_verifier', params.pkce.code_verifier);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n return fetch(params.tokenUri, { method: 'POST', headers, body });\n}\n\nexport async function refreshAccessToken(\n params: RefreshTokenParams & {\n tokenUri: string;\n authentication?: 'basic' | 'post';\n }\n) {\n const body = new URLSearchParams();\n body.append('grant_type', 'refresh_token');\n body.append('refresh_token', params.refreshToken);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n return fetch(params.tokenUri, { method: 'POST', headers, body });\n}\n\ninterface RevokeTokenParams {\n token: string;\n clientId: string;\n clientSecret: string;\n tokenRevokeUri: string;\n authentication?: 'basic' | 'post';\n}\n\nexport async function revokeToken(params: RevokeTokenParams) {\n const body = new URLSearchParams();\n body.append('token', params.token);\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n const response = await fetch(params.tokenRevokeUri, { method: 'POST', headers, body });\n if (!response.ok) {\n const error = await response.json();\n console.error('Refresh token error:', error);\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to revoke token');\n }\n}\n\ninterface JWKSet {\n keys: { kty: string; kid: string; use: string; alg: string; n: string; e: string }[];\n}\n\nconst cache = new Map<string, JWKSet>();\n\nasync function getJWK(kid: string, jwkSetUri: string) {\n let jwkSet: JWKSet;\n if (cache.has(jwkSetUri)) {\n jwkSet = cache.get(jwkSetUri)!;\n } else {\n const response = await fetch(jwkSetUri);\n if (!response.ok) throw new OAuth2Error(response.status, 'server_error', 'Failed to fetch JWK');\n jwkSet = (await response.json()) as JWKSet;\n cache.set(jwkSetUri, jwkSet);\n }\n\n const jwk = jwkSet.keys.find((key) => key.kid === kid);\n if (!jwk) throw new OAuth2Error(400, 'invalid_request', `JWK not found for kid: ${kid}`);\n return jwk;\n}\n\nexport async function verifyIdToken<T>(idToken: string, jwkSetUri: string) {\n const header = jwt.decode(idToken, { complete: true });\n if (!header?.header.kid) {\n throw new OAuth2Error(400, 'invalid_request', 'kid not found in id_token header');\n }\n try {\n const key = await getJWK(header.header.kid, jwkSetUri);\n return jwt.verify(idToken, { key, format: 'jwk' }) as T;\n } catch (e) {\n throw new OAuth2Error(400, 'invalid_request', 'Failed to verify id_token');\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -30,13 +30,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/oauth2/provider/facebook.ts
|
|
31
31
|
var facebook_exports = {};
|
|
32
32
|
__export(facebook_exports, {
|
|
33
|
+
createFacebookProvider: () => createFacebookProvider,
|
|
33
34
|
facebook: () => facebook
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(facebook_exports);
|
|
36
37
|
var import_tiny_invariant = __toESM(require("tiny-invariant"), 1);
|
|
37
38
|
var import_error = require("../error.cjs");
|
|
38
39
|
var import_common = require("./common.cjs");
|
|
39
|
-
function
|
|
40
|
+
function createFacebookProvider() {
|
|
40
41
|
return {
|
|
41
42
|
authorizationUri: "https://www.facebook.com/v21.0/dialog/oauth",
|
|
42
43
|
tokenUri: "https://graph.facebook.com/v19.0/oauth/access_token",
|
|
@@ -44,14 +45,14 @@ function facebook() {
|
|
|
44
45
|
jwkSetUri: "https://limited.facebook.com/.well-known/oauth/openid/jwks/",
|
|
45
46
|
userNameAttribute: "id",
|
|
46
47
|
defaultScope: ["profile", "email"],
|
|
47
|
-
createAuthorizationUri({
|
|
48
|
+
createAuthorizationUri({ pkce, ...params }) {
|
|
48
49
|
return (0, import_common.createAuthorizationUri)({
|
|
49
50
|
...params,
|
|
50
51
|
scope: params.scope ?? this.defaultScope,
|
|
51
52
|
authorizationUri: this.authorizationUri
|
|
52
53
|
});
|
|
53
54
|
},
|
|
54
|
-
async exchangeAuthorizationCode({
|
|
55
|
+
async exchangeAuthorizationCode({ pkce, ...params }) {
|
|
55
56
|
const response = await (0, import_common.exchangeAuthorizationCode)({ ...params, tokenUri: this.tokenUri });
|
|
56
57
|
if (!response.ok) {
|
|
57
58
|
const { error } = await response.json();
|
|
@@ -96,11 +97,26 @@ function facebook() {
|
|
|
96
97
|
email_verified: data.email_verified
|
|
97
98
|
}
|
|
98
99
|
};
|
|
100
|
+
},
|
|
101
|
+
async loginOAuth2Native({ credentials }) {
|
|
102
|
+
if (credentials.id_token || credentials.access_token) {
|
|
103
|
+
const userInfo = await this.getUserInfo(credentials);
|
|
104
|
+
const token = {
|
|
105
|
+
token_type: "bearer",
|
|
106
|
+
access_token: credentials.access_token ?? "",
|
|
107
|
+
id_token: credentials.id_token
|
|
108
|
+
};
|
|
109
|
+
return { token, userInfo };
|
|
110
|
+
} else {
|
|
111
|
+
throw new import_error.OAuth2Error(400, "invalid_request", "id_token or access_token is required");
|
|
112
|
+
}
|
|
99
113
|
}
|
|
100
114
|
};
|
|
101
115
|
}
|
|
116
|
+
var facebook = createFacebookProvider();
|
|
102
117
|
// Annotate the CommonJS export names for ESM import in node:
|
|
103
118
|
0 && (module.exports = {
|
|
119
|
+
createFacebookProvider,
|
|
104
120
|
facebook
|
|
105
121
|
});
|
|
106
122
|
//# sourceMappingURL=facebook.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth2/provider/facebook.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from './common';\n\n/**\n * ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/\n * ref: https://developers.facebook.com/tools/explorer\n * */\nexport function
|
|
1
|
+
{"version":3,"sources":["../../../src/oauth2/provider/facebook.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { LoginOAuth2NativeParams, OAuth2Token, Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from './common';\n\n/**\n * ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/\n * ref: https://developers.facebook.com/tools/explorer\n * */\nexport function createFacebookProvider(): Provider {\n return {\n authorizationUri: 'https://www.facebook.com/v21.0/dialog/oauth',\n tokenUri: 'https://graph.facebook.com/v19.0/oauth/access_token',\n userInfoUri: 'https://graph.facebook.com/me',\n jwkSetUri: 'https://limited.facebook.com/.well-known/oauth/openid/jwks/',\n userNameAttribute: 'id',\n defaultScope: ['profile', 'email'],\n createAuthorizationUri({ pkce, ...params }) {\n return createAuthorizationUri({\n ...params,\n scope: params.scope ?? this.defaultScope,\n authorizationUri: this.authorizationUri,\n });\n },\n async exchangeAuthorizationCode({ pkce, ...params }) {\n const response = await exchangeAuthorizationCode({ ...params, tokenUri: this.tokenUri });\n if (!response.ok) {\n const { error } = (await response.json()) as FacebookErrorResponse;\n throw new OAuth2Error(response.status, 'invalid_request', error.message);\n }\n return (await response.json()) as FacebookToken;\n },\n async getUserInfo({ id_token, access_token }) {\n invariant(this.jwkSetUri, 'jwkSetUri is required');\n if (id_token) {\n const data = await verifyIdToken<FacebookDecodedIdToken>(id_token, this.jwkSetUri);\n return {\n data,\n claims: {\n sub: data.sub,\n name: data.name,\n picture: data.picture,\n email: data.email,\n email_verified: true,\n },\n };\n }\n invariant(access_token, 'access_token is required');\n invariant(this.userInfoUri, 'userInfoUri is required');\n\n const url = new URL(this.userInfoUri);\n const fields = ['id', 'name', 'email', 'picture.width(320).height(320)'];\n url.searchParams.append('access_token', access_token);\n url.searchParams.append('fields', fields.join(','));\n const headers = { Accept: 'application/json' };\n const response = await fetch(url.href, { headers });\n if (!response.ok) {\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to fetch user info');\n }\n const data = (await response.json()) as FacebookUserInfo;\n return {\n data,\n claims: {\n sub: data.id,\n name: data.name,\n email: data.email,\n picture: data.picture.data.url,\n email_verified: data.email_verified,\n },\n };\n },\n async loginOAuth2Native({ credentials }: LoginOAuth2NativeParams) {\n if (credentials.id_token || credentials.access_token) {\n const userInfo = await this.getUserInfo(credentials as unknown as OAuth2Token);\n const token: OAuth2Token = {\n token_type: 'bearer',\n access_token: credentials.access_token ?? '',\n id_token: credentials.id_token,\n };\n return { token, userInfo };\n } else {\n throw new OAuth2Error(400, 'invalid_request', 'id_token or access_token is required');\n }\n },\n };\n}\n\nexport const facebook = createFacebookProvider();\n\nexport interface FacebookDecodedIdToken {\n sub: string;\n name: string;\n email: string;\n picture: string;\n}\n\nexport interface FacebookUserInfo {\n id: string;\n name: string;\n email: string;\n email_verified: boolean;\n picture: {\n data: {\n url: string;\n width: number;\n height: number;\n is_silhouette: boolean;\n };\n };\n}\n\nexport interface FacebookToken extends OAuth2Token {\n access_token: string;\n token_type: 'bearer';\n expires_in: number;\n id_token?: string;\n}\n\nexport type FacebookAppCredentials =\n | { state: string; id_token: string } // platform=ios and tracking=limited\n | { state: string; access_token: string }; // tracking=enabled\n\ninterface FacebookErrorResponse {\n error: {\n message: string;\n type: 'OAuthException';\n code: number;\n error_subcode: number;\n fbtrace_id: string;\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAsB;AAEtB,mBAA4B;AAC5B,oBAAiF;AAM1E,SAAS,yBAAmC;AACjD,SAAO;AAAA,IACL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,cAAc,CAAC,WAAW,OAAO;AAAA,IACjC,uBAAuB,EAAE,MAAM,GAAG,OAAO,GAAG;AAC1C,iBAAO,sCAAuB;AAAA,QAC5B,GAAG;AAAA,QACH,OAAO,OAAO,SAAS,KAAK;AAAA,QAC5B,kBAAkB,KAAK;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,IACA,MAAM,0BAA0B,EAAE,MAAM,GAAG,OAAO,GAAG;AACnD,YAAM,WAAW,UAAM,yCAA0B,EAAE,GAAG,QAAQ,UAAU,KAAK,SAAS,CAAC;AACvF,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,EAAE,MAAM,IAAK,MAAM,SAAS,KAAK;AACvC,cAAM,IAAI,yBAAY,SAAS,QAAQ,mBAAmB,MAAM,OAAO;AAAA,MACzE;AACA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAAA,IACA,MAAM,YAAY,EAAE,UAAU,aAAa,GAAG;AAC5C,gCAAAA,SAAU,KAAK,WAAW,uBAAuB;AACjD,UAAI,UAAU;AACZ,cAAMC,QAAO,UAAM,6BAAsC,UAAU,KAAK,SAAS;AACjF,eAAO;AAAA,UACL,MAAAA;AAAA,UACA,QAAQ;AAAA,YACN,KAAKA,MAAK;AAAA,YACV,MAAMA,MAAK;AAAA,YACX,SAASA,MAAK;AAAA,YACd,OAAOA,MAAK;AAAA,YACZ,gBAAgB;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AACA,gCAAAD,SAAU,cAAc,0BAA0B;AAClD,gCAAAA,SAAU,KAAK,aAAa,yBAAyB;AAErD,YAAM,MAAM,IAAI,IAAI,KAAK,WAAW;AACpC,YAAM,SAAS,CAAC,MAAM,QAAQ,SAAS,gCAAgC;AACvE,UAAI,aAAa,OAAO,gBAAgB,YAAY;AACpD,UAAI,aAAa,OAAO,UAAU,OAAO,KAAK,GAAG,CAAC;AAClD,YAAM,UAAU,EAAE,QAAQ,mBAAmB;AAC7C,YAAM,WAAW,MAAM,MAAM,IAAI,MAAM,EAAE,QAAQ,CAAC;AAClD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,yBAAY,SAAS,QAAQ,mBAAmB,2BAA2B;AAAA,MACvF;AACA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,UACN,KAAK,KAAK;AAAA,UACV,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK,QAAQ,KAAK;AAAA,UAC3B,gBAAgB,KAAK;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM,kBAAkB,EAAE,YAAY,GAA4B;AAChE,UAAI,YAAY,YAAY,YAAY,cAAc;AACpD,cAAM,WAAW,MAAM,KAAK,YAAY,WAAqC;AAC7E,cAAM,QAAqB;AAAA,UACzB,YAAY;AAAA,UACZ,cAAc,YAAY,gBAAgB;AAAA,UAC1C,UAAU,YAAY;AAAA,QACxB;AACA,eAAO,EAAE,OAAO,SAAS;AAAA,MAC3B,OAAO;AACL,cAAM,IAAI,yBAAY,KAAK,mBAAmB,sCAAsC;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,WAAW,uBAAuB;","names":["invariant","data"]}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Provider } from '../types.cjs';
|
|
1
|
+
import { Provider, OAuth2Token } from '../types.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/
|
|
5
5
|
* ref: https://developers.facebook.com/tools/explorer
|
|
6
6
|
* */
|
|
7
|
-
declare function
|
|
7
|
+
declare function createFacebookProvider(): Provider;
|
|
8
|
+
declare const facebook: Provider;
|
|
8
9
|
interface FacebookDecodedIdToken {
|
|
9
10
|
sub: string;
|
|
10
11
|
name: string;
|
|
@@ -25,5 +26,18 @@ interface FacebookUserInfo {
|
|
|
25
26
|
};
|
|
26
27
|
};
|
|
27
28
|
}
|
|
29
|
+
interface FacebookToken extends OAuth2Token {
|
|
30
|
+
access_token: string;
|
|
31
|
+
token_type: 'bearer';
|
|
32
|
+
expires_in: number;
|
|
33
|
+
id_token?: string;
|
|
34
|
+
}
|
|
35
|
+
type FacebookAppCredentials = {
|
|
36
|
+
state: string;
|
|
37
|
+
id_token: string;
|
|
38
|
+
} | {
|
|
39
|
+
state: string;
|
|
40
|
+
access_token: string;
|
|
41
|
+
};
|
|
28
42
|
|
|
29
|
-
export { type FacebookDecodedIdToken, type FacebookUserInfo, facebook };
|
|
43
|
+
export { type FacebookAppCredentials, type FacebookDecodedIdToken, type FacebookToken, type FacebookUserInfo, createFacebookProvider, facebook };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Provider } from '../types.js';
|
|
1
|
+
import { Provider, OAuth2Token } from '../types.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/
|
|
5
5
|
* ref: https://developers.facebook.com/tools/explorer
|
|
6
6
|
* */
|
|
7
|
-
declare function
|
|
7
|
+
declare function createFacebookProvider(): Provider;
|
|
8
|
+
declare const facebook: Provider;
|
|
8
9
|
interface FacebookDecodedIdToken {
|
|
9
10
|
sub: string;
|
|
10
11
|
name: string;
|
|
@@ -25,5 +26,18 @@ interface FacebookUserInfo {
|
|
|
25
26
|
};
|
|
26
27
|
};
|
|
27
28
|
}
|
|
29
|
+
interface FacebookToken extends OAuth2Token {
|
|
30
|
+
access_token: string;
|
|
31
|
+
token_type: 'bearer';
|
|
32
|
+
expires_in: number;
|
|
33
|
+
id_token?: string;
|
|
34
|
+
}
|
|
35
|
+
type FacebookAppCredentials = {
|
|
36
|
+
state: string;
|
|
37
|
+
id_token: string;
|
|
38
|
+
} | {
|
|
39
|
+
state: string;
|
|
40
|
+
access_token: string;
|
|
41
|
+
};
|
|
28
42
|
|
|
29
|
-
export { type FacebookDecodedIdToken, type FacebookUserInfo, facebook };
|
|
43
|
+
export { type FacebookAppCredentials, type FacebookDecodedIdToken, type FacebookToken, type FacebookUserInfo, createFacebookProvider, facebook };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import invariant from "tiny-invariant";
|
|
3
3
|
import { OAuth2Error } from "../error.mjs";
|
|
4
4
|
import { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from "./common.mjs";
|
|
5
|
-
function
|
|
5
|
+
function createFacebookProvider() {
|
|
6
6
|
return {
|
|
7
7
|
authorizationUri: "https://www.facebook.com/v21.0/dialog/oauth",
|
|
8
8
|
tokenUri: "https://graph.facebook.com/v19.0/oauth/access_token",
|
|
@@ -10,14 +10,14 @@ function facebook() {
|
|
|
10
10
|
jwkSetUri: "https://limited.facebook.com/.well-known/oauth/openid/jwks/",
|
|
11
11
|
userNameAttribute: "id",
|
|
12
12
|
defaultScope: ["profile", "email"],
|
|
13
|
-
createAuthorizationUri({
|
|
13
|
+
createAuthorizationUri({ pkce, ...params }) {
|
|
14
14
|
return createAuthorizationUri({
|
|
15
15
|
...params,
|
|
16
16
|
scope: params.scope ?? this.defaultScope,
|
|
17
17
|
authorizationUri: this.authorizationUri
|
|
18
18
|
});
|
|
19
19
|
},
|
|
20
|
-
async exchangeAuthorizationCode({
|
|
20
|
+
async exchangeAuthorizationCode({ pkce, ...params }) {
|
|
21
21
|
const response = await exchangeAuthorizationCode({ ...params, tokenUri: this.tokenUri });
|
|
22
22
|
if (!response.ok) {
|
|
23
23
|
const { error } = await response.json();
|
|
@@ -62,10 +62,25 @@ function facebook() {
|
|
|
62
62
|
email_verified: data.email_verified
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
|
+
},
|
|
66
|
+
async loginOAuth2Native({ credentials }) {
|
|
67
|
+
if (credentials.id_token || credentials.access_token) {
|
|
68
|
+
const userInfo = await this.getUserInfo(credentials);
|
|
69
|
+
const token = {
|
|
70
|
+
token_type: "bearer",
|
|
71
|
+
access_token: credentials.access_token ?? "",
|
|
72
|
+
id_token: credentials.id_token
|
|
73
|
+
};
|
|
74
|
+
return { token, userInfo };
|
|
75
|
+
} else {
|
|
76
|
+
throw new OAuth2Error(400, "invalid_request", "id_token or access_token is required");
|
|
77
|
+
}
|
|
65
78
|
}
|
|
66
79
|
};
|
|
67
80
|
}
|
|
81
|
+
var facebook = createFacebookProvider();
|
|
68
82
|
export {
|
|
83
|
+
createFacebookProvider,
|
|
69
84
|
facebook
|
|
70
85
|
};
|
|
71
86
|
//# sourceMappingURL=facebook.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth2/provider/facebook.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from './common';\n\n/**\n * ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/\n * ref: https://developers.facebook.com/tools/explorer\n * */\nexport function
|
|
1
|
+
{"version":3,"sources":["../../../src/oauth2/provider/facebook.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { LoginOAuth2NativeParams, OAuth2Token, Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from './common';\n\n/**\n * ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/\n * ref: https://developers.facebook.com/tools/explorer\n * */\nexport function createFacebookProvider(): Provider {\n return {\n authorizationUri: 'https://www.facebook.com/v21.0/dialog/oauth',\n tokenUri: 'https://graph.facebook.com/v19.0/oauth/access_token',\n userInfoUri: 'https://graph.facebook.com/me',\n jwkSetUri: 'https://limited.facebook.com/.well-known/oauth/openid/jwks/',\n userNameAttribute: 'id',\n defaultScope: ['profile', 'email'],\n createAuthorizationUri({ pkce, ...params }) {\n return createAuthorizationUri({\n ...params,\n scope: params.scope ?? this.defaultScope,\n authorizationUri: this.authorizationUri,\n });\n },\n async exchangeAuthorizationCode({ pkce, ...params }) {\n const response = await exchangeAuthorizationCode({ ...params, tokenUri: this.tokenUri });\n if (!response.ok) {\n const { error } = (await response.json()) as FacebookErrorResponse;\n throw new OAuth2Error(response.status, 'invalid_request', error.message);\n }\n return (await response.json()) as FacebookToken;\n },\n async getUserInfo({ id_token, access_token }) {\n invariant(this.jwkSetUri, 'jwkSetUri is required');\n if (id_token) {\n const data = await verifyIdToken<FacebookDecodedIdToken>(id_token, this.jwkSetUri);\n return {\n data,\n claims: {\n sub: data.sub,\n name: data.name,\n picture: data.picture,\n email: data.email,\n email_verified: true,\n },\n };\n }\n invariant(access_token, 'access_token is required');\n invariant(this.userInfoUri, 'userInfoUri is required');\n\n const url = new URL(this.userInfoUri);\n const fields = ['id', 'name', 'email', 'picture.width(320).height(320)'];\n url.searchParams.append('access_token', access_token);\n url.searchParams.append('fields', fields.join(','));\n const headers = { Accept: 'application/json' };\n const response = await fetch(url.href, { headers });\n if (!response.ok) {\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to fetch user info');\n }\n const data = (await response.json()) as FacebookUserInfo;\n return {\n data,\n claims: {\n sub: data.id,\n name: data.name,\n email: data.email,\n picture: data.picture.data.url,\n email_verified: data.email_verified,\n },\n };\n },\n async loginOAuth2Native({ credentials }: LoginOAuth2NativeParams) {\n if (credentials.id_token || credentials.access_token) {\n const userInfo = await this.getUserInfo(credentials as unknown as OAuth2Token);\n const token: OAuth2Token = {\n token_type: 'bearer',\n access_token: credentials.access_token ?? '',\n id_token: credentials.id_token,\n };\n return { token, userInfo };\n } else {\n throw new OAuth2Error(400, 'invalid_request', 'id_token or access_token is required');\n }\n },\n };\n}\n\nexport const facebook = createFacebookProvider();\n\nexport interface FacebookDecodedIdToken {\n sub: string;\n name: string;\n email: string;\n picture: string;\n}\n\nexport interface FacebookUserInfo {\n id: string;\n name: string;\n email: string;\n email_verified: boolean;\n picture: {\n data: {\n url: string;\n width: number;\n height: number;\n is_silhouette: boolean;\n };\n };\n}\n\nexport interface FacebookToken extends OAuth2Token {\n access_token: string;\n token_type: 'bearer';\n expires_in: number;\n id_token?: string;\n}\n\nexport type FacebookAppCredentials =\n | { state: string; id_token: string } // platform=ios and tracking=limited\n | { state: string; access_token: string }; // tracking=enabled\n\ninterface FacebookErrorResponse {\n error: {\n message: string;\n type: 'OAuthException';\n code: number;\n error_subcode: number;\n fbtrace_id: string;\n };\n}\n"],"mappings":";AAAA,OAAO,eAAe;AAEtB,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB,2BAA2B,qBAAqB;AAM1E,SAAS,yBAAmC;AACjD,SAAO;AAAA,IACL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,cAAc,CAAC,WAAW,OAAO;AAAA,IACjC,uBAAuB,EAAE,MAAM,GAAG,OAAO,GAAG;AAC1C,aAAO,uBAAuB;AAAA,QAC5B,GAAG;AAAA,QACH,OAAO,OAAO,SAAS,KAAK;AAAA,QAC5B,kBAAkB,KAAK;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,IACA,MAAM,0BAA0B,EAAE,MAAM,GAAG,OAAO,GAAG;AACnD,YAAM,WAAW,MAAM,0BAA0B,EAAE,GAAG,QAAQ,UAAU,KAAK,SAAS,CAAC;AACvF,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,EAAE,MAAM,IAAK,MAAM,SAAS,KAAK;AACvC,cAAM,IAAI,YAAY,SAAS,QAAQ,mBAAmB,MAAM,OAAO;AAAA,MACzE;AACA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAAA,IACA,MAAM,YAAY,EAAE,UAAU,aAAa,GAAG;AAC5C,gBAAU,KAAK,WAAW,uBAAuB;AACjD,UAAI,UAAU;AACZ,cAAMA,QAAO,MAAM,cAAsC,UAAU,KAAK,SAAS;AACjF,eAAO;AAAA,UACL,MAAAA;AAAA,UACA,QAAQ;AAAA,YACN,KAAKA,MAAK;AAAA,YACV,MAAMA,MAAK;AAAA,YACX,SAASA,MAAK;AAAA,YACd,OAAOA,MAAK;AAAA,YACZ,gBAAgB;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AACA,gBAAU,cAAc,0BAA0B;AAClD,gBAAU,KAAK,aAAa,yBAAyB;AAErD,YAAM,MAAM,IAAI,IAAI,KAAK,WAAW;AACpC,YAAM,SAAS,CAAC,MAAM,QAAQ,SAAS,gCAAgC;AACvE,UAAI,aAAa,OAAO,gBAAgB,YAAY;AACpD,UAAI,aAAa,OAAO,UAAU,OAAO,KAAK,GAAG,CAAC;AAClD,YAAM,UAAU,EAAE,QAAQ,mBAAmB;AAC7C,YAAM,WAAW,MAAM,MAAM,IAAI,MAAM,EAAE,QAAQ,CAAC;AAClD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,YAAY,SAAS,QAAQ,mBAAmB,2BAA2B;AAAA,MACvF;AACA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,UACN,KAAK,KAAK;AAAA,UACV,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK,QAAQ,KAAK;AAAA,UAC3B,gBAAgB,KAAK;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM,kBAAkB,EAAE,YAAY,GAA4B;AAChE,UAAI,YAAY,YAAY,YAAY,cAAc;AACpD,cAAM,WAAW,MAAM,KAAK,YAAY,WAAqC;AAC7E,cAAM,QAAqB;AAAA,UACzB,YAAY;AAAA,UACZ,cAAc,YAAY,gBAAgB;AAAA,UAC1C,UAAU,YAAY;AAAA,QACxB;AACA,eAAO,EAAE,OAAO,SAAS;AAAA,MAC3B,OAAO;AACL,cAAM,IAAI,YAAY,KAAK,mBAAmB,sCAAsC;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,WAAW,uBAAuB;","names":["data"]}
|
|
@@ -30,27 +30,28 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/oauth2/provider/github.ts
|
|
31
31
|
var github_exports = {};
|
|
32
32
|
__export(github_exports, {
|
|
33
|
+
createGithubProvider: () => createGithubProvider,
|
|
33
34
|
github: () => github
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(github_exports);
|
|
36
37
|
var import_tiny_invariant = __toESM(require("tiny-invariant"), 1);
|
|
37
38
|
var import_error = require("../error.cjs");
|
|
38
39
|
var import_common = require("./common.cjs");
|
|
39
|
-
function
|
|
40
|
+
function createGithubProvider() {
|
|
40
41
|
return {
|
|
41
42
|
authorizationUri: "https://github.com/login/oauth/authorize",
|
|
42
43
|
tokenUri: "https://github.com/login/oauth/access_token",
|
|
43
44
|
userInfoUri: "https://api.github.com/user",
|
|
44
45
|
userNameAttribute: "id",
|
|
45
46
|
defaultScope: ["user:email"],
|
|
46
|
-
createAuthorizationUri({
|
|
47
|
+
createAuthorizationUri({ pkce, ...params }) {
|
|
47
48
|
return (0, import_common.createAuthorizationUri)({
|
|
48
49
|
...params,
|
|
49
50
|
scope: params.scope ?? this.defaultScope,
|
|
50
51
|
authorizationUri: this.authorizationUri
|
|
51
52
|
});
|
|
52
53
|
},
|
|
53
|
-
async exchangeAuthorizationCode({
|
|
54
|
+
async exchangeAuthorizationCode({ pkce, ...params }) {
|
|
54
55
|
const response = await (0, import_common.exchangeAuthorizationCode)({ ...params, tokenUri: this.tokenUri });
|
|
55
56
|
if (!response.ok) {
|
|
56
57
|
const { error, error_description } = await response.json();
|
|
@@ -94,8 +95,10 @@ function github() {
|
|
|
94
95
|
}
|
|
95
96
|
};
|
|
96
97
|
}
|
|
98
|
+
var github = createGithubProvider();
|
|
97
99
|
// Annotate the CommonJS export names for ESM import in node:
|
|
98
100
|
0 && (module.exports = {
|
|
101
|
+
createGithubProvider,
|
|
99
102
|
github
|
|
100
103
|
});
|
|
101
104
|
//# sourceMappingURL=github.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth2/provider/github.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode } from './common';\n\nexport function
|
|
1
|
+
{"version":3,"sources":["../../../src/oauth2/provider/github.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { OAuth2Token, Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode } from './common';\n\nexport function createGithubProvider(): Provider {\n return {\n authorizationUri: 'https://github.com/login/oauth/authorize',\n tokenUri: 'https://github.com/login/oauth/access_token',\n userInfoUri: 'https://api.github.com/user',\n userNameAttribute: 'id',\n defaultScope: ['user:email'],\n createAuthorizationUri({ pkce, ...params }) {\n return createAuthorizationUri({\n ...params,\n scope: params.scope ?? this.defaultScope,\n authorizationUri: this.authorizationUri,\n });\n },\n async exchangeAuthorizationCode({ pkce, ...params }) {\n const response = await exchangeAuthorizationCode({ ...params, tokenUri: this.tokenUri });\n if (!response.ok) {\n const { error, error_description } = (await response.json()) as GithubErrorResponse;\n throw new OAuth2Error(response.status, error, error_description);\n }\n return (await response.json()) as GithubToken;\n },\n async getUserInfo({ access_token }) {\n invariant(access_token, 'access_token is required');\n invariant(this.userInfoUri, 'userInfoUri is required');\n const headers = { Accept: 'application/json', Authorization: `Bearer ${access_token}` };\n const response = await fetch(this.userInfoUri, { headers });\n if (!response.ok) {\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to fetch user info');\n }\n const data = (await response.json()) as GithubUserInfo;\n const emailResponse = await fetch('https://api.github.com/user/emails', { headers });\n if (!emailResponse.ok) {\n throw new OAuth2Error(\n emailResponse.status,\n 'invalid_request',\n 'Failed to fetch user email'\n );\n }\n const emails = (await emailResponse.json()) as GithubEmail[];\n data.email = emails.find((email) => email.primary)?.email || data.email;\n const email_verified = emails.find((email) => email.email === data.email)?.verified || false;\n return {\n data,\n claims: {\n sub: data.id,\n name: data.name || data.login,\n email_verified,\n email: data.email,\n picture: data.avatar_url,\n profile: data.html_url,\n website: data.html_url,\n updated_at: data.updated_at ? Date.parse(data.updated_at) : undefined,\n },\n };\n },\n };\n}\n\nexport const github = createGithubProvider();\n\nexport interface GithubUserInfo {\n login: string;\n id: string;\n node_id: string;\n avatar_url: string;\n gravatar_id: string;\n url: string;\n html_url: string;\n followers_url: string;\n following_url: string;\n gists_url: string;\n starred_url: string;\n subscriptions_url: string;\n organizations_url: string;\n repos_url: string;\n events_url: string;\n received_events_url: string;\n type: string;\n site_admin: boolean;\n name: string;\n company: string;\n blog: string;\n location: string;\n email: string;\n hireable: boolean;\n bio: string;\n twitter_username: string;\n public_repos: string;\n public_gists: string;\n followers: string;\n following: string;\n created_at: string;\n updated_at: string;\n private_gists: string;\n total_private_repos: string;\n owned_private_repos: string;\n disk_usage: string;\n collaborators: string;\n two_factor_authentication: boolean;\n plan: {\n name: string;\n space: string;\n private_repos: string;\n collaborators: string;\n };\n}\n\ninterface GithubEmail {\n email: string;\n primary: boolean;\n verified: boolean;\n visibility: 'public' | 'private';\n}\n\nexport interface GithubToken extends OAuth2Token {\n access_token: string;\n token_type: string;\n scope: string;\n expires_in: number;\n refresh_token: string;\n}\n\ninterface GithubErrorResponse {\n error: string;\n error_description: string;\n error_uri: string;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAsB;AAEtB,mBAA4B;AAC5B,oBAAkE;AAE3D,SAAS,uBAAiC;AAC/C,SAAO;AAAA,IACL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,cAAc,CAAC,YAAY;AAAA,IAC3B,uBAAuB,EAAE,MAAM,GAAG,OAAO,GAAG;AAC1C,iBAAO,sCAAuB;AAAA,QAC5B,GAAG;AAAA,QACH,OAAO,OAAO,SAAS,KAAK;AAAA,QAC5B,kBAAkB,KAAK;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,IACA,MAAM,0BAA0B,EAAE,MAAM,GAAG,OAAO,GAAG;AACnD,YAAM,WAAW,UAAM,yCAA0B,EAAE,GAAG,QAAQ,UAAU,KAAK,SAAS,CAAC;AACvF,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,EAAE,OAAO,kBAAkB,IAAK,MAAM,SAAS,KAAK;AAC1D,cAAM,IAAI,yBAAY,SAAS,QAAQ,OAAO,iBAAiB;AAAA,MACjE;AACA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAAA,IACA,MAAM,YAAY,EAAE,aAAa,GAAG;AAClC,gCAAAA,SAAU,cAAc,0BAA0B;AAClD,gCAAAA,SAAU,KAAK,aAAa,yBAAyB;AACrD,YAAM,UAAU,EAAE,QAAQ,oBAAoB,eAAe,UAAU,YAAY,GAAG;AACtF,YAAM,WAAW,MAAM,MAAM,KAAK,aAAa,EAAE,QAAQ,CAAC;AAC1D,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,yBAAY,SAAS,QAAQ,mBAAmB,2BAA2B;AAAA,MACvF;AACA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,YAAM,gBAAgB,MAAM,MAAM,sCAAsC,EAAE,QAAQ,CAAC;AACnF,UAAI,CAAC,cAAc,IAAI;AACrB,cAAM,IAAI;AAAA,UACR,cAAc;AAAA,UACd;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,YAAM,SAAU,MAAM,cAAc,KAAK;AACzC,WAAK,QAAQ,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,GAAG,SAAS,KAAK;AAClE,YAAM,iBAAiB,OAAO,KAAK,CAAC,UAAU,MAAM,UAAU,KAAK,KAAK,GAAG,YAAY;AACvF,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,UACN,KAAK,KAAK;AAAA,UACV,MAAM,KAAK,QAAQ,KAAK;AAAA,UACxB;AAAA,UACA,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK;AAAA,UACd,SAAS,KAAK;AAAA,UACd,SAAS,KAAK;AAAA,UACd,YAAY,KAAK,aAAa,KAAK,MAAM,KAAK,UAAU,IAAI;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,SAAS,qBAAqB;","names":["invariant"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Provider } from '../types.cjs';
|
|
1
|
+
import { Provider, OAuth2Token } from '../types.cjs';
|
|
2
2
|
|
|
3
|
-
declare function
|
|
3
|
+
declare function createGithubProvider(): Provider;
|
|
4
|
+
declare const github: Provider;
|
|
4
5
|
interface GithubUserInfo {
|
|
5
6
|
login: string;
|
|
6
7
|
id: string;
|
|
@@ -47,5 +48,12 @@ interface GithubUserInfo {
|
|
|
47
48
|
collaborators: string;
|
|
48
49
|
};
|
|
49
50
|
}
|
|
51
|
+
interface GithubToken extends OAuth2Token {
|
|
52
|
+
access_token: string;
|
|
53
|
+
token_type: string;
|
|
54
|
+
scope: string;
|
|
55
|
+
expires_in: number;
|
|
56
|
+
refresh_token: string;
|
|
57
|
+
}
|
|
50
58
|
|
|
51
|
-
export { type GithubUserInfo, github };
|
|
59
|
+
export { type GithubToken, type GithubUserInfo, createGithubProvider, github };
|