🔐 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
@@ -24,6 +24,7 @@ export default interface AuthServiceAPI extends TdriveServiceProvider {
generateJWT(
userId: uuid,
email: string,
session: string,
options: {
track: boolean;
provider_id: string;
@@ -31,6 +31,7 @@ export class AuthService implements AuthServiceAPI {
generateJWT(
userId: uuid,
email: string,
session: string,
options: {
track: boolean;
provider_id: string;
@@ -54,6 +55,7 @@ export class AuthService implements AuthServiceAPI {
iat: now - 60 * 10,
nbf: now - 60 * 10,
sub: userId,
sid: session,
email: email,
track: !!options.track,
provider_id: options.provider_id || "",
@@ -66,6 +68,7 @@ export class AuthService implements AuthServiceAPI {
iat: now - 60 * 10,
nbf: now - 60 * 10,
sub: userId,
sid: session,
email: email,
track: !!options.track,
provider_id: options.provider_id || "",
@@ -5,8 +5,9 @@ import fp from "fastify-plugin";
import config from "../../../../config";
import { JwtType } from "../../types";
import { executionStorage } from "../../../framework/execution-storage";
import gr from "../../../../../services/global-resolver";
const jwtPlugin: FastifyPluginCallback = (fastify, _opts, next) => {
const jwtPlugin: FastifyPluginCallback = async (fastify, _opts, next) => {
fastify.register(cookie);
fastify.register(fastifyJwt, {
secret: config.get("auth.jwt.secret"),
@@ -18,6 +19,10 @@ const jwtPlugin: FastifyPluginCallback = (fastify, _opts, next) => {
const authenticate = async (request: FastifyRequest) => {
const jwt: JwtType = await request.jwtVerify();
// Verify the SID exists and is valid
await gr.services.console.getClient().verifyJwtSid(jwt.sid);
if (jwt.type === "refresh") {
// TODO in the future we must invalidate the refresh token (because it should be single use)
}
@@ -25,6 +30,7 @@ const jwtPlugin: FastifyPluginCallback = (fastify, _opts, next) => {
request.currentUser = {
...{ email: jwt.email },
...{ id: jwt.sub },
...{ sid: jwt.sid },
...{ identity_provider_id: jwt.provider_id },
...{ application_id: jwt.application_id || null },
...{ server_request: jwt.server_request || false },
@@ -107,8 +107,8 @@ export function toMongoDbOrderable(timeuuid?: string): string {
/**
* Check if filtering is necessary
* @param {string} key
* @returns {boolean} Returns true if key is "is_in_trash" or "scope", otherwise returns false.
* @returns {boolean} Returns true if key is "is_in_trash", "scope" or "sub", otherwise returns false.
*/
export const filteringRequired = (key: string) => {
return key === "is_in_trash" || key === "scope";
return key === "is_in_trash" || key === "scope" || key === "sub";
};
@@ -1,6 +1,7 @@
export type JwtType = {
type: "access" | "refresh";
sub: string;
sid: string;
provider_id: string; //Console sub
email: string;
application_id?: string;