Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: OAuth2Client interface changes #904

Merged
merged 1 commit into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions lib/build/recipe/oauth2client/api/authorisationUrl.d.ts

This file was deleted.

44 changes: 0 additions & 44 deletions lib/build/recipe/oauth2client/api/authorisationUrl.js

This file was deleted.

15 changes: 3 additions & 12 deletions lib/build/recipe/oauth2client/api/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand All @@ -32,15 +23,15 @@ 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,
});
const { user, recipeUserId } = await options.recipeImplementation.signIn({
userId,
tenantId,
rawUserInfoFromProvider,
rawUserInfo,
oAuthTokens: oAuthTokensToUse,
userContext,
});
Expand All @@ -58,7 +49,7 @@ function getAPIInterface() {
user,
session,
oAuthTokens: oAuthTokensToUse,
rawUserInfoFromProvider,
rawUserInfo,
};
},
};
Expand Down
5 changes: 2 additions & 3 deletions lib/build/recipe/oauth2client/api/signin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -61,7 +61,6 @@ async function signInAPI(apiImplementation, tenantId, options, userContext) {
tenantId,
redirectURIInfo,
oAuthTokens,
session,
options,
userContext,
});
Expand Down
3 changes: 1 addition & 2 deletions lib/build/recipe/oauth2client/constants.d.ts
Original file line number Diff line number Diff line change
@@ -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";
5 changes: 2 additions & 3 deletions lib/build/recipe/oauth2client/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
10 changes: 1 addition & 9 deletions lib/build/recipe/oauth2client/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, any>
): Promise<{
urlWithQueryParams: string;
pkceCodeVerifier?: string | undefined;
}>;
static exchangeAuthCodeForOAuthTokens(
redirectURIInfo: {
redirectURIOnProviderDashboard: string;
redirectURI: string;
redirectURIQueryParams: any;
pkceCodeVerifier?: string | undefined;
},
Expand All @@ -24,7 +17,6 @@ export default class Wrapper {
): Promise<import("./types").UserInfo>;
}
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 };
15 changes: 1 addition & 14 deletions lib/build/recipe/oauth2client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
9 changes: 0 additions & 9 deletions lib/build/recipe/oauth2client/recipe.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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) => {
Expand All @@ -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;
};
Expand Down
54 changes: 11 additions & 43 deletions lib/build/recipe/oauth2client/recipeImplementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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`);
Expand All @@ -49,7 +23,7 @@ function getRecipeImplementation(_querier, config) {
user,
recipeUserId: new recipeUserId_1.default(userId),
oAuthTokens,
rawUserInfoFromProvider,
rawUserInfo,
};
},
getProviderConfig: async function () {
Expand Down Expand Up @@ -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",
};
Expand All @@ -110,15 +84,15 @@ function getRecipeImplementation(_querier, config) {
let jwks;
const accessToken = oAuthTokens["access_token"];
const idToken = oAuthTokens["id_token"];
let rawUserInfoFromProvider = {
let rawUserInfo = {
fromUserInfoAPI: {},
fromIdTokenPayload: {},
};
if (idToken && providerConfig.jwksURI !== undefined) {
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,
{
Expand All @@ -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,
};
},
};
Expand Down
Loading
Loading