diff --git a/lib/build/recipe/oauth2client/api/authorisationUrl.d.ts b/lib/build/recipe/oauth2client/api/authorisationUrl.d.ts deleted file mode 100644 index 61b231e1a..000000000 --- a/lib/build/recipe/oauth2client/api/authorisationUrl.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -// @ts-nocheck -import { APIInterface, APIOptions } from "../"; -import { UserContext } from "../../../types"; -export default function authorisationUrlAPI( - apiImplementation: APIInterface, - _tenantId: string, - options: APIOptions, - userContext: UserContext -): Promise; diff --git a/lib/build/recipe/oauth2client/api/authorisationUrl.js b/lib/build/recipe/oauth2client/api/authorisationUrl.js deleted file mode 100644 index e4544b31c..000000000 --- a/lib/build/recipe/oauth2client/api/authorisationUrl.js +++ /dev/null @@ -1,44 +0,0 @@ -"use strict"; -/* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod }; - }; -Object.defineProperty(exports, "__esModule", { value: true }); -const utils_1 = require("../../../utils"); -const error_1 = __importDefault(require("../../../error")); -async function authorisationUrlAPI(apiImplementation, _tenantId, options, userContext) { - if (apiImplementation.authorisationUrlGET === undefined) { - return false; - } - // TODO: Check if we can rename `redirectURIOnProviderDashboard` to a more suitable name - const redirectURIOnProviderDashboard = options.req.getKeyValueFromQuery("redirectURIOnProviderDashboard"); - if (redirectURIOnProviderDashboard === undefined || typeof redirectURIOnProviderDashboard !== "string") { - throw new error_1.default({ - type: error_1.default.BAD_INPUT_ERROR, - message: "Please provide the redirectURIOnProviderDashboard as a GET param", - }); - } - let result = await apiImplementation.authorisationUrlGET({ - redirectURIOnProviderDashboard, - options, - userContext, - }); - utils_1.send200Response(options.res, result); - return true; -} -exports.default = authorisationUrlAPI; diff --git a/lib/build/recipe/oauth2client/api/implementation.js b/lib/build/recipe/oauth2client/api/implementation.js index 5b642629a..159016c57 100644 --- a/lib/build/recipe/oauth2client/api/implementation.js +++ b/lib/build/recipe/oauth2client/api/implementation.js @@ -8,15 +8,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); const session_1 = __importDefault(require("../../session")); function getAPIInterface() { return { - authorisationUrlGET: async function ({ options, redirectURIOnProviderDashboard, userContext }) { - const providerConfig = await options.recipeImplementation.getProviderConfig({ userContext }); - const authUrl = await options.recipeImplementation.getAuthorisationRedirectURL({ - providerConfig, - redirectURIOnProviderDashboard, - userContext, - }); - return Object.assign({ status: "OK" }, authUrl); - }, signInPOST: async function (input) { const { options, tenantId, userContext } = input; const providerConfig = await options.recipeImplementation.getProviderConfig({ userContext }); @@ -32,7 +23,7 @@ function getAPIInterface() { } else { throw Error("should never come here"); } - const { userId, rawUserInfoFromProvider } = await options.recipeImplementation.getUserInfo({ + const { userId, rawUserInfo } = await options.recipeImplementation.getUserInfo({ providerConfig, oAuthTokens: oAuthTokensToUse, userContext, @@ -40,7 +31,7 @@ function getAPIInterface() { const { user, recipeUserId } = await options.recipeImplementation.signIn({ userId, tenantId, - rawUserInfoFromProvider, + rawUserInfo, oAuthTokens: oAuthTokensToUse, userContext, }); @@ -58,7 +49,7 @@ function getAPIInterface() { user, session, oAuthTokens: oAuthTokensToUse, - rawUserInfoFromProvider, + rawUserInfo, }; }, }; diff --git a/lib/build/recipe/oauth2client/api/signin.js b/lib/build/recipe/oauth2client/api/signin.js index 0a0fadc45..52631ac60 100644 --- a/lib/build/recipe/oauth2client/api/signin.js +++ b/lib/build/recipe/oauth2client/api/signin.js @@ -30,10 +30,10 @@ async function signInAPI(apiImplementation, tenantId, options, userContext) { let redirectURIInfo; let oAuthTokens; if (bodyParams.redirectURIInfo !== undefined) { - if (bodyParams.redirectURIInfo.redirectURIOnProviderDashboard === undefined) { + if (bodyParams.redirectURIInfo.redirectURI === undefined) { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, - message: "Please provide the redirectURIOnProviderDashboard in request body", + message: "Please provide the redirectURI in request body", }); } redirectURIInfo = bodyParams.redirectURIInfo; @@ -61,7 +61,6 @@ async function signInAPI(apiImplementation, tenantId, options, userContext) { tenantId, redirectURIInfo, oAuthTokens, - session, options, userContext, }); diff --git a/lib/build/recipe/oauth2client/constants.d.ts b/lib/build/recipe/oauth2client/constants.d.ts index fd2bef07d..1fb91e760 100644 --- a/lib/build/recipe/oauth2client/constants.d.ts +++ b/lib/build/recipe/oauth2client/constants.d.ts @@ -1,3 +1,2 @@ // @ts-nocheck -export declare const AUTHORISATION_API = "/oauth2client/authorisationurl"; -export declare const SIGN_IN_API = "/oauth2client/signin"; +export declare const SIGN_IN_API = "/oauth/client/signin"; diff --git a/lib/build/recipe/oauth2client/constants.js b/lib/build/recipe/oauth2client/constants.js index e8156ec89..4f42a6cb4 100644 --- a/lib/build/recipe/oauth2client/constants.js +++ b/lib/build/recipe/oauth2client/constants.js @@ -14,6 +14,5 @@ * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -exports.SIGN_IN_API = exports.AUTHORISATION_API = void 0; -exports.AUTHORISATION_API = "/oauth2client/authorisationurl"; -exports.SIGN_IN_API = "/oauth2client/signin"; +exports.SIGN_IN_API = void 0; +exports.SIGN_IN_API = "/oauth/client/signin"; diff --git a/lib/build/recipe/oauth2client/index.d.ts b/lib/build/recipe/oauth2client/index.d.ts index a16f0bb05..fd09feb41 100644 --- a/lib/build/recipe/oauth2client/index.d.ts +++ b/lib/build/recipe/oauth2client/index.d.ts @@ -3,16 +3,9 @@ import Recipe from "./recipe"; import { RecipeInterface, APIInterface, APIOptions, OAuthTokens } from "./types"; export default class Wrapper { static init: typeof Recipe.init; - static getAuthorisationRedirectURL( - redirectURIOnProviderDashboard: string, - userContext?: Record - ): Promise<{ - urlWithQueryParams: string; - pkceCodeVerifier?: string | undefined; - }>; static exchangeAuthCodeForOAuthTokens( redirectURIInfo: { - redirectURIOnProviderDashboard: string; + redirectURI: string; redirectURIQueryParams: any; pkceCodeVerifier?: string | undefined; }, @@ -24,7 +17,6 @@ export default class Wrapper { ): Promise; } export declare let init: typeof Recipe.init; -export declare let getAuthorisationRedirectURL: typeof Wrapper.getAuthorisationRedirectURL; export declare let exchangeAuthCodeForOAuthTokens: typeof Wrapper.exchangeAuthCodeForOAuthTokens; export declare let getUserInfo: typeof Wrapper.getUserInfo; export type { RecipeInterface, APIInterface, APIOptions }; diff --git a/lib/build/recipe/oauth2client/index.js b/lib/build/recipe/oauth2client/index.js index cdf968aaf..c70a69f41 100644 --- a/lib/build/recipe/oauth2client/index.js +++ b/lib/build/recipe/oauth2client/index.js @@ -19,22 +19,10 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getUserInfo = exports.exchangeAuthCodeForOAuthTokens = exports.getAuthorisationRedirectURL = exports.init = void 0; +exports.getUserInfo = exports.exchangeAuthCodeForOAuthTokens = exports.init = void 0; const utils_1 = require("../../utils"); const recipe_1 = __importDefault(require("./recipe")); class Wrapper { - static async getAuthorisationRedirectURL(redirectURIOnProviderDashboard, userContext) { - const recipeInterfaceImpl = recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl; - const normalisedUserContext = utils_1.getUserContext(userContext); - const providerConfig = await recipeInterfaceImpl.getProviderConfig({ - userContext: normalisedUserContext, - }); - return await recipeInterfaceImpl.getAuthorisationRedirectURL({ - providerConfig, - redirectURIOnProviderDashboard, - userContext: normalisedUserContext, - }); - } static async exchangeAuthCodeForOAuthTokens(redirectURIInfo, userContext) { const recipeInterfaceImpl = recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl; const normalisedUserContext = utils_1.getUserContext(userContext); @@ -63,6 +51,5 @@ class Wrapper { exports.default = Wrapper; Wrapper.init = recipe_1.default.init; exports.init = Wrapper.init; -exports.getAuthorisationRedirectURL = Wrapper.getAuthorisationRedirectURL; exports.exchangeAuthCodeForOAuthTokens = Wrapper.exchangeAuthCodeForOAuthTokens; exports.getUserInfo = Wrapper.getUserInfo; diff --git a/lib/build/recipe/oauth2client/recipe.js b/lib/build/recipe/oauth2client/recipe.js index d3ad7c29a..daf6b07f3 100644 --- a/lib/build/recipe/oauth2client/recipe.js +++ b/lib/build/recipe/oauth2client/recipe.js @@ -25,7 +25,6 @@ const error_1 = __importDefault(require("../../error")); const constants_1 = require("./constants"); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const signin_1 = __importDefault(require("./api/signin")); -const authorisationUrl_1 = __importDefault(require("./api/authorisationUrl")); const recipeImplementation_1 = __importDefault(require("./recipeImplementation")); const implementation_1 = __importDefault(require("./api/implementation")); const querier_1 = require("../../querier"); @@ -41,12 +40,6 @@ class Recipe extends recipeModule_1.default { id: constants_1.SIGN_IN_API, disabled: this.apiImpl.signInPOST === undefined, }, - { - method: "get", - pathWithoutApiBasePath: new normalisedURLPath_1.default(constants_1.AUTHORISATION_API), - id: constants_1.AUTHORISATION_API, - disabled: this.apiImpl.authorisationUrlGET === undefined, - }, ]; }; this.handleAPIRequest = async (id, tenantId, req, res, _path, _method, userContext) => { @@ -61,8 +54,6 @@ class Recipe extends recipeModule_1.default { }; if (id === constants_1.SIGN_IN_API) { return await signin_1.default(this.apiImpl, tenantId, options, userContext); - } else if (id === constants_1.AUTHORISATION_API) { - return await authorisationUrl_1.default(this.apiImpl, tenantId, options, userContext); } return false; }; diff --git a/lib/build/recipe/oauth2client/recipeImplementation.js b/lib/build/recipe/oauth2client/recipeImplementation.js index 3ea769a72..e935c9e60 100644 --- a/lib/build/recipe/oauth2client/recipeImplementation.js +++ b/lib/build/recipe/oauth2client/recipeImplementation.js @@ -7,39 +7,13 @@ var __importDefault = Object.defineProperty(exports, "__esModule", { value: true }); const recipeUserId_1 = __importDefault(require("../../recipeUserId")); const thirdpartyUtils_1 = require("../../thirdpartyUtils"); -const pkce_challenge_1 = __importDefault(require("pkce-challenge")); const __1 = require("../.."); const logger_1 = require("../../logger"); const jose_1 = require("jose"); function getRecipeImplementation(_querier, config) { let providerConfigWithOIDCInfo = null; return { - getAuthorisationRedirectURL: async function ({ providerConfig, redirectURIOnProviderDashboard }) { - const queryParams = { - client_id: providerConfig.clientId, - redirect_uri: redirectURIOnProviderDashboard, - response_type: "code", - }; - if (providerConfig.scope !== undefined) { - queryParams.scope = providerConfig.scope.join(" "); - } - let pkceCodeVerifier = undefined; - if (providerConfig.clientSecret === undefined || providerConfig.forcePKCE) { - const { code_challenge, code_verifier } = pkce_challenge_1.default(64); // According to https://www.rfc-editor.org/rfc/rfc7636, length must be between 43 and 128 - queryParams["code_challenge"] = code_challenge; - queryParams["code_challenge_method"] = "S256"; - pkceCodeVerifier = code_verifier; - } - const urlObj = new URL(providerConfig.authorizationEndpoint); - for (const [key, value] of Object.entries(queryParams)) { - urlObj.searchParams.set(key, value); - } - return { - urlWithQueryParams: urlObj.toString(), - pkceCodeVerifier: pkceCodeVerifier, - }; - }, - signIn: async function ({ userId, tenantId, userContext, oAuthTokens, rawUserInfoFromProvider }) { + signIn: async function ({ userId, tenantId, userContext, oAuthTokens, rawUserInfo }) { const user = await __1.getUser(userId, userContext); if (user === undefined) { throw new Error(`Failed to getUser from the userId ${userId} in the ${tenantId} tenant`); @@ -49,7 +23,7 @@ function getRecipeImplementation(_querier, config) { user, recipeUserId: new recipeUserId_1.default(userId), oAuthTokens, - rawUserInfoFromProvider, + rawUserInfo, }; }, getProviderConfig: async function () { @@ -84,7 +58,7 @@ function getRecipeImplementation(_querier, config) { const tokenAPIURL = providerConfig.tokenEndpoint; const accessTokenAPIParams = { client_id: providerConfig.clientId, - redirect_uri: redirectURIInfo.redirectURIOnProviderDashboard, + redirect_uri: redirectURIInfo.redirectURI, code: redirectURIInfo.redirectURIQueryParams["code"], grant_type: "authorization_code", }; @@ -110,7 +84,7 @@ function getRecipeImplementation(_querier, config) { let jwks; const accessToken = oAuthTokens["access_token"]; const idToken = oAuthTokens["id_token"]; - let rawUserInfoFromProvider = { + let rawUserInfo = { fromUserInfoAPI: {}, fromIdTokenPayload: {}, }; @@ -118,7 +92,7 @@ function getRecipeImplementation(_querier, config) { if (jwks === undefined) { jwks = jose_1.createRemoteJWKSet(new URL(providerConfig.jwksURI)); } - rawUserInfoFromProvider.fromIdTokenPayload = await thirdpartyUtils_1.verifyIdTokenFromJWKSEndpointAndGetPayload( + rawUserInfo.fromIdTokenPayload = await thirdpartyUtils_1.verifyIdTokenFromJWKSEndpointAndGetPayload( idToken, jwks, { @@ -144,26 +118,20 @@ function getRecipeImplementation(_querier, config) { `Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}` ); } - rawUserInfoFromProvider.fromUserInfoAPI = userInfoFromAccessToken.jsonResponse; + rawUserInfo.fromUserInfoAPI = userInfoFromAccessToken.jsonResponse; } let userId = undefined; - if ( - ((_a = rawUserInfoFromProvider.fromIdTokenPayload) === null || _a === void 0 ? void 0 : _a.sub) !== - undefined - ) { - userId = rawUserInfoFromProvider.fromIdTokenPayload["sub"]; - } else if ( - ((_b = rawUserInfoFromProvider.fromUserInfoAPI) === null || _b === void 0 ? void 0 : _b.sub) !== - undefined - ) { - userId = rawUserInfoFromProvider.fromUserInfoAPI["sub"]; + if (((_a = rawUserInfo.fromIdTokenPayload) === null || _a === void 0 ? void 0 : _a.sub) !== undefined) { + userId = rawUserInfo.fromIdTokenPayload["sub"]; + } else if (((_b = rawUserInfo.fromUserInfoAPI) === null || _b === void 0 ? void 0 : _b.sub) !== undefined) { + userId = rawUserInfo.fromUserInfoAPI["sub"]; } if (userId === undefined) { throw new Error(`Failed to get userId from both the idToken and userInfo endpoint.`); } return { userId, - rawUserInfoFromProvider, + rawUserInfo, }; }, }; diff --git a/lib/build/recipe/oauth2client/types.d.ts b/lib/build/recipe/oauth2client/types.d.ts index d00a4a069..c7b43e2f3 100644 --- a/lib/build/recipe/oauth2client/types.d.ts +++ b/lib/build/recipe/oauth2client/types.d.ts @@ -7,7 +7,7 @@ import { GeneralErrorResponse, User } from "../../types"; import RecipeUserId from "../../recipeUserId"; export declare type UserInfo = { userId: string; - rawUserInfoFromProvider: { + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any; }; @@ -19,12 +19,7 @@ export declare type UserInfo = { export declare type ProviderConfigInput = { clientId: string; clientSecret: string; - authorizationEndpointQueryParams?: { - [key: string]: string | null; - }; oidcDiscoveryEndpoint: string; - scope?: string[]; - forcePKCE?: boolean; }; export declare type ProviderConfigWithOIDCInfo = ProviderConfigInput & { authorizationEndpoint: string; @@ -65,19 +60,11 @@ export declare type TypeNormalisedInput = { }; }; export declare type RecipeInterface = { - getAuthorisationRedirectURL(input: { - providerConfig: ProviderConfigWithOIDCInfo; - redirectURIOnProviderDashboard: string; - userContext: UserContext; - }): Promise<{ - urlWithQueryParams: string; - pkceCodeVerifier?: string; - }>; getProviderConfig(input: { userContext: UserContext }): Promise; signIn(input: { userId: string; oAuthTokens: OAuthTokens; - rawUserInfoFromProvider: { + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any; }; @@ -92,7 +79,7 @@ export declare type RecipeInterface = { recipeUserId: RecipeUserId; user: User; oAuthTokens: OAuthTokens; - rawUserInfoFromProvider: { + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any; }; @@ -104,7 +91,7 @@ export declare type RecipeInterface = { exchangeAuthCodeForOAuthTokens(input: { providerConfig: ProviderConfigWithOIDCInfo; redirectURIInfo: { - redirectURIOnProviderDashboard: string; + redirectURI: string; redirectURIQueryParams: any; pkceCodeVerifier?: string | undefined; }; @@ -126,30 +113,15 @@ export declare type APIOptions = { appInfo: NormalisedAppinfo; }; export declare type APIInterface = { - authorisationUrlGET: - | undefined - | ((input: { - redirectURIOnProviderDashboard: string; - options: APIOptions; - userContext: UserContext; - }) => Promise< - | { - status: "OK"; - urlWithQueryParams: string; - pkceCodeVerifier?: string; - } - | GeneralErrorResponse - >); signInPOST: ( input: { tenantId: string; - session: SessionContainerInterface | undefined; options: APIOptions; userContext: UserContext; } & ( | { redirectURIInfo: { - redirectURIOnProviderDashboard: string; + redirectURI: string; redirectURIQueryParams: any; pkceCodeVerifier?: string; }; @@ -168,7 +140,7 @@ export declare type APIInterface = { oAuthTokens: { [key: string]: any; }; - rawUserInfoFromProvider: { + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any; }; diff --git a/lib/ts/recipe/oauth2client/api/authorisationUrl.ts b/lib/ts/recipe/oauth2client/api/authorisationUrl.ts deleted file mode 100644 index 80d43138c..000000000 --- a/lib/ts/recipe/oauth2client/api/authorisationUrl.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -import { send200Response } from "../../../utils"; -import STError from "../../../error"; -import { APIInterface, APIOptions } from "../"; -import { UserContext } from "../../../types"; - -export default async function authorisationUrlAPI( - apiImplementation: APIInterface, - _tenantId: string, - options: APIOptions, - userContext: UserContext -): Promise { - if (apiImplementation.authorisationUrlGET === undefined) { - return false; - } - - // TODO: Check if we can rename `redirectURIOnProviderDashboard` to a more suitable name - const redirectURIOnProviderDashboard = options.req.getKeyValueFromQuery("redirectURIOnProviderDashboard"); - - if (redirectURIOnProviderDashboard === undefined || typeof redirectURIOnProviderDashboard !== "string") { - throw new STError({ - type: STError.BAD_INPUT_ERROR, - message: "Please provide the redirectURIOnProviderDashboard as a GET param", - }); - } - - let result = await apiImplementation.authorisationUrlGET({ - redirectURIOnProviderDashboard, - options, - userContext, - }); - - send200Response(options.res, result); - return true; -} diff --git a/lib/ts/recipe/oauth2client/api/implementation.ts b/lib/ts/recipe/oauth2client/api/implementation.ts index a6f14e0cb..7e18629e0 100644 --- a/lib/ts/recipe/oauth2client/api/implementation.ts +++ b/lib/ts/recipe/oauth2client/api/implementation.ts @@ -4,19 +4,6 @@ import { OAuthTokens } from "../types"; export default function getAPIInterface(): APIInterface { return { - authorisationUrlGET: async function ({ options, redirectURIOnProviderDashboard, userContext }) { - const providerConfig = await options.recipeImplementation.getProviderConfig({ userContext }); - - const authUrl = await options.recipeImplementation.getAuthorisationRedirectURL({ - providerConfig, - redirectURIOnProviderDashboard, - userContext, - }); - return { - status: "OK", - ...authUrl, - }; - }, signInPOST: async function (input) { const { options, tenantId, userContext } = input; @@ -36,7 +23,7 @@ export default function getAPIInterface(): APIInterface { throw Error("should never come here"); } - const { userId, rawUserInfoFromProvider } = await options.recipeImplementation.getUserInfo({ + const { userId, rawUserInfo } = await options.recipeImplementation.getUserInfo({ providerConfig, oAuthTokens: oAuthTokensToUse, userContext, @@ -45,7 +32,7 @@ export default function getAPIInterface(): APIInterface { const { user, recipeUserId } = await options.recipeImplementation.signIn({ userId, tenantId, - rawUserInfoFromProvider, + rawUserInfo, oAuthTokens: oAuthTokensToUse, userContext, }); @@ -65,7 +52,7 @@ export default function getAPIInterface(): APIInterface { user, session, oAuthTokens: oAuthTokensToUse, - rawUserInfoFromProvider, + rawUserInfo, }; }, }; diff --git a/lib/ts/recipe/oauth2client/api/signin.ts b/lib/ts/recipe/oauth2client/api/signin.ts index 663af60e4..6e89436f9 100644 --- a/lib/ts/recipe/oauth2client/api/signin.ts +++ b/lib/ts/recipe/oauth2client/api/signin.ts @@ -34,17 +34,17 @@ export default async function signInAPI( let redirectURIInfo: | undefined | { - redirectURIOnProviderDashboard: string; + redirectURI: string; redirectURIQueryParams: any; pkceCodeVerifier?: string; }; let oAuthTokens: any; if (bodyParams.redirectURIInfo !== undefined) { - if (bodyParams.redirectURIInfo.redirectURIOnProviderDashboard === undefined) { + if (bodyParams.redirectURIInfo.redirectURI === undefined) { throw new STError({ type: STError.BAD_INPUT_ERROR, - message: "Please provide the redirectURIOnProviderDashboard in request body", + message: "Please provide the redirectURI in request body", }); } redirectURIInfo = bodyParams.redirectURIInfo; @@ -75,7 +75,6 @@ export default async function signInAPI( tenantId, redirectURIInfo, oAuthTokens, - session, options, userContext, }); diff --git a/lib/ts/recipe/oauth2client/constants.ts b/lib/ts/recipe/oauth2client/constants.ts index 545ef08f1..8e45f0567 100644 --- a/lib/ts/recipe/oauth2client/constants.ts +++ b/lib/ts/recipe/oauth2client/constants.ts @@ -13,6 +13,4 @@ * under the License. */ -export const AUTHORISATION_API = "/oauth2client/authorisationurl"; - -export const SIGN_IN_API = "/oauth2client/signin"; +export const SIGN_IN_API = "/oauth/client/signin"; diff --git a/lib/ts/recipe/oauth2client/index.ts b/lib/ts/recipe/oauth2client/index.ts index 0ae16a19d..d2b2e2a02 100644 --- a/lib/ts/recipe/oauth2client/index.ts +++ b/lib/ts/recipe/oauth2client/index.ts @@ -20,25 +20,9 @@ import { RecipeInterface, APIInterface, APIOptions, OAuthTokens } from "./types" export default class Wrapper { static init = Recipe.init; - static async getAuthorisationRedirectURL( - redirectURIOnProviderDashboard: string, - userContext?: Record - ) { - const recipeInterfaceImpl = Recipe.getInstanceOrThrowError().recipeInterfaceImpl; - const normalisedUserContext = getUserContext(userContext); - const providerConfig = await recipeInterfaceImpl.getProviderConfig({ - userContext: normalisedUserContext, - }); - return await recipeInterfaceImpl.getAuthorisationRedirectURL({ - providerConfig, - redirectURIOnProviderDashboard, - userContext: normalisedUserContext, - }); - } - static async exchangeAuthCodeForOAuthTokens( redirectURIInfo: { - redirectURIOnProviderDashboard: string; + redirectURI: string; redirectURIQueryParams: any; pkceCodeVerifier?: string | undefined; }, @@ -72,8 +56,6 @@ export default class Wrapper { export let init = Wrapper.init; -export let getAuthorisationRedirectURL = Wrapper.getAuthorisationRedirectURL; - export let exchangeAuthCodeForOAuthTokens = Wrapper.exchangeAuthCodeForOAuthTokens; export let getUserInfo = Wrapper.getUserInfo; diff --git a/lib/ts/recipe/oauth2client/recipe.ts b/lib/ts/recipe/oauth2client/recipe.ts index 9dfc98a90..7da475c5c 100644 --- a/lib/ts/recipe/oauth2client/recipe.ts +++ b/lib/ts/recipe/oauth2client/recipe.ts @@ -18,10 +18,9 @@ import { NormalisedAppinfo, APIHandled, RecipeListFunction, HTTPMethod, UserCont import { TypeInput, TypeNormalisedInput, RecipeInterface, APIInterface } from "./types"; import { validateAndNormaliseUserInput } from "./utils"; import STError from "../../error"; -import { SIGN_IN_API, AUTHORISATION_API } from "./constants"; +import { SIGN_IN_API } from "./constants"; import NormalisedURLPath from "../../normalisedURLPath"; import signInAPI from "./api/signin"; -import authorisationUrlAPI from "./api/authorisationUrl"; import RecipeImplementation from "./recipeImplementation"; import APIImplementation from "./api/implementation"; import { Querier } from "../../querier"; @@ -97,12 +96,6 @@ export default class Recipe extends RecipeModule { id: SIGN_IN_API, disabled: this.apiImpl.signInPOST === undefined, }, - { - method: "get", - pathWithoutApiBasePath: new NormalisedURLPath(AUTHORISATION_API), - id: AUTHORISATION_API, - disabled: this.apiImpl.authorisationUrlGET === undefined, - }, ]; }; @@ -126,8 +119,6 @@ export default class Recipe extends RecipeModule { }; if (id === SIGN_IN_API) { return await signInAPI(this.apiImpl, tenantId, options, userContext); - } else if (id === AUTHORISATION_API) { - return await authorisationUrlAPI(this.apiImpl, tenantId, options, userContext); } return false; }; diff --git a/lib/ts/recipe/oauth2client/recipeImplementation.ts b/lib/ts/recipe/oauth2client/recipeImplementation.ts index 11b277965..a5115c815 100644 --- a/lib/ts/recipe/oauth2client/recipeImplementation.ts +++ b/lib/ts/recipe/oauth2client/recipeImplementation.ts @@ -15,7 +15,6 @@ import { getOIDCDiscoveryInfo, verifyIdTokenFromJWKSEndpointAndGetPayload, } from "../../thirdpartyUtils"; -import pkceChallenge from "pkce-challenge"; import { getUser } from "../.."; import { logDebugMessage } from "../../logger"; import { JWTVerifyGetKey, createRemoteJWKSet } from "jose"; @@ -24,52 +23,18 @@ export default function getRecipeImplementation(_querier: Querier, config: TypeN let providerConfigWithOIDCInfo: ProviderConfigWithOIDCInfo | null = null; return { - getAuthorisationRedirectURL: async function ( - this: RecipeInterface, - { providerConfig, redirectURIOnProviderDashboard } - ) { - const queryParams: { [key: string]: string } = { - client_id: providerConfig.clientId, - redirect_uri: redirectURIOnProviderDashboard, - response_type: "code", - }; - - if (providerConfig.scope !== undefined) { - queryParams.scope = providerConfig.scope.join(" "); - } - - let pkceCodeVerifier: string | undefined = undefined; - - if (providerConfig.clientSecret === undefined || providerConfig.forcePKCE) { - const { code_challenge, code_verifier } = pkceChallenge(64); // According to https://www.rfc-editor.org/rfc/rfc7636, length must be between 43 and 128 - queryParams["code_challenge"] = code_challenge; - queryParams["code_challenge_method"] = "S256"; - pkceCodeVerifier = code_verifier; - } - - const urlObj = new URL(providerConfig.authorizationEndpoint); - - for (const [key, value] of Object.entries(queryParams)) { - urlObj.searchParams.set(key, value); - } - - return { - urlWithQueryParams: urlObj.toString(), - pkceCodeVerifier: pkceCodeVerifier, - }; - }, signIn: async function ({ userId, tenantId, userContext, oAuthTokens, - rawUserInfoFromProvider, + rawUserInfo, }): Promise<{ status: "OK"; user: UserType; recipeUserId: RecipeUserId; oAuthTokens: OAuthTokens; - rawUserInfoFromProvider: { + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any }; fromUserInfoAPI?: { [key: string]: any }; }; @@ -85,7 +50,7 @@ export default function getRecipeImplementation(_querier: Querier, config: TypeN user, recipeUserId: new RecipeUserId(userId), oAuthTokens, - rawUserInfoFromProvider, + rawUserInfo, }; }, getProviderConfig: async function () { @@ -123,7 +88,7 @@ export default function getRecipeImplementation(_querier: Querier, config: TypeN const tokenAPIURL = providerConfig.tokenEndpoint; const accessTokenAPIParams: { [key: string]: string } = { client_id: providerConfig.clientId, - redirect_uri: redirectURIInfo.redirectURIOnProviderDashboard, + redirect_uri: redirectURIInfo.redirectURI, code: redirectURIInfo.redirectURIQueryParams["code"], grant_type: "authorization_code", }; @@ -153,7 +118,7 @@ export default function getRecipeImplementation(_querier: Querier, config: TypeN const accessToken = oAuthTokens["access_token"]; const idToken = oAuthTokens["id_token"]; - let rawUserInfoFromProvider: { + let rawUserInfo: { fromUserInfoAPI: any; fromIdTokenPayload: any; } = { @@ -166,13 +131,9 @@ export default function getRecipeImplementation(_querier: Querier, config: TypeN jwks = createRemoteJWKSet(new URL(providerConfig.jwksURI)); } - rawUserInfoFromProvider.fromIdTokenPayload = await verifyIdTokenFromJWKSEndpointAndGetPayload( - idToken, - jwks, - { - audience: providerConfig.clientId, - } - ); + rawUserInfo.fromIdTokenPayload = await verifyIdTokenFromJWKSEndpointAndGetPayload(idToken, jwks, { + audience: providerConfig.clientId, + }); } if (accessToken && providerConfig.userInfoEndpoint !== undefined) { @@ -196,15 +157,15 @@ export default function getRecipeImplementation(_querier: Querier, config: TypeN ); } - rawUserInfoFromProvider.fromUserInfoAPI = userInfoFromAccessToken.jsonResponse; + rawUserInfo.fromUserInfoAPI = userInfoFromAccessToken.jsonResponse; } let userId: string | undefined = undefined; - if (rawUserInfoFromProvider.fromIdTokenPayload?.sub !== undefined) { - userId = rawUserInfoFromProvider.fromIdTokenPayload["sub"]; - } else if (rawUserInfoFromProvider.fromUserInfoAPI?.sub !== undefined) { - userId = rawUserInfoFromProvider.fromUserInfoAPI["sub"]; + if (rawUserInfo.fromIdTokenPayload?.sub !== undefined) { + userId = rawUserInfo.fromIdTokenPayload["sub"]; + } else if (rawUserInfo.fromUserInfoAPI?.sub !== undefined) { + userId = rawUserInfo.fromUserInfoAPI["sub"]; } if (userId === undefined) { @@ -213,7 +174,7 @@ export default function getRecipeImplementation(_querier: Querier, config: TypeN return { userId, - rawUserInfoFromProvider, + rawUserInfo, }; }, }; diff --git a/lib/ts/recipe/oauth2client/types.ts b/lib/ts/recipe/oauth2client/types.ts index 75d3a55c2..0c40c9bdc 100644 --- a/lib/ts/recipe/oauth2client/types.ts +++ b/lib/ts/recipe/oauth2client/types.ts @@ -22,16 +22,13 @@ import RecipeUserId from "../../recipeUserId"; export type UserInfo = { userId: string; - rawUserInfoFromProvider: { fromIdTokenPayload?: { [key: string]: any }; fromUserInfoAPI?: { [key: string]: any } }; + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any }; fromUserInfoAPI?: { [key: string]: any } }; }; export type ProviderConfigInput = { clientId: string; clientSecret: string; - authorizationEndpointQueryParams?: { [key: string]: string | null }; oidcDiscoveryEndpoint: string; - scope?: string[]; - forcePKCE?: boolean; }; export type ProviderConfigWithOIDCInfo = ProviderConfigInput & { @@ -78,20 +75,12 @@ export type TypeNormalisedInput = { }; export type RecipeInterface = { - getAuthorisationRedirectURL(input: { - providerConfig: ProviderConfigWithOIDCInfo; - redirectURIOnProviderDashboard: string; - userContext: UserContext; - }): Promise<{ - urlWithQueryParams: string; - pkceCodeVerifier?: string; - }>; getProviderConfig(input: { userContext: UserContext }): Promise; signIn(input: { userId: string; oAuthTokens: OAuthTokens; - rawUserInfoFromProvider: { + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any }; fromUserInfoAPI?: { [key: string]: any }; }; @@ -102,7 +91,7 @@ export type RecipeInterface = { recipeUserId: RecipeUserId; user: User; oAuthTokens: OAuthTokens; - rawUserInfoFromProvider: { + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any }; fromUserInfoAPI?: { [key: string]: any }; }; @@ -110,7 +99,7 @@ export type RecipeInterface = { exchangeAuthCodeForOAuthTokens(input: { providerConfig: ProviderConfigWithOIDCInfo; redirectURIInfo: { - redirectURIOnProviderDashboard: string; + redirectURI: string; redirectURIQueryParams: any; pkceCodeVerifier?: string | undefined; }; @@ -134,31 +123,15 @@ export type APIOptions = { }; export type APIInterface = { - authorisationUrlGET: - | undefined - | ((input: { - redirectURIOnProviderDashboard: string; - options: APIOptions; - userContext: UserContext; - }) => Promise< - | { - status: "OK"; - urlWithQueryParams: string; - pkceCodeVerifier?: string; - } - | GeneralErrorResponse - >); - signInPOST: ( input: { tenantId: string; - session: SessionContainerInterface | undefined; options: APIOptions; userContext: UserContext; } & ( | { redirectURIInfo: { - redirectURIOnProviderDashboard: string; + redirectURI: string; redirectURIQueryParams: any; pkceCodeVerifier?: string; }; @@ -173,7 +146,7 @@ export type APIInterface = { user: User; session: SessionContainerInterface; oAuthTokens: { [key: string]: any }; - rawUserInfoFromProvider: { + rawUserInfo: { fromIdTokenPayload?: { [key: string]: any }; fromUserInfoAPI?: { [key: string]: any }; };