@strapi/plugin-users-permissions 5.50.1 → 5.51.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/admin/src/pages/Roles/pages/EditPage.jsx +1 -1
- package/admin/src/translations/en.json +2 -0
- package/admin/src/translations/ko.json +2 -1
- package/dist/admin/pages/Roles/pages/EditPage.js +1 -1
- package/dist/admin/pages/Roles/pages/EditPage.js.map +1 -1
- package/dist/admin/pages/Roles/pages/EditPage.mjs +1 -1
- package/dist/admin/pages/Roles/pages/EditPage.mjs.map +1 -1
- package/dist/admin/translations/en.json.js +1 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +1 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/translations/ko.json.js +2 -1
- package/dist/admin/translations/ko.json.js.map +1 -1
- package/dist/admin/translations/ko.json.mjs +2 -1
- package/dist/admin/translations/ko.json.mjs.map +1 -1
- package/dist/server/_virtual/_node_crypto.js +10 -0
- package/dist/server/_virtual/_node_crypto.js.map +1 -0
- package/dist/server/_virtual/_node_crypto.mjs +7 -0
- package/dist/server/_virtual/_node_crypto.mjs.map +1 -0
- package/dist/server/_virtual/_node_url.js +10 -0
- package/dist/server/_virtual/_node_url.js.map +1 -0
- package/dist/server/_virtual/_node_url.mjs +7 -0
- package/dist/server/_virtual/_node_url.mjs.map +1 -0
- package/dist/server/controllers/auth.js +19 -19
- package/dist/server/controllers/auth.js.map +1 -1
- package/dist/server/controllers/auth.mjs +19 -18
- package/dist/server/controllers/auth.mjs.map +1 -1
- package/dist/server/services/providers-registry.js +121 -242
- package/dist/server/services/providers-registry.js.map +1 -1
- package/dist/server/services/providers-registry.mjs +121 -239
- package/dist/server/services/providers-registry.mjs.map +1 -1
- package/dist/server/utils/oauth-connect/index.js +236 -0
- package/dist/server/utils/oauth-connect/index.js.map +1 -0
- package/dist/server/utils/oauth-connect/index.mjs +230 -0
- package/dist/server/utils/oauth-connect/index.mjs.map +1 -0
- package/dist/server/utils/oauth-connect/oauth1.js +138 -0
- package/dist/server/utils/oauth-connect/oauth1.js.map +1 -0
- package/dist/server/utils/oauth-connect/oauth1.mjs +136 -0
- package/dist/server/utils/oauth-connect/oauth1.mjs.map +1 -0
- package/dist/server/utils/oauth-connect/oauth2.js +117 -0
- package/dist/server/utils/oauth-connect/oauth2.js.map +1 -0
- package/dist/server/utils/oauth-connect/oauth2.mjs +115 -0
- package/dist/server/utils/oauth-connect/oauth2.mjs.map +1 -0
- package/dist/server/utils/oauth-connect/providers.js +109 -0
- package/dist/server/utils/oauth-connect/providers.js.map +1 -0
- package/dist/server/utils/oauth-connect/providers.mjs +107 -0
- package/dist/server/utils/oauth-connect/providers.mjs.map +1 -0
- package/dist/server/utils/provider-http.js +52 -0
- package/dist/server/utils/provider-http.js.map +1 -0
- package/dist/server/utils/provider-http.mjs +50 -0
- package/dist/server/utils/provider-http.mjs.map +1 -0
- package/dist/server/utils/verify-jwt-with-jwks.js +60 -0
- package/dist/server/utils/verify-jwt-with-jwks.js.map +1 -0
- package/dist/server/utils/verify-jwt-with-jwks.mjs +54 -0
- package/dist/server/utils/verify-jwt-with-jwks.mjs.map +1 -0
- package/jsconfig.json +7 -0
- package/package.json +12 -12
- package/server/controllers/auth.js +13 -20
- package/server/services/providers-registry.js +137 -293
- package/server/utils/oauth-connect/index.js +256 -0
- package/server/utils/oauth-connect/oauth1.js +169 -0
- package/server/utils/oauth-connect/oauth2.js +123 -0
- package/server/utils/oauth-connect/providers.js +100 -0
- package/server/utils/provider-http.js +49 -0
- package/server/utils/verify-jwt-with-jwks.js +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../server/utils/oauth-connect/index.js"],"sourcesContent":["'use strict';\n\nconst { errors } = require('@strapi/utils');\n\nconst builtinProviderEndpoints = require('./providers');\nconst oauth1 = require('./oauth1');\nconst oauth2 = require('./oauth2');\n\nconst CONNECT_PREFIX = '/connect';\n\nconst parseConnectPath = (requestPath, apiPrefix) => {\n const prefix = `${apiPrefix}${CONNECT_PREFIX}/`;\n if (!requestPath.startsWith(prefix)) {\n return null;\n }\n\n const remainder = requestPath.slice(prefix.length);\n const [provider, segment] = remainder.split('/').filter(Boolean);\n\n if (!provider) {\n return null;\n }\n\n return {\n provider,\n isCallback: segment === 'callback',\n };\n};\n\n/**\n * Resolve OAuth endpoint config from built-ins, falling back to store-defined\n * endpoints so custom providers registered via providers-registry still work.\n */\nconst buildProviderConfig = (providerName, storedConfig, redirectUri) => {\n const defaults = builtinProviderEndpoints[providerName];\n const endpoints = defaults || {\n oauth: storedConfig.oauth,\n authorize_url: storedConfig.authorize_url,\n access_url: storedConfig.access_url,\n request_url: storedConfig.request_url,\n scope_delimiter: storedConfig.scope_delimiter,\n token_endpoint_auth_method: storedConfig.token_endpoint_auth_method,\n };\n\n if (endpoints.oauth === 1) {\n if (!endpoints.request_url || !endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n } else if (!endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n\n return {\n name: providerName,\n ...endpoints,\n key: storedConfig.key,\n secret: storedConfig.secret,\n scope: storedConfig.scope,\n subdomain: storedConfig.subdomain,\n callback: storedConfig.callback,\n redirect_uri: redirectUri,\n };\n};\n\nconst redirectWithPayload = (ctx, callbackUrl, payload) => {\n const url = new URL(callbackUrl);\n const params = new URLSearchParams();\n\n Object.entries(payload).forEach(([key, value]) => {\n if (key === 'raw') {\n Object.entries(value).forEach(([rawKey, rawValue]) => {\n params.set(`raw[${rawKey}]`, String(rawValue));\n });\n return;\n }\n if (value !== undefined && value !== null) {\n params.set(key, String(value));\n }\n });\n\n url.search = params.toString();\n ctx.redirect(url.toString());\n};\n\nconst preserveGrantDynamic = (ctx) => {\n const dynamic = ctx.session.grant?.dynamic;\n return dynamic ? { dynamic } : {};\n};\n\nconst startOAuth1Flow = async (ctx, provider, parsed, redirectUri) => {\n const requestToken = await oauth1.requestToken({\n requestUrl: provider.request_url,\n redirectUri,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n });\n\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n request: requestToken,\n };\n\n const authorizeUrl = `${provider.authorize_url}?oauth_token=${encodeURIComponent(requestToken.oauth_token)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst startOAuth2Flow = (ctx, provider, parsed, redirectUri) => {\n const state = oauth2.generateState();\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n state,\n };\n\n let authorizeUrl = oauth2.buildAuthorizeUrl(provider, {\n key: provider.key,\n redirectUri,\n scope: provider.scope,\n subdomain: provider.subdomain,\n });\n\n authorizeUrl += `&state=${encodeURIComponent(state)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst handleOAuth1Callback = async (ctx, provider, callbackUrl) => {\n const session = ctx.session.grant || {};\n const { oauth_token: oauthToken, oauth_verifier: oauthVerifier } = ctx.query;\n const requestToken = session.request;\n\n if (!requestToken?.oauth_token || oauthToken !== requestToken.oauth_token) {\n throw new Error('OAuth1 token mismatch');\n }\n\n const tokenResponse = await oauth1.accessToken({\n accessUrl: provider.access_url,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n oauthToken,\n oauthVerifier,\n oauthTokenCredential: requestToken.oauth_token_secret,\n });\n\n const payload = oauth2.tokensToQueryPayload(provider, tokenResponse);\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, payload);\n};\n\nconst handleOAuth2Callback = async (ctx, provider, callbackUrl, redirectUri) => {\n const session = ctx.session.grant || {};\n const { code, state: queryState, error, error_description: errorDescription } = ctx.query;\n\n if (error) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error,\n error_description: errorDescription,\n });\n }\n\n if (!code) {\n throw new Error('OAuth2 missing code parameter');\n }\n\n // Reject when session state is missing (not only on mismatch) to close login-CSRF.\n if (!session.state || queryState !== session.state) {\n throw new Error('OAuth2 state mismatch');\n }\n\n const tokenResponse = await oauth2.exchangeAuthorizationCode(provider, {\n key: provider.key,\n secret: provider.secret,\n redirectUri,\n code,\n subdomain: provider.subdomain,\n });\n\n const payload = oauth2.tokensToQueryPayload(provider, tokenResponse);\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, payload);\n};\n\nconst createOAuthConnectMiddleware = () => {\n return async (ctx, next) => {\n const apiPrefix = strapi.config.get('api.rest.prefix');\n const [requestPath] = ctx.request.url.split('?');\n const parsed = parseConnectPath(requestPath, apiPrefix);\n\n if (!parsed) {\n return next();\n }\n\n if (!ctx.session) {\n ctx.throw(400, 'OAuth connect requires session middleware');\n }\n\n const storedProviders = await strapi\n .store({ type: 'plugin', name: 'users-permissions', key: 'grant' })\n .get();\n\n const storedConfig = storedProviders?.[parsed.provider];\n if (!storedConfig?.enabled) {\n throw new errors.ApplicationError('This provider is disabled');\n }\n\n const { getService } = require('..');\n const redirectUri = getService('providers').buildRedirectUri(parsed.provider);\n\n const callbackOverride =\n ctx.state.oauthConnect?.callback ?? ctx.session.grant?.dynamic?.callback;\n const effectiveConfig = callbackOverride\n ? { ...storedConfig, callback: callbackOverride }\n : storedConfig;\n\n const provider = buildProviderConfig(parsed.provider, effectiveConfig, redirectUri);\n\n if (!provider) {\n throw new errors.ApplicationError('Unknown OAuth provider');\n }\n\n ctx.session.grant = ctx.session.grant || {};\n\n if (!parsed.isCallback) {\n if (provider.oauth === 1) {\n return startOAuth1Flow(ctx, provider, parsed, redirectUri);\n }\n return startOAuth2Flow(ctx, provider, parsed, redirectUri);\n }\n\n const callbackUrl = effectiveConfig.callback;\n if (!callbackUrl) {\n throw new errors.ApplicationError('Provider callback URL is not configured');\n }\n\n try {\n if (provider.oauth === 1) {\n return await handleOAuth1Callback(ctx, provider, callbackUrl);\n }\n return await handleOAuth2Callback(ctx, provider, callbackUrl, redirectUri);\n } catch (err) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error: 'oauth_error',\n error_description: err.message,\n });\n }\n };\n};\n\nmodule.exports = {\n createOAuthConnectMiddleware,\n parseConnectPath,\n buildProviderConfig,\n redirectWithPayload,\n};\n"],"names":["errors","require$$0","builtinProviderEndpoints","require$$1","oauth1","require$$2","oauth2","require$$3","CONNECT_PREFIX","parseConnectPath","requestPath","apiPrefix","prefix","startsWith","remainder","slice","length","provider","segment","split","filter","Boolean","isCallback","buildProviderConfig","providerName","storedConfig","redirectUri","defaults","endpoints","oauth","authorize_url","access_url","request_url","scope_delimiter","token_endpoint_auth_method","name","key","secret","scope","subdomain","callback","redirect_uri","redirectWithPayload","ctx","callbackUrl","payload","url","URL","params","URLSearchParams","Object","entries","forEach","value","rawKey","rawValue","set","String","undefined","search","toString","redirect","preserveGrantDynamic","dynamic","session","grant","startOAuth1Flow","parsed","requestToken","requestUrl","consumerKey","clientCredential","request","authorizeUrl","encodeURIComponent","oauth_token","startOAuth2Flow","state","generateState","buildAuthorizeUrl","handleOAuth1Callback","oauthToken","oauth_verifier","oauthVerifier","query","Error","tokenResponse","accessToken","accessUrl","oauthTokenCredential","oauth_token_secret","tokensToQueryPayload","handleOAuth2Callback","code","queryState","error","error_description","errorDescription","exchangeAuthorizationCode","createOAuthConnectMiddleware","next","strapi","config","get","throw","storedProviders","store","type","enabled","ApplicationError","getService","require$$4","buildRedirectUri","callbackOverride","oauthConnect","effectiveConfig","err","message"],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _node_crypto_commonjsExternal = require('../../_virtual/_node_crypto.js');
|
|
4
|
+
var _node_url_commonjsExternal = require('../../_virtual/_node_url.js');
|
|
5
|
+
|
|
6
|
+
var oauth1;
|
|
7
|
+
var hasRequiredOauth1;
|
|
8
|
+
function requireOauth1() {
|
|
9
|
+
if (hasRequiredOauth1) return oauth1;
|
|
10
|
+
hasRequiredOauth1 = 1;
|
|
11
|
+
const crypto = _node_crypto_commonjsExternal.__require();
|
|
12
|
+
const { URLSearchParams } = _node_url_commonjsExternal.__require();
|
|
13
|
+
const encode = (str)=>encodeURIComponent(str).replace(/[!'()*]/g, (c)=>`%${c.codePointAt(0).toString(16).toUpperCase()}`);
|
|
14
|
+
const sortKeys = (keys)=>keys.sort((a, b)=>{
|
|
15
|
+
if (a < b) return -1;
|
|
16
|
+
if (a > b) return 1;
|
|
17
|
+
return 0;
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* OAuth 1.0 (RFC 5849) request signature — HMAC-SHA1 is required by the protocol.
|
|
21
|
+
* This is not password storage or user-credential hashing (those use bcrypt).
|
|
22
|
+
*/ const signRfc5849BaseString = (signatureBaseString, signingMaterial)=>{
|
|
23
|
+
// codeql[js/insufficient-password-hash] OAuth 1.0 signing material, not user password storage
|
|
24
|
+
return crypto.createHmac('sha1', signingMaterial).update(signatureBaseString).digest('base64');
|
|
25
|
+
};
|
|
26
|
+
const buildOAuth1Header = ({ method, url, params, consumerKey, clientCredential, token, tokenCredential })=>{
|
|
27
|
+
const requestParameters = {
|
|
28
|
+
oauth_consumer_key: consumerKey,
|
|
29
|
+
oauth_nonce: crypto.randomBytes(16).toString('hex'),
|
|
30
|
+
oauth_signature_method: 'HMAC-SHA1',
|
|
31
|
+
oauth_timestamp: Math.floor(Date.now() / 1000).toString(),
|
|
32
|
+
oauth_version: '1.0',
|
|
33
|
+
...token ? {
|
|
34
|
+
oauth_token: token
|
|
35
|
+
} : {},
|
|
36
|
+
...params
|
|
37
|
+
};
|
|
38
|
+
const paramString = sortKeys(Object.keys(requestParameters)).map((key)=>`${encode(key)}=${encode(requestParameters[key])}`).join('&');
|
|
39
|
+
const signatureBaseString = [
|
|
40
|
+
method.toUpperCase(),
|
|
41
|
+
encode(url),
|
|
42
|
+
encode(paramString)
|
|
43
|
+
].join('&');
|
|
44
|
+
const signingMaterial = `${encode(clientCredential)}&${encode(tokenCredential || '')}`;
|
|
45
|
+
const signature = signRfc5849BaseString(signatureBaseString, signingMaterial);
|
|
46
|
+
const headerParameters = {
|
|
47
|
+
...requestParameters,
|
|
48
|
+
oauth_signature: signature
|
|
49
|
+
};
|
|
50
|
+
const header = `OAuth ${sortKeys(Object.keys(headerParameters)).map((key)=>`${encode(key)}="${encode(headerParameters[key])}"`).join(', ')}`;
|
|
51
|
+
return header;
|
|
52
|
+
};
|
|
53
|
+
const oauth1Request = async ({ method, url, consumerKey, clientCredential, token, tokenCredential, params = {} })=>{
|
|
54
|
+
const authorization = buildOAuth1Header({
|
|
55
|
+
method,
|
|
56
|
+
url,
|
|
57
|
+
params,
|
|
58
|
+
consumerKey,
|
|
59
|
+
clientCredential,
|
|
60
|
+
token,
|
|
61
|
+
tokenCredential
|
|
62
|
+
});
|
|
63
|
+
const response = await fetch(url, {
|
|
64
|
+
method,
|
|
65
|
+
headers: {
|
|
66
|
+
Authorization: authorization
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const text = await response.text();
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
throw new Error(text || `OAuth1 request failed (${response.status})`);
|
|
72
|
+
}
|
|
73
|
+
return Object.fromEntries(new URLSearchParams(text));
|
|
74
|
+
};
|
|
75
|
+
const requestToken = async ({ requestUrl, redirectUri, consumerKey, clientCredential })=>oauth1Request({
|
|
76
|
+
method: 'POST',
|
|
77
|
+
url: requestUrl,
|
|
78
|
+
consumerKey,
|
|
79
|
+
clientCredential,
|
|
80
|
+
params: {
|
|
81
|
+
oauth_callback: redirectUri
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
const accessToken = async ({ accessUrl, consumerKey, clientCredential, oauthToken, oauthVerifier, oauthTokenCredential })=>oauth1Request({
|
|
85
|
+
method: 'POST',
|
|
86
|
+
url: accessUrl,
|
|
87
|
+
consumerKey,
|
|
88
|
+
clientCredential,
|
|
89
|
+
token: oauthToken,
|
|
90
|
+
tokenCredential: oauthTokenCredential,
|
|
91
|
+
params: {
|
|
92
|
+
oauth_verifier: oauthVerifier
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
const twitterGet = async ({ url, accessToken, accessCredential, consumerKey, clientCredential, qs = {} })=>{
|
|
96
|
+
const target = new URL(url);
|
|
97
|
+
const signedParams = {};
|
|
98
|
+
Object.entries(qs).forEach(([key, value])=>{
|
|
99
|
+
if (value !== undefined && value !== null) {
|
|
100
|
+
const stringValue = String(value);
|
|
101
|
+
target.searchParams.set(key, stringValue);
|
|
102
|
+
// RFC 5849 §3.4.1: base-string URI excludes the query; params are signed separately.
|
|
103
|
+
signedParams[key] = stringValue;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
const authorization = buildOAuth1Header({
|
|
107
|
+
method: 'GET',
|
|
108
|
+
url: target.origin + target.pathname,
|
|
109
|
+
params: signedParams,
|
|
110
|
+
consumerKey,
|
|
111
|
+
clientCredential,
|
|
112
|
+
token: accessToken,
|
|
113
|
+
tokenCredential: accessCredential
|
|
114
|
+
});
|
|
115
|
+
const response = await fetch(target, {
|
|
116
|
+
headers: {
|
|
117
|
+
Authorization: authorization
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
const body = await response.json();
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
throw new Error(body.errors?.[0]?.message || `Twitter API error (${response.status})`);
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
body
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
oauth1 = {
|
|
129
|
+
buildOAuth1Header,
|
|
130
|
+
requestToken,
|
|
131
|
+
accessToken,
|
|
132
|
+
twitterGet
|
|
133
|
+
};
|
|
134
|
+
return oauth1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
exports.__require = requireOauth1;
|
|
138
|
+
//# sourceMappingURL=oauth1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth1.js","sources":["../../../../server/utils/oauth-connect/oauth1.js"],"sourcesContent":["'use strict';\n\nconst crypto = require('node:crypto');\nconst { URLSearchParams } = require('node:url');\n\nconst encode = (str) =>\n encodeURIComponent(str).replace(\n /[!'()*]/g,\n (c) => `%${c.codePointAt(0).toString(16).toUpperCase()}`\n );\n\nconst sortKeys = (keys) =>\n keys.sort((a, b) => {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n });\n\n/**\n * OAuth 1.0 (RFC 5849) request signature — HMAC-SHA1 is required by the protocol.\n * This is not password storage or user-credential hashing (those use bcrypt).\n */\nconst signRfc5849BaseString = (signatureBaseString, signingMaterial) => {\n // codeql[js/insufficient-password-hash] OAuth 1.0 signing material, not user password storage\n return crypto.createHmac('sha1', signingMaterial).update(signatureBaseString).digest('base64');\n};\n\nconst buildOAuth1Header = ({\n method,\n url,\n params,\n consumerKey,\n clientCredential,\n token,\n tokenCredential,\n}) => {\n const requestParameters = {\n oauth_consumer_key: consumerKey,\n oauth_nonce: crypto.randomBytes(16).toString('hex'),\n oauth_signature_method: 'HMAC-SHA1',\n oauth_timestamp: Math.floor(Date.now() / 1000).toString(),\n oauth_version: '1.0',\n ...(token ? { oauth_token: token } : {}),\n ...params,\n };\n\n const paramString = sortKeys(Object.keys(requestParameters))\n .map((key) => `${encode(key)}=${encode(requestParameters[key])}`)\n .join('&');\n\n const signatureBaseString = [method.toUpperCase(), encode(url), encode(paramString)].join('&');\n const signingMaterial = `${encode(clientCredential)}&${encode(tokenCredential || '')}`;\n const signature = signRfc5849BaseString(signatureBaseString, signingMaterial);\n\n const headerParameters = { ...requestParameters, oauth_signature: signature };\n const header = `OAuth ${sortKeys(Object.keys(headerParameters))\n .map((key) => `${encode(key)}=\"${encode(headerParameters[key])}\"`)\n .join(', ')}`;\n\n return header;\n};\n\nconst oauth1Request = async ({\n method,\n url,\n consumerKey,\n clientCredential,\n token,\n tokenCredential,\n params = {},\n}) => {\n const authorization = buildOAuth1Header({\n method,\n url,\n params,\n consumerKey,\n clientCredential,\n token,\n tokenCredential,\n });\n\n const response = await fetch(url, {\n method,\n headers: { Authorization: authorization },\n });\n\n const text = await response.text();\n if (!response.ok) {\n throw new Error(text || `OAuth1 request failed (${response.status})`);\n }\n\n return Object.fromEntries(new URLSearchParams(text));\n};\n\nconst requestToken = async ({ requestUrl, redirectUri, consumerKey, clientCredential }) =>\n oauth1Request({\n method: 'POST',\n url: requestUrl,\n consumerKey,\n clientCredential,\n params: { oauth_callback: redirectUri },\n });\n\nconst accessToken = async ({\n accessUrl,\n consumerKey,\n clientCredential,\n oauthToken,\n oauthVerifier,\n oauthTokenCredential,\n}) =>\n oauth1Request({\n method: 'POST',\n url: accessUrl,\n consumerKey,\n clientCredential,\n token: oauthToken,\n tokenCredential: oauthTokenCredential,\n params: { oauth_verifier: oauthVerifier },\n });\n\nconst twitterGet = async ({\n url,\n accessToken,\n accessCredential,\n consumerKey,\n clientCredential,\n qs = {},\n}) => {\n const target = new URL(url);\n const signedParams = {};\n\n Object.entries(qs).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n const stringValue = String(value);\n target.searchParams.set(key, stringValue);\n // RFC 5849 §3.4.1: base-string URI excludes the query; params are signed separately.\n signedParams[key] = stringValue;\n }\n });\n\n const authorization = buildOAuth1Header({\n method: 'GET',\n url: target.origin + target.pathname,\n params: signedParams,\n consumerKey,\n clientCredential,\n token: accessToken,\n tokenCredential: accessCredential,\n });\n\n const response = await fetch(target, {\n headers: { Authorization: authorization },\n });\n\n const body = await response.json();\n if (!response.ok) {\n throw new Error(body.errors?.[0]?.message || `Twitter API error (${response.status})`);\n }\n\n return { body };\n};\n\nmodule.exports = {\n buildOAuth1Header,\n requestToken,\n accessToken,\n twitterGet,\n};\n"],"names":["crypto","require$$0","URLSearchParams","require$$1","encode","str","encodeURIComponent","replace","c","codePointAt","toString","toUpperCase","sortKeys","keys","sort","a","b","signRfc5849BaseString","signatureBaseString","signingMaterial","createHmac","update","digest","buildOAuth1Header","method","url","params","consumerKey","clientCredential","token","tokenCredential","requestParameters","oauth_consumer_key","oauth_nonce","randomBytes","oauth_signature_method","oauth_timestamp","Math","floor","Date","now","oauth_version","oauth_token","paramString","Object","map","key","join","signature","headerParameters","oauth_signature","header","oauth1Request","authorization","response","fetch","headers","Authorization","text","ok","Error","status","fromEntries","requestToken","requestUrl","redirectUri","oauth_callback","accessToken","accessUrl","oauthToken","oauthVerifier","oauthTokenCredential","oauth_verifier","twitterGet","accessCredential","qs","target","URL","signedParams","entries","forEach","value","undefined","stringValue","String","searchParams","set","origin","pathname","body","json","errors","message","oauth1"],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { __require } from '../../_virtual/_node_crypto.mjs';
|
|
2
|
+
import { __require as __require$1 } from '../../_virtual/_node_url.mjs';
|
|
3
|
+
|
|
4
|
+
var oauth1;
|
|
5
|
+
var hasRequiredOauth1;
|
|
6
|
+
function requireOauth1() {
|
|
7
|
+
if (hasRequiredOauth1) return oauth1;
|
|
8
|
+
hasRequiredOauth1 = 1;
|
|
9
|
+
const crypto = __require();
|
|
10
|
+
const { URLSearchParams } = __require$1();
|
|
11
|
+
const encode = (str)=>encodeURIComponent(str).replace(/[!'()*]/g, (c)=>`%${c.codePointAt(0).toString(16).toUpperCase()}`);
|
|
12
|
+
const sortKeys = (keys)=>keys.sort((a, b)=>{
|
|
13
|
+
if (a < b) return -1;
|
|
14
|
+
if (a > b) return 1;
|
|
15
|
+
return 0;
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* OAuth 1.0 (RFC 5849) request signature — HMAC-SHA1 is required by the protocol.
|
|
19
|
+
* This is not password storage or user-credential hashing (those use bcrypt).
|
|
20
|
+
*/ const signRfc5849BaseString = (signatureBaseString, signingMaterial)=>{
|
|
21
|
+
// codeql[js/insufficient-password-hash] OAuth 1.0 signing material, not user password storage
|
|
22
|
+
return crypto.createHmac('sha1', signingMaterial).update(signatureBaseString).digest('base64');
|
|
23
|
+
};
|
|
24
|
+
const buildOAuth1Header = ({ method, url, params, consumerKey, clientCredential, token, tokenCredential })=>{
|
|
25
|
+
const requestParameters = {
|
|
26
|
+
oauth_consumer_key: consumerKey,
|
|
27
|
+
oauth_nonce: crypto.randomBytes(16).toString('hex'),
|
|
28
|
+
oauth_signature_method: 'HMAC-SHA1',
|
|
29
|
+
oauth_timestamp: Math.floor(Date.now() / 1000).toString(),
|
|
30
|
+
oauth_version: '1.0',
|
|
31
|
+
...token ? {
|
|
32
|
+
oauth_token: token
|
|
33
|
+
} : {},
|
|
34
|
+
...params
|
|
35
|
+
};
|
|
36
|
+
const paramString = sortKeys(Object.keys(requestParameters)).map((key)=>`${encode(key)}=${encode(requestParameters[key])}`).join('&');
|
|
37
|
+
const signatureBaseString = [
|
|
38
|
+
method.toUpperCase(),
|
|
39
|
+
encode(url),
|
|
40
|
+
encode(paramString)
|
|
41
|
+
].join('&');
|
|
42
|
+
const signingMaterial = `${encode(clientCredential)}&${encode(tokenCredential || '')}`;
|
|
43
|
+
const signature = signRfc5849BaseString(signatureBaseString, signingMaterial);
|
|
44
|
+
const headerParameters = {
|
|
45
|
+
...requestParameters,
|
|
46
|
+
oauth_signature: signature
|
|
47
|
+
};
|
|
48
|
+
const header = `OAuth ${sortKeys(Object.keys(headerParameters)).map((key)=>`${encode(key)}="${encode(headerParameters[key])}"`).join(', ')}`;
|
|
49
|
+
return header;
|
|
50
|
+
};
|
|
51
|
+
const oauth1Request = async ({ method, url, consumerKey, clientCredential, token, tokenCredential, params = {} })=>{
|
|
52
|
+
const authorization = buildOAuth1Header({
|
|
53
|
+
method,
|
|
54
|
+
url,
|
|
55
|
+
params,
|
|
56
|
+
consumerKey,
|
|
57
|
+
clientCredential,
|
|
58
|
+
token,
|
|
59
|
+
tokenCredential
|
|
60
|
+
});
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
method,
|
|
63
|
+
headers: {
|
|
64
|
+
Authorization: authorization
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
const text = await response.text();
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
throw new Error(text || `OAuth1 request failed (${response.status})`);
|
|
70
|
+
}
|
|
71
|
+
return Object.fromEntries(new URLSearchParams(text));
|
|
72
|
+
};
|
|
73
|
+
const requestToken = async ({ requestUrl, redirectUri, consumerKey, clientCredential })=>oauth1Request({
|
|
74
|
+
method: 'POST',
|
|
75
|
+
url: requestUrl,
|
|
76
|
+
consumerKey,
|
|
77
|
+
clientCredential,
|
|
78
|
+
params: {
|
|
79
|
+
oauth_callback: redirectUri
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
const accessToken = async ({ accessUrl, consumerKey, clientCredential, oauthToken, oauthVerifier, oauthTokenCredential })=>oauth1Request({
|
|
83
|
+
method: 'POST',
|
|
84
|
+
url: accessUrl,
|
|
85
|
+
consumerKey,
|
|
86
|
+
clientCredential,
|
|
87
|
+
token: oauthToken,
|
|
88
|
+
tokenCredential: oauthTokenCredential,
|
|
89
|
+
params: {
|
|
90
|
+
oauth_verifier: oauthVerifier
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
const twitterGet = async ({ url, accessToken, accessCredential, consumerKey, clientCredential, qs = {} })=>{
|
|
94
|
+
const target = new URL(url);
|
|
95
|
+
const signedParams = {};
|
|
96
|
+
Object.entries(qs).forEach(([key, value])=>{
|
|
97
|
+
if (value !== undefined && value !== null) {
|
|
98
|
+
const stringValue = String(value);
|
|
99
|
+
target.searchParams.set(key, stringValue);
|
|
100
|
+
// RFC 5849 §3.4.1: base-string URI excludes the query; params are signed separately.
|
|
101
|
+
signedParams[key] = stringValue;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
const authorization = buildOAuth1Header({
|
|
105
|
+
method: 'GET',
|
|
106
|
+
url: target.origin + target.pathname,
|
|
107
|
+
params: signedParams,
|
|
108
|
+
consumerKey,
|
|
109
|
+
clientCredential,
|
|
110
|
+
token: accessToken,
|
|
111
|
+
tokenCredential: accessCredential
|
|
112
|
+
});
|
|
113
|
+
const response = await fetch(target, {
|
|
114
|
+
headers: {
|
|
115
|
+
Authorization: authorization
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
const body = await response.json();
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error(body.errors?.[0]?.message || `Twitter API error (${response.status})`);
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
body
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
oauth1 = {
|
|
127
|
+
buildOAuth1Header,
|
|
128
|
+
requestToken,
|
|
129
|
+
accessToken,
|
|
130
|
+
twitterGet
|
|
131
|
+
};
|
|
132
|
+
return oauth1;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export { requireOauth1 as __require };
|
|
136
|
+
//# sourceMappingURL=oauth1.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth1.mjs","sources":["../../../../server/utils/oauth-connect/oauth1.js"],"sourcesContent":["'use strict';\n\nconst crypto = require('node:crypto');\nconst { URLSearchParams } = require('node:url');\n\nconst encode = (str) =>\n encodeURIComponent(str).replace(\n /[!'()*]/g,\n (c) => `%${c.codePointAt(0).toString(16).toUpperCase()}`\n );\n\nconst sortKeys = (keys) =>\n keys.sort((a, b) => {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n });\n\n/**\n * OAuth 1.0 (RFC 5849) request signature — HMAC-SHA1 is required by the protocol.\n * This is not password storage or user-credential hashing (those use bcrypt).\n */\nconst signRfc5849BaseString = (signatureBaseString, signingMaterial) => {\n // codeql[js/insufficient-password-hash] OAuth 1.0 signing material, not user password storage\n return crypto.createHmac('sha1', signingMaterial).update(signatureBaseString).digest('base64');\n};\n\nconst buildOAuth1Header = ({\n method,\n url,\n params,\n consumerKey,\n clientCredential,\n token,\n tokenCredential,\n}) => {\n const requestParameters = {\n oauth_consumer_key: consumerKey,\n oauth_nonce: crypto.randomBytes(16).toString('hex'),\n oauth_signature_method: 'HMAC-SHA1',\n oauth_timestamp: Math.floor(Date.now() / 1000).toString(),\n oauth_version: '1.0',\n ...(token ? { oauth_token: token } : {}),\n ...params,\n };\n\n const paramString = sortKeys(Object.keys(requestParameters))\n .map((key) => `${encode(key)}=${encode(requestParameters[key])}`)\n .join('&');\n\n const signatureBaseString = [method.toUpperCase(), encode(url), encode(paramString)].join('&');\n const signingMaterial = `${encode(clientCredential)}&${encode(tokenCredential || '')}`;\n const signature = signRfc5849BaseString(signatureBaseString, signingMaterial);\n\n const headerParameters = { ...requestParameters, oauth_signature: signature };\n const header = `OAuth ${sortKeys(Object.keys(headerParameters))\n .map((key) => `${encode(key)}=\"${encode(headerParameters[key])}\"`)\n .join(', ')}`;\n\n return header;\n};\n\nconst oauth1Request = async ({\n method,\n url,\n consumerKey,\n clientCredential,\n token,\n tokenCredential,\n params = {},\n}) => {\n const authorization = buildOAuth1Header({\n method,\n url,\n params,\n consumerKey,\n clientCredential,\n token,\n tokenCredential,\n });\n\n const response = await fetch(url, {\n method,\n headers: { Authorization: authorization },\n });\n\n const text = await response.text();\n if (!response.ok) {\n throw new Error(text || `OAuth1 request failed (${response.status})`);\n }\n\n return Object.fromEntries(new URLSearchParams(text));\n};\n\nconst requestToken = async ({ requestUrl, redirectUri, consumerKey, clientCredential }) =>\n oauth1Request({\n method: 'POST',\n url: requestUrl,\n consumerKey,\n clientCredential,\n params: { oauth_callback: redirectUri },\n });\n\nconst accessToken = async ({\n accessUrl,\n consumerKey,\n clientCredential,\n oauthToken,\n oauthVerifier,\n oauthTokenCredential,\n}) =>\n oauth1Request({\n method: 'POST',\n url: accessUrl,\n consumerKey,\n clientCredential,\n token: oauthToken,\n tokenCredential: oauthTokenCredential,\n params: { oauth_verifier: oauthVerifier },\n });\n\nconst twitterGet = async ({\n url,\n accessToken,\n accessCredential,\n consumerKey,\n clientCredential,\n qs = {},\n}) => {\n const target = new URL(url);\n const signedParams = {};\n\n Object.entries(qs).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n const stringValue = String(value);\n target.searchParams.set(key, stringValue);\n // RFC 5849 §3.4.1: base-string URI excludes the query; params are signed separately.\n signedParams[key] = stringValue;\n }\n });\n\n const authorization = buildOAuth1Header({\n method: 'GET',\n url: target.origin + target.pathname,\n params: signedParams,\n consumerKey,\n clientCredential,\n token: accessToken,\n tokenCredential: accessCredential,\n });\n\n const response = await fetch(target, {\n headers: { Authorization: authorization },\n });\n\n const body = await response.json();\n if (!response.ok) {\n throw new Error(body.errors?.[0]?.message || `Twitter API error (${response.status})`);\n }\n\n return { body };\n};\n\nmodule.exports = {\n buildOAuth1Header,\n requestToken,\n accessToken,\n twitterGet,\n};\n"],"names":["crypto","require$$0","URLSearchParams","require$$1","encode","str","encodeURIComponent","replace","c","codePointAt","toString","toUpperCase","sortKeys","keys","sort","a","b","signRfc5849BaseString","signatureBaseString","signingMaterial","createHmac","update","digest","buildOAuth1Header","method","url","params","consumerKey","clientCredential","token","tokenCredential","requestParameters","oauth_consumer_key","oauth_nonce","randomBytes","oauth_signature_method","oauth_timestamp","Math","floor","Date","now","oauth_version","oauth_token","paramString","Object","map","key","join","signature","headerParameters","oauth_signature","header","oauth1Request","authorization","response","fetch","headers","Authorization","text","ok","Error","status","fromEntries","requestToken","requestUrl","redirectUri","oauth_callback","accessToken","accessUrl","oauthToken","oauthVerifier","oauthTokenCredential","oauth_verifier","twitterGet","accessCredential","qs","target","URL","signedParams","entries","forEach","value","undefined","stringValue","String","searchParams","set","origin","pathname","body","json","errors","message","oauth1"],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _node_crypto_commonjsExternal = require('../../_virtual/_node_crypto.js');
|
|
4
|
+
|
|
5
|
+
var oauth2;
|
|
6
|
+
var hasRequiredOauth2;
|
|
7
|
+
function requireOauth2() {
|
|
8
|
+
if (hasRequiredOauth2) return oauth2;
|
|
9
|
+
hasRequiredOauth2 = 1;
|
|
10
|
+
const crypto = _node_crypto_commonjsExternal.__require();
|
|
11
|
+
const formatScope = (scope, delimiter = ',')=>{
|
|
12
|
+
if (Array.isArray(scope)) {
|
|
13
|
+
return scope.filter(Boolean).join(delimiter) || undefined;
|
|
14
|
+
}
|
|
15
|
+
return scope || undefined;
|
|
16
|
+
};
|
|
17
|
+
const substituteSubdomain = (url, subdomain)=>subdomain ? url.replace('[subdomain]', subdomain) : url;
|
|
18
|
+
const buildAuthorizeUrl = (provider, { key, redirectUri, scope, subdomain })=>{
|
|
19
|
+
const authorizeUrl = substituteSubdomain(provider.authorize_url, subdomain);
|
|
20
|
+
const params = new URLSearchParams({
|
|
21
|
+
client_id: key,
|
|
22
|
+
response_type: 'code',
|
|
23
|
+
redirect_uri: redirectUri
|
|
24
|
+
});
|
|
25
|
+
const formattedScope = formatScope(scope, provider.scope_delimiter);
|
|
26
|
+
if (formattedScope) {
|
|
27
|
+
params.set('scope', formattedScope);
|
|
28
|
+
}
|
|
29
|
+
if (provider.name === 'instagram' && /^\d+$/.test(key)) {
|
|
30
|
+
params.delete('client_id');
|
|
31
|
+
params.set('app_id', key);
|
|
32
|
+
if (formattedScope) {
|
|
33
|
+
params.set('scope', formattedScope.replaceAll(' ', ','));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return `${authorizeUrl}?${params.toString()}`;
|
|
37
|
+
};
|
|
38
|
+
const parseTokenResponse = async (response)=>{
|
|
39
|
+
const contentType = response.headers.get('content-type') || '';
|
|
40
|
+
if (contentType.includes('application/json')) {
|
|
41
|
+
return response.json();
|
|
42
|
+
}
|
|
43
|
+
const text = await response.text();
|
|
44
|
+
return Object.fromEntries(new URLSearchParams(text));
|
|
45
|
+
};
|
|
46
|
+
const exchangeAuthorizationCode = async (provider, { key, secret, redirectUri, code, subdomain })=>{
|
|
47
|
+
const accessUrl = substituteSubdomain(provider.access_url, subdomain);
|
|
48
|
+
const body = new URLSearchParams({
|
|
49
|
+
grant_type: 'authorization_code',
|
|
50
|
+
code,
|
|
51
|
+
redirect_uri: redirectUri,
|
|
52
|
+
client_id: key,
|
|
53
|
+
client_secret: secret
|
|
54
|
+
});
|
|
55
|
+
const headers = {
|
|
56
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
57
|
+
};
|
|
58
|
+
if (provider.token_endpoint_auth_method === 'client_secret_basic') {
|
|
59
|
+
const credentials = Buffer.from(`${key}:${secret}`).toString('base64');
|
|
60
|
+
headers.Authorization = `Basic ${credentials}`;
|
|
61
|
+
body.delete('client_id');
|
|
62
|
+
body.delete('client_secret');
|
|
63
|
+
}
|
|
64
|
+
if (provider.name === 'instagram' && /^\d+$/.test(key)) {
|
|
65
|
+
body.delete('client_id');
|
|
66
|
+
body.delete('client_secret');
|
|
67
|
+
body.set('app_id', key);
|
|
68
|
+
body.set('app_secret', secret);
|
|
69
|
+
}
|
|
70
|
+
const response = await fetch(accessUrl, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers,
|
|
73
|
+
body
|
|
74
|
+
});
|
|
75
|
+
const output = await parseTokenResponse(response);
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
throw new Error(output.error_description || output.error || `Token exchange failed (${response.status})`);
|
|
78
|
+
}
|
|
79
|
+
return output;
|
|
80
|
+
};
|
|
81
|
+
const tokensToQueryPayload = (provider, tokenResponse)=>{
|
|
82
|
+
const data = {
|
|
83
|
+
raw: tokenResponse
|
|
84
|
+
};
|
|
85
|
+
if (provider.oauth === 1) {
|
|
86
|
+
if (tokenResponse.oauth_token) {
|
|
87
|
+
data.access_token = tokenResponse.oauth_token;
|
|
88
|
+
}
|
|
89
|
+
if (tokenResponse.oauth_token_secret) {
|
|
90
|
+
data.access_secret = tokenResponse.oauth_token_secret;
|
|
91
|
+
}
|
|
92
|
+
return data;
|
|
93
|
+
}
|
|
94
|
+
if (tokenResponse.id_token) {
|
|
95
|
+
data.id_token = tokenResponse.id_token;
|
|
96
|
+
}
|
|
97
|
+
if (tokenResponse.access_token) {
|
|
98
|
+
data.access_token = tokenResponse.access_token;
|
|
99
|
+
}
|
|
100
|
+
if (tokenResponse.refresh_token) {
|
|
101
|
+
data.refresh_token = tokenResponse.refresh_token;
|
|
102
|
+
}
|
|
103
|
+
return data;
|
|
104
|
+
};
|
|
105
|
+
const generateState = ()=>crypto.randomBytes(20).toString('hex');
|
|
106
|
+
oauth2 = {
|
|
107
|
+
buildAuthorizeUrl,
|
|
108
|
+
exchangeAuthorizationCode,
|
|
109
|
+
tokensToQueryPayload,
|
|
110
|
+
generateState,
|
|
111
|
+
substituteSubdomain
|
|
112
|
+
};
|
|
113
|
+
return oauth2;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
exports.__require = requireOauth2;
|
|
117
|
+
//# sourceMappingURL=oauth2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth2.js","sources":["../../../../server/utils/oauth-connect/oauth2.js"],"sourcesContent":["'use strict';\n\nconst crypto = require('node:crypto');\n\nconst formatScope = (scope, delimiter = ',') => {\n if (Array.isArray(scope)) {\n return scope.filter(Boolean).join(delimiter) || undefined;\n }\n return scope || undefined;\n};\n\nconst substituteSubdomain = (url, subdomain) =>\n subdomain ? url.replace('[subdomain]', subdomain) : url;\n\nconst buildAuthorizeUrl = (provider, { key, redirectUri, scope, subdomain }) => {\n const authorizeUrl = substituteSubdomain(provider.authorize_url, subdomain);\n const params = new URLSearchParams({\n client_id: key,\n response_type: 'code',\n redirect_uri: redirectUri,\n });\n\n const formattedScope = formatScope(scope, provider.scope_delimiter);\n if (formattedScope) {\n params.set('scope', formattedScope);\n }\n\n if (provider.name === 'instagram' && /^\\d+$/.test(key)) {\n params.delete('client_id');\n params.set('app_id', key);\n if (formattedScope) {\n params.set('scope', formattedScope.replaceAll(' ', ','));\n }\n }\n\n return `${authorizeUrl}?${params.toString()}`;\n};\n\nconst parseTokenResponse = async (response) => {\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return response.json();\n }\n const text = await response.text();\n return Object.fromEntries(new URLSearchParams(text));\n};\n\nconst exchangeAuthorizationCode = async (\n provider,\n { key, secret, redirectUri, code, subdomain }\n) => {\n const accessUrl = substituteSubdomain(provider.access_url, subdomain);\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri,\n client_id: key,\n client_secret: secret,\n });\n\n const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n\n if (provider.token_endpoint_auth_method === 'client_secret_basic') {\n const credentials = Buffer.from(`${key}:${secret}`).toString('base64');\n headers.Authorization = `Basic ${credentials}`;\n body.delete('client_id');\n body.delete('client_secret');\n }\n\n if (provider.name === 'instagram' && /^\\d+$/.test(key)) {\n body.delete('client_id');\n body.delete('client_secret');\n body.set('app_id', key);\n body.set('app_secret', secret);\n }\n\n const response = await fetch(accessUrl, { method: 'POST', headers, body });\n const output = await parseTokenResponse(response);\n\n if (!response.ok) {\n throw new Error(\n output.error_description || output.error || `Token exchange failed (${response.status})`\n );\n }\n\n return output;\n};\n\nconst tokensToQueryPayload = (provider, tokenResponse) => {\n const data = { raw: tokenResponse };\n\n if (provider.oauth === 1) {\n if (tokenResponse.oauth_token) {\n data.access_token = tokenResponse.oauth_token;\n }\n if (tokenResponse.oauth_token_secret) {\n data.access_secret = tokenResponse.oauth_token_secret;\n }\n return data;\n }\n\n if (tokenResponse.id_token) {\n data.id_token = tokenResponse.id_token;\n }\n if (tokenResponse.access_token) {\n data.access_token = tokenResponse.access_token;\n }\n if (tokenResponse.refresh_token) {\n data.refresh_token = tokenResponse.refresh_token;\n }\n\n return data;\n};\n\nconst generateState = () => crypto.randomBytes(20).toString('hex');\n\nmodule.exports = {\n buildAuthorizeUrl,\n exchangeAuthorizationCode,\n tokensToQueryPayload,\n generateState,\n substituteSubdomain,\n};\n"],"names":["crypto","require$$0","formatScope","scope","delimiter","Array","isArray","filter","Boolean","join","undefined","substituteSubdomain","url","subdomain","replace","buildAuthorizeUrl","provider","key","redirectUri","authorizeUrl","authorize_url","params","URLSearchParams","client_id","response_type","redirect_uri","formattedScope","scope_delimiter","set","name","test","delete","replaceAll","toString","parseTokenResponse","response","contentType","headers","get","includes","json","text","Object","fromEntries","exchangeAuthorizationCode","secret","code","accessUrl","access_url","body","grant_type","client_secret","token_endpoint_auth_method","credentials","Buffer","from","Authorization","fetch","method","output","ok","Error","error_description","error","status","tokensToQueryPayload","tokenResponse","data","raw","oauth","oauth_token","access_token","oauth_token_secret","access_secret","id_token","refresh_token","generateState","randomBytes","oauth2"],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { __require } from '../../_virtual/_node_crypto.mjs';
|
|
2
|
+
|
|
3
|
+
var oauth2;
|
|
4
|
+
var hasRequiredOauth2;
|
|
5
|
+
function requireOauth2() {
|
|
6
|
+
if (hasRequiredOauth2) return oauth2;
|
|
7
|
+
hasRequiredOauth2 = 1;
|
|
8
|
+
const crypto = __require();
|
|
9
|
+
const formatScope = (scope, delimiter = ',')=>{
|
|
10
|
+
if (Array.isArray(scope)) {
|
|
11
|
+
return scope.filter(Boolean).join(delimiter) || undefined;
|
|
12
|
+
}
|
|
13
|
+
return scope || undefined;
|
|
14
|
+
};
|
|
15
|
+
const substituteSubdomain = (url, subdomain)=>subdomain ? url.replace('[subdomain]', subdomain) : url;
|
|
16
|
+
const buildAuthorizeUrl = (provider, { key, redirectUri, scope, subdomain })=>{
|
|
17
|
+
const authorizeUrl = substituteSubdomain(provider.authorize_url, subdomain);
|
|
18
|
+
const params = new URLSearchParams({
|
|
19
|
+
client_id: key,
|
|
20
|
+
response_type: 'code',
|
|
21
|
+
redirect_uri: redirectUri
|
|
22
|
+
});
|
|
23
|
+
const formattedScope = formatScope(scope, provider.scope_delimiter);
|
|
24
|
+
if (formattedScope) {
|
|
25
|
+
params.set('scope', formattedScope);
|
|
26
|
+
}
|
|
27
|
+
if (provider.name === 'instagram' && /^\d+$/.test(key)) {
|
|
28
|
+
params.delete('client_id');
|
|
29
|
+
params.set('app_id', key);
|
|
30
|
+
if (formattedScope) {
|
|
31
|
+
params.set('scope', formattedScope.replaceAll(' ', ','));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return `${authorizeUrl}?${params.toString()}`;
|
|
35
|
+
};
|
|
36
|
+
const parseTokenResponse = async (response)=>{
|
|
37
|
+
const contentType = response.headers.get('content-type') || '';
|
|
38
|
+
if (contentType.includes('application/json')) {
|
|
39
|
+
return response.json();
|
|
40
|
+
}
|
|
41
|
+
const text = await response.text();
|
|
42
|
+
return Object.fromEntries(new URLSearchParams(text));
|
|
43
|
+
};
|
|
44
|
+
const exchangeAuthorizationCode = async (provider, { key, secret, redirectUri, code, subdomain })=>{
|
|
45
|
+
const accessUrl = substituteSubdomain(provider.access_url, subdomain);
|
|
46
|
+
const body = new URLSearchParams({
|
|
47
|
+
grant_type: 'authorization_code',
|
|
48
|
+
code,
|
|
49
|
+
redirect_uri: redirectUri,
|
|
50
|
+
client_id: key,
|
|
51
|
+
client_secret: secret
|
|
52
|
+
});
|
|
53
|
+
const headers = {
|
|
54
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
55
|
+
};
|
|
56
|
+
if (provider.token_endpoint_auth_method === 'client_secret_basic') {
|
|
57
|
+
const credentials = Buffer.from(`${key}:${secret}`).toString('base64');
|
|
58
|
+
headers.Authorization = `Basic ${credentials}`;
|
|
59
|
+
body.delete('client_id');
|
|
60
|
+
body.delete('client_secret');
|
|
61
|
+
}
|
|
62
|
+
if (provider.name === 'instagram' && /^\d+$/.test(key)) {
|
|
63
|
+
body.delete('client_id');
|
|
64
|
+
body.delete('client_secret');
|
|
65
|
+
body.set('app_id', key);
|
|
66
|
+
body.set('app_secret', secret);
|
|
67
|
+
}
|
|
68
|
+
const response = await fetch(accessUrl, {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
headers,
|
|
71
|
+
body
|
|
72
|
+
});
|
|
73
|
+
const output = await parseTokenResponse(response);
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
throw new Error(output.error_description || output.error || `Token exchange failed (${response.status})`);
|
|
76
|
+
}
|
|
77
|
+
return output;
|
|
78
|
+
};
|
|
79
|
+
const tokensToQueryPayload = (provider, tokenResponse)=>{
|
|
80
|
+
const data = {
|
|
81
|
+
raw: tokenResponse
|
|
82
|
+
};
|
|
83
|
+
if (provider.oauth === 1) {
|
|
84
|
+
if (tokenResponse.oauth_token) {
|
|
85
|
+
data.access_token = tokenResponse.oauth_token;
|
|
86
|
+
}
|
|
87
|
+
if (tokenResponse.oauth_token_secret) {
|
|
88
|
+
data.access_secret = tokenResponse.oauth_token_secret;
|
|
89
|
+
}
|
|
90
|
+
return data;
|
|
91
|
+
}
|
|
92
|
+
if (tokenResponse.id_token) {
|
|
93
|
+
data.id_token = tokenResponse.id_token;
|
|
94
|
+
}
|
|
95
|
+
if (tokenResponse.access_token) {
|
|
96
|
+
data.access_token = tokenResponse.access_token;
|
|
97
|
+
}
|
|
98
|
+
if (tokenResponse.refresh_token) {
|
|
99
|
+
data.refresh_token = tokenResponse.refresh_token;
|
|
100
|
+
}
|
|
101
|
+
return data;
|
|
102
|
+
};
|
|
103
|
+
const generateState = ()=>crypto.randomBytes(20).toString('hex');
|
|
104
|
+
oauth2 = {
|
|
105
|
+
buildAuthorizeUrl,
|
|
106
|
+
exchangeAuthorizationCode,
|
|
107
|
+
tokensToQueryPayload,
|
|
108
|
+
generateState,
|
|
109
|
+
substituteSubdomain
|
|
110
|
+
};
|
|
111
|
+
return oauth2;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export { requireOauth2 as __require };
|
|
115
|
+
//# sourceMappingURL=oauth2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth2.mjs","sources":["../../../../server/utils/oauth-connect/oauth2.js"],"sourcesContent":["'use strict';\n\nconst crypto = require('node:crypto');\n\nconst formatScope = (scope, delimiter = ',') => {\n if (Array.isArray(scope)) {\n return scope.filter(Boolean).join(delimiter) || undefined;\n }\n return scope || undefined;\n};\n\nconst substituteSubdomain = (url, subdomain) =>\n subdomain ? url.replace('[subdomain]', subdomain) : url;\n\nconst buildAuthorizeUrl = (provider, { key, redirectUri, scope, subdomain }) => {\n const authorizeUrl = substituteSubdomain(provider.authorize_url, subdomain);\n const params = new URLSearchParams({\n client_id: key,\n response_type: 'code',\n redirect_uri: redirectUri,\n });\n\n const formattedScope = formatScope(scope, provider.scope_delimiter);\n if (formattedScope) {\n params.set('scope', formattedScope);\n }\n\n if (provider.name === 'instagram' && /^\\d+$/.test(key)) {\n params.delete('client_id');\n params.set('app_id', key);\n if (formattedScope) {\n params.set('scope', formattedScope.replaceAll(' ', ','));\n }\n }\n\n return `${authorizeUrl}?${params.toString()}`;\n};\n\nconst parseTokenResponse = async (response) => {\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return response.json();\n }\n const text = await response.text();\n return Object.fromEntries(new URLSearchParams(text));\n};\n\nconst exchangeAuthorizationCode = async (\n provider,\n { key, secret, redirectUri, code, subdomain }\n) => {\n const accessUrl = substituteSubdomain(provider.access_url, subdomain);\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri,\n client_id: key,\n client_secret: secret,\n });\n\n const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n\n if (provider.token_endpoint_auth_method === 'client_secret_basic') {\n const credentials = Buffer.from(`${key}:${secret}`).toString('base64');\n headers.Authorization = `Basic ${credentials}`;\n body.delete('client_id');\n body.delete('client_secret');\n }\n\n if (provider.name === 'instagram' && /^\\d+$/.test(key)) {\n body.delete('client_id');\n body.delete('client_secret');\n body.set('app_id', key);\n body.set('app_secret', secret);\n }\n\n const response = await fetch(accessUrl, { method: 'POST', headers, body });\n const output = await parseTokenResponse(response);\n\n if (!response.ok) {\n throw new Error(\n output.error_description || output.error || `Token exchange failed (${response.status})`\n );\n }\n\n return output;\n};\n\nconst tokensToQueryPayload = (provider, tokenResponse) => {\n const data = { raw: tokenResponse };\n\n if (provider.oauth === 1) {\n if (tokenResponse.oauth_token) {\n data.access_token = tokenResponse.oauth_token;\n }\n if (tokenResponse.oauth_token_secret) {\n data.access_secret = tokenResponse.oauth_token_secret;\n }\n return data;\n }\n\n if (tokenResponse.id_token) {\n data.id_token = tokenResponse.id_token;\n }\n if (tokenResponse.access_token) {\n data.access_token = tokenResponse.access_token;\n }\n if (tokenResponse.refresh_token) {\n data.refresh_token = tokenResponse.refresh_token;\n }\n\n return data;\n};\n\nconst generateState = () => crypto.randomBytes(20).toString('hex');\n\nmodule.exports = {\n buildAuthorizeUrl,\n exchangeAuthorizationCode,\n tokensToQueryPayload,\n generateState,\n substituteSubdomain,\n};\n"],"names":["crypto","require$$0","formatScope","scope","delimiter","Array","isArray","filter","Boolean","join","undefined","substituteSubdomain","url","subdomain","replace","buildAuthorizeUrl","provider","key","redirectUri","authorizeUrl","authorize_url","params","URLSearchParams","client_id","response_type","redirect_uri","formattedScope","scope_delimiter","set","name","test","delete","replaceAll","toString","parseTokenResponse","response","contentType","headers","get","includes","json","text","Object","fromEntries","exchangeAuthorizationCode","secret","code","accessUrl","access_url","body","grant_type","client_secret","token_endpoint_auth_method","credentials","Buffer","from","Authorization","fetch","method","output","ok","Error","error_description","error","status","tokensToQueryPayload","tokenResponse","data","raw","oauth","oauth_token","access_token","oauth_token_secret","access_secret","id_token","refresh_token","generateState","randomBytes","oauth2"],"mappings":"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"}
|