🔐 OIDC back-channel logout (#521)

* feat: oidc backchannel session storage
* feat: oidc backchannel logout
* ref: e2e test
* 🛠️ Code review
* ♻️ Do not mock internal auth token but call "/login" with oidc_token instead
* ♻️ Refactoring for back-channel logout test
* fix: feedback and e2e tests
* feat: more e2e tests
* ♻️ Added test to test multiple login requests flow
* ref: jwt sid verifier and e2e tests

---------

Co-authored-by: Monta <monta@HP-ProBook-445-14-inch-G9-Notebook-PC-505aadfc.localdomain>
Co-authored-by: Anton SHEPILOV <ashepilov@linagora.com>
This commit is contained in:
Montassar Ghanmy
2024-05-24 12:52:58 +01:00
committed by GitHub
parent c8a9145906
commit b4412d3ed3
22 changed files with 426 additions and 22 deletions
@@ -10,6 +10,7 @@ import {
ConsoleHookResponse,
ConsoleHookUser,
ConsoleType,
ConsoleBackchannelLogoutRequest,
} from "../types";
import Company from "../../user/entities/company";
import { CrudException } from "../../../core/platform/framework/api/crud-service";
@@ -132,6 +133,7 @@ export class ConsoleController {
access_token: gr.platformServices.auth.generateJWT(
request.currentUser.id,
request.currentUser.email,
request.currentUser.sid,
{
track: request.currentUser?.allow_tracking || false,
provider_id: request.currentUser.identity_provider_id,
@@ -287,7 +289,7 @@ export class ConsoleController {
logger.warn("ERROR_NOTONPROD: YOU ARE RUNNING IN DEVELOPMENT MODE, AUTH IS DISABLED!!!");
}
return gr.platformServices.auth.generateJWT(user.id, user.email_canonical, {
return gr.platformServices.auth.generateJWT(user.id, user.email_canonical, "", {
track: user?.preferences?.allow_tracking || false,
provider_id: user.identity_provider_id,
});
@@ -297,12 +299,34 @@ export class ConsoleController {
const client = gr.services.console.getClient();
const userDTO = await client.getUserByAccessToken(idToken);
const user = await client.updateLocalUserFromConsole(userDTO);
if (!user) {
throw CrudException.notFound(`User details not found for access token ${idToken}`);
}
return gr.platformServices.auth.generateJWT(user.id, user.email_canonical, {
// update the user session
const session = await client.updateUserSession(idToken);
return gr.platformServices.auth.generateJWT(user.id, user.email_canonical, session, {
track: user?.preferences?.allow_tracking || false,
provider_id: user.identity_provider_id,
});
}
async backChannelLogout(
request: FastifyRequest<{ Body: ConsoleBackchannelLogoutRequest }>,
reply: FastifyReply,
): Promise<void> {
try {
const logoutToken = request.body.logout_token;
if (!logoutToken) {
throw new CrudException("Missing logout_token", 400);
}
await gr.services.console.getClient().backChannelLogout(logoutToken);
reply.status(200).send({ success: true });
} catch (e) {
logger.error(e.message);
reply.status(400).send({ error: e.message });
}
}
}
@@ -51,6 +51,12 @@ const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next)
handler: controller.resendVerificationEmail.bind(controller),
});
fastify.route({
method: "POST",
url: "/backchannel_logout",
handler: controller.backChannelLogout.bind(controller),
});
next();
};