Skip to content

Commit

Permalink
feat: OAuth2Client interface changes
Browse files Browse the repository at this point in the history
  • Loading branch information
anku255 committed Aug 5, 2024
1 parent f53853c commit d3fc88e
Show file tree
Hide file tree
Showing 19 changed files with 56 additions and 369 deletions.
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

0 comments on commit d3fc88e

Please sign in to comment.