diff --git a/lib/build/recipe/thirdparty/providers/github.js b/lib/build/recipe/thirdparty/providers/github.js index 14b22ce21..83239b76d 100644 --- a/lib/build/recipe/thirdparty/providers/github.js +++ b/lib/build/recipe/thirdparty/providers/github.js @@ -21,6 +21,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); */ const cross_fetch_1 = __importDefault(require("cross-fetch")); const custom_1 = __importDefault(require("./custom")); +const utils_1 = require("./utils"); function getSupertokensUserInfoFromRawUserInfoResponseForGithub(rawUserInfoResponse) { if (rawUserInfoResponse.fromUserInfoAPI === undefined) { throw new Error("rawUserInfoResponse.fromUserInfoAPI is not available"); @@ -58,24 +59,22 @@ function Github(input) { const basicAuthToken = Buffer.from( `${clientConfig.clientId}:${clientConfig.clientSecret === undefined ? "" : clientConfig.clientSecret}` ).toString("base64"); - const applicationsResponse = await cross_fetch_1.default( + const applicationResponse = await utils_1.doPostRequest( `https://api.github.com/applications/${clientConfig.clientId}/token`, { - headers: { - Authorization: `Basic ${basicAuthToken}`, - "Content-Type": "application/json", - }, - method: "POST", - body: JSON.stringify({ - access_token: accessToken, - }), + access_token: accessToken, + }, + { + Authorization: `Basic ${basicAuthToken}`, + "Content-Type": "application/json", + }, + (status) => { + if (status !== 200) { + throw new Error("Invalid access token"); + } } ); - if (applicationsResponse.status !== 200) { - throw new Error("Invalid access token"); - } - const body = await applicationsResponse.json(); - if (body.app === undefined || body.app.client_id !== clientConfig.clientId) { + if (applicationResponse.app === undefined || applicationResponse.app.client_id !== clientConfig.clientId) { throw new Error("Access token does not belong to your application"); } }; diff --git a/lib/build/recipe/thirdparty/providers/utils.d.ts b/lib/build/recipe/thirdparty/providers/utils.d.ts index fe9b9e048..a421649d0 100644 --- a/lib/build/recipe/thirdparty/providers/utils.d.ts +++ b/lib/build/recipe/thirdparty/providers/utils.d.ts @@ -17,7 +17,8 @@ export declare function doPostRequest( }, headers?: { [key: string]: string; - } + }, + validateStatusCode?: (status: number) => void ): Promise; export declare function verifyIdTokenFromJWKSEndpointAndGetPayload( idToken: string, diff --git a/lib/build/recipe/thirdparty/providers/utils.js b/lib/build/recipe/thirdparty/providers/utils.js index 7e5896f2c..6a975517b 100644 --- a/lib/build/recipe/thirdparty/providers/utils.js +++ b/lib/build/recipe/thirdparty/providers/utils.js @@ -70,7 +70,7 @@ async function doGetRequest(url, queryParams, headers) { return respData; } exports.doGetRequest = doGetRequest; -async function doPostRequest(url, params, headers) { +async function doPostRequest(url, params, headers, validateStatusCode) { if (headers === undefined) { headers = {}; } @@ -85,6 +85,10 @@ async function doPostRequest(url, params, headers) { body, headers, }); + // This lets callers verify the status code, if invalid this function should throw an error + if (validateStatusCode !== undefined) { + validateStatusCode(response.status); + } if (response.status >= 400) { logger_1.logDebugMessage( `Received response with status ${response.status} and body ${await response.clone().text()}` diff --git a/lib/ts/recipe/thirdparty/providers/github.ts b/lib/ts/recipe/thirdparty/providers/github.ts index e9307658d..38dde239d 100644 --- a/lib/ts/recipe/thirdparty/providers/github.ts +++ b/lib/ts/recipe/thirdparty/providers/github.ts @@ -15,6 +15,7 @@ import fetch from "cross-fetch"; import { ProviderInput, TypeProvider, UserInfo } from "../types"; import NewProvider from "./custom"; +import { doPostRequest } from "./utils"; function getSupertokensUserInfoFromRawUserInfoResponseForGithub(rawUserInfoResponse: { fromIdTokenPayload?: any; @@ -64,27 +65,23 @@ export default function Github(input: ProviderInput): TypeProvider { `${clientConfig.clientId}:${clientConfig.clientSecret === undefined ? "" : clientConfig.clientSecret}` ).toString("base64"); - const applicationsResponse = await fetch( + const applicationResponse = await doPostRequest( `https://api.github.com/applications/${clientConfig.clientId}/token`, { - headers: { - Authorization: `Basic ${basicAuthToken}`, - "Content-Type": "application/json", - }, - method: "POST", - body: JSON.stringify({ - access_token: accessToken, - }), + access_token: accessToken, + }, + { + Authorization: `Basic ${basicAuthToken}`, + "Content-Type": "application/json", + }, + (status) => { + if (status !== 200) { + throw new Error("Invalid access token"); + } } ); - if (applicationsResponse.status !== 200) { - throw new Error("Invalid access token"); - } - - const body = await applicationsResponse.json(); - - if (body.app === undefined || body.app.client_id !== clientConfig.clientId) { + if (applicationResponse.app === undefined || applicationResponse.app.client_id !== clientConfig.clientId) { throw new Error("Access token does not belong to your application"); } }; diff --git a/lib/ts/recipe/thirdparty/providers/utils.ts b/lib/ts/recipe/thirdparty/providers/utils.ts index 28dcf6e26..f13f47bed 100644 --- a/lib/ts/recipe/thirdparty/providers/utils.ts +++ b/lib/ts/recipe/thirdparty/providers/utils.ts @@ -39,7 +39,8 @@ export async function doGetRequest( export async function doPostRequest( url: string, params: { [key: string]: any }, - headers?: { [key: string]: string } + headers?: { [key: string]: string }, + validateStatusCode?: (status: number) => void ): Promise { if (headers === undefined) { headers = {}; @@ -59,6 +60,11 @@ export async function doPostRequest( headers, }); + // This lets callers verify the status code, if invalid this function should throw an error + if (validateStatusCode !== undefined) { + validateStatusCode(response.status); + } + if (response.status >= 400) { logDebugMessage(`Received response with status ${response.status} and body ${await response.clone().text()}`); throw new Error(`Received response with status ${response.status} and body ${await response.clone().text()}`);