From 3b79f91ae96b47338a404324d670331e4f309670 Mon Sep 17 00:00:00 2001 From: Enguerran Weiss Date: Tue, 10 Sep 2024 17:32:16 +0200 Subject: [PATCH] provide idToken from front to back to make auth provider logout urls --- .../createInclusionConnectedAllowedRouter.ts | 4 +++- .../inclusionConnectedAllowed.e2e.test.ts | 7 ++++++- .../adapters/oauth-gateway/HttpOAuthGateway.ts | 3 +++ .../adapters/oauth-gateway/InMemoryOAuthGateway.ts | 4 +++- .../oauth-gateway/inclusionConnect.routes.ts | 1 + .../adapters/oauth-gateway/proConnect.routes.ts | 1 + .../inclusion-connect/port/OAuthGateway.ts | 7 +++++-- .../use-cases/GetInclusionConnectLogoutUrl.ts | 11 +++++++---- .../GetInclusionConnectLogoutUrl.unit.test.ts | 6 +++++- .../HttpInclusionConnectedGateway.ts | 5 +++-- front/src/core-logic/domain/auth/auth.epics.ts | 13 ++++++++++++- .../core-logic/ports/InclusionConnectedGateway.ts | 8 +++----- .../inclusionConnectedAllowed.schema.ts | 2 +- 13 files changed, 53 insertions(+), 19 deletions(-) diff --git a/back/src/adapters/primary/routers/inclusionConnect/createInclusionConnectedAllowedRouter.ts b/back/src/adapters/primary/routers/inclusionConnect/createInclusionConnectedAllowedRouter.ts index 66639a7d5a..391cc32c2d 100644 --- a/back/src/adapters/primary/routers/inclusionConnect/createInclusionConnectedAllowedRouter.ts +++ b/back/src/adapters/primary/routers/inclusionConnect/createInclusionConnectedAllowedRouter.ts @@ -38,7 +38,9 @@ export const createInclusionConnectedAllowedRouter = ( inclusionConnectedSharedRoutes.getInclusionConnectLogoutUrl((req, res) => sendHttpResponse(req, res, () => - deps.useCases.inclusionConnectLogout.execute(), + deps.useCases.inclusionConnectLogout.execute({ + idToken: req.query.idToken, + }), ), ); diff --git a/back/src/adapters/primary/routers/inclusionConnect/inclusionConnectedAllowed.e2e.test.ts b/back/src/adapters/primary/routers/inclusionConnect/inclusionConnectedAllowed.e2e.test.ts index 691121bf9c..6d8f847128 100644 --- a/back/src/adapters/primary/routers/inclusionConnect/inclusionConnectedAllowed.e2e.test.ts +++ b/back/src/adapters/primary/routers/inclusionConnect/inclusionConnectedAllowed.e2e.test.ts @@ -389,13 +389,18 @@ describe("InclusionConnectedAllowedRoutes", () => { inclusionConnectedAllowedRoutes.getInclusionConnectLogoutUrl, )} returns the logout url`, () => { it("returns a correct logout url with status 200", async () => { - const response = await httpClient.getInclusionConnectLogoutUrl(); + const response = await httpClient.getInclusionConnectLogoutUrl({ + queryParams: { + idToken: "fake-id-token", + }, + }); expectHttpResponseToEqual(response, { body: `${ appConfig.inclusionConnectConfig.providerBaseUri }/logout-inclusion-connect?${queryParamsAsString({ postLogoutRedirectUrl: appConfig.immersionFacileBaseUrl, clientId: appConfig.inclusionConnectConfig.clientId, + idToken: "fake-id-token", })}`, status: 200, }); diff --git a/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/HttpOAuthGateway.ts b/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/HttpOAuthGateway.ts index 4e46f94ba2..f09916d32b 100644 --- a/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/HttpOAuthGateway.ts +++ b/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/HttpOAuthGateway.ts @@ -1,5 +1,6 @@ import { AbsoluteUrl, + WithIdToken, WithSourcePage, decodeJwtWithoutSignatureCheck, errors, @@ -206,6 +207,7 @@ export class HttpOAuthGateway implements OAuthGateway { } public async getLogoutUrl( + params: WithIdToken, provider: OAuthGatewayProvider, ): Promise { const uri: AbsoluteUrl = @@ -217,6 +219,7 @@ export class HttpOAuthGateway implements OAuthGateway { client_id: this.inclusionConnectConfig.clientId, post_logout_redirect_uri: this.inclusionConnectConfig.immersionRedirectUri.afterLogout, + id_token: params.idToken, })}`; } diff --git a/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/InMemoryOAuthGateway.ts b/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/InMemoryOAuthGateway.ts index fe3364a38a..447eefc105 100644 --- a/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/InMemoryOAuthGateway.ts +++ b/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/InMemoryOAuthGateway.ts @@ -1,4 +1,4 @@ -import { AbsoluteUrl, queryParamsAsString } from "shared"; +import { AbsoluteUrl, WithIdToken, queryParamsAsString } from "shared"; import { OAuthConfig } from "../../../../../../config/bootstrap/appConfig"; import { GetAccessTokenParams, @@ -42,6 +42,7 @@ export class InMemoryOAuthGateway implements OAuthGateway { } public async getLogoutUrl( + params: WithIdToken, provider: OAuthGatewayProvider, ): Promise { const logoutUri: Record = { @@ -53,6 +54,7 @@ export class InMemoryOAuthGateway implements OAuthGateway { postLogoutRedirectUrl: this.providerConfig.immersionRedirectUri.afterLogout, clientId: this.providerConfig.clientId, + idToken: params.idToken, })}`; } diff --git a/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/inclusionConnect.routes.ts b/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/inclusionConnect.routes.ts index a988c90f82..ee0af77f1e 100644 --- a/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/inclusionConnect.routes.ts +++ b/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/inclusionConnect.routes.ts @@ -29,6 +29,7 @@ const withContentTypeUrlEncodedSchema = z.object({ export type InclusionConnectLogoutQueryParams = { client_id: string; post_logout_redirect_uri: AbsoluteUrl; + id_token: string; }; export type InclusionConnectRoutes = ReturnType< diff --git a/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/proConnect.routes.ts b/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/proConnect.routes.ts index 5d982f0b83..ddd1b1406e 100644 --- a/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/proConnect.routes.ts +++ b/back/src/domains/core/authentication/inclusion-connect/adapters/oauth-gateway/proConnect.routes.ts @@ -29,6 +29,7 @@ const withContentTypeUrlEncodedSchema = z.object({ export type ProConnectLogoutQueryParams = { client_id: string; post_logout_redirect_uri: AbsoluteUrl; + id_token: string; }; export type ProConnectRoutes = ReturnType; diff --git a/back/src/domains/core/authentication/inclusion-connect/port/OAuthGateway.ts b/back/src/domains/core/authentication/inclusion-connect/port/OAuthGateway.ts index 38d36169bb..591984ce82 100644 --- a/back/src/domains/core/authentication/inclusion-connect/port/OAuthGateway.ts +++ b/back/src/domains/core/authentication/inclusion-connect/port/OAuthGateway.ts @@ -4,10 +4,10 @@ import { ExternalId, FeatureFlags, IdToken, + WithIdToken, WithSourcePage, } from "shared"; import { OAuthJwt } from "../entities/OngoingOAuth"; -import { z } from "zod"; export type GetAccessTokenParams = WithSourcePage & { code: string; @@ -51,5 +51,8 @@ export interface OAuthGateway { params: GetAccessTokenParams, provider: OAuthGatewayProvider, ) => Promise; - getLogoutUrl(mode: OAuthGatewayProvider): Promise; + getLogoutUrl( + params: WithIdToken, + provider: OAuthGatewayProvider, + ): Promise; } diff --git a/back/src/domains/core/authentication/inclusion-connect/use-cases/GetInclusionConnectLogoutUrl.ts b/back/src/domains/core/authentication/inclusion-connect/use-cases/GetInclusionConnectLogoutUrl.ts index 413ceff862..16c9847c59 100644 --- a/back/src/domains/core/authentication/inclusion-connect/use-cases/GetInclusionConnectLogoutUrl.ts +++ b/back/src/domains/core/authentication/inclusion-connect/use-cases/GetInclusionConnectLogoutUrl.ts @@ -1,12 +1,11 @@ -import { AbsoluteUrl } from "shared"; -import { z } from "zod"; +import { AbsoluteUrl, WithIdToken, withIdTokenSchema } from "shared"; import { TransactionalUseCase } from "../../../UseCase"; import { UnitOfWork } from "../../../unit-of-work/ports/UnitOfWork"; import { UnitOfWorkPerformer } from "../../../unit-of-work/ports/UnitOfWorkPerformer"; import { OAuthGateway, oAuthModeByFeatureFlags } from "../port/OAuthGateway"; export class GetInclusionConnectLogoutUrl extends TransactionalUseCase< - void, + WithIdToken, AbsoluteUrl > { protected inputSchema = withIdTokenSchema; @@ -18,8 +17,12 @@ export class GetInclusionConnectLogoutUrl extends TransactionalUseCase< super(uowPerformer); } - public async _execute(_: void, uow: UnitOfWork): Promise { + public async _execute( + params: WithIdToken, + uow: UnitOfWork, + ): Promise { return this.inclusionConnectGateway.getLogoutUrl( + params, oAuthModeByFeatureFlags(await uow.featureFlagRepository.getAll()), ); } diff --git a/back/src/domains/core/authentication/inclusion-connect/use-cases/GetInclusionConnectLogoutUrl.unit.test.ts b/back/src/domains/core/authentication/inclusion-connect/use-cases/GetInclusionConnectLogoutUrl.unit.test.ts index 1479a172b9..5b4d8d8d23 100644 --- a/back/src/domains/core/authentication/inclusion-connect/use-cases/GetInclusionConnectLogoutUrl.unit.test.ts +++ b/back/src/domains/core/authentication/inclusion-connect/use-cases/GetInclusionConnectLogoutUrl.unit.test.ts @@ -32,14 +32,18 @@ describe("GetInclusionConnectLogoutUrl", () => { it("returns the inclusion connect logout url from %s", async () => { const logoutSuffixe = mode === "ProConnect" ? "pro-connect" : "inclusion-connect"; + const idToken = "fake-id-token"; expectToEqual( - await getInclusionConnectLogoutUrl.execute(), + await getInclusionConnectLogoutUrl.execute({ + idToken, + }), `${ fakeProviderConfig.providerBaseUri }/logout-${logoutSuffixe}?${queryParamsAsString({ postLogoutRedirectUrl: fakeProviderConfig.immersionRedirectUri.afterLogout, clientId: fakeProviderConfig.clientId, + idToken, })}`, ); }); diff --git a/front/src/core-logic/adapters/InclusionConnected/HttpInclusionConnectedGateway.ts b/front/src/core-logic/adapters/InclusionConnected/HttpInclusionConnectedGateway.ts index 38f7ce0f8f..e57bd694df 100644 --- a/front/src/core-logic/adapters/InclusionConnected/HttpInclusionConnectedGateway.ts +++ b/front/src/core-logic/adapters/InclusionConnected/HttpInclusionConnectedGateway.ts @@ -7,6 +7,7 @@ import { InclusionConnectedAllowedRoutes, InclusionConnectedUser, MarkPartnersErroredConventionAsHandledRequest, + WithIdToken, makeRejection, } from "shared"; import { HttpClient } from "shared-routes"; @@ -66,11 +67,11 @@ export class HttpInclusionConnectedGateway ); } - public getLogoutUrl$({ idToken }): Observable { + public getLogoutUrl$({ idToken }: WithIdToken): Observable { return from( this.httpClient .getInclusionConnectLogoutUrl({ - idToken, + queryParams: { idToken }, }) .then((response) => match(response) diff --git a/front/src/core-logic/domain/auth/auth.epics.ts b/front/src/core-logic/domain/auth/auth.epics.ts index c3cf266928..2076d146ae 100644 --- a/front/src/core-logic/domain/auth/auth.epics.ts +++ b/front/src/core-logic/domain/auth/auth.epics.ts @@ -57,7 +57,18 @@ const logoutFromInclusionConnect: AuthEpic = ( state$.value.auth.federatedIdentityWithUser?.provider === "inclusionConnect" && action.payload.mode === "device-and-inclusion", ), - switchMap(() => inclusionConnectedGateway.getLogoutUrl$()), + switchMap(() => { + return state$.value.auth.federatedIdentityWithUser?.provider === + "peConnect" + ? inclusionConnectedGateway.getLogoutUrl$({ + idToken: "", + }) + : inclusionConnectedGateway.getLogoutUrl$({ + idToken: state$.value.auth.federatedIdentityWithUser + ? state$.value.auth.federatedIdentityWithUser.idToken + : "", + }); + }), map((logoutUrl) => { navigationGateway.goToUrl(logoutUrl); return authSlice.actions.loggedOutSuccessfullyFromInclusionConnect(); diff --git a/front/src/core-logic/ports/InclusionConnectedGateway.ts b/front/src/core-logic/ports/InclusionConnectedGateway.ts index 1f9faede04..00016248dd 100644 --- a/front/src/core-logic/ports/InclusionConnectedGateway.ts +++ b/front/src/core-logic/ports/InclusionConnectedGateway.ts @@ -5,9 +5,9 @@ import { ConventionSupportedJwt, DiscussionReadDto, DiscussionRejected, - IdToken, InclusionConnectedUser, MarkPartnersErroredConventionAsHandledRequest, + WithIdToken, } from "shared"; import { FetchDiscussionRequestedPayload } from "../domain/discussion/discussion.slice"; @@ -24,10 +24,8 @@ export interface InclusionConnectedGateway { getDiscussionById$( payload: FetchDiscussionRequestedPayload, ): Observable; - getLogoutUrl$(payload: { - idToken: IdToken; - }): Observable; - updateDiscussiokenonStatus$( + getLogoutUrl$(payload: WithIdToken): Observable; + updateDiscussionStatus$( payload: { jwt: ConventionSupportedJwt; discussionId: string; diff --git a/shared/src/inclusionConnectedAllowed/inclusionConnectedAllowed.schema.ts b/shared/src/inclusionConnectedAllowed/inclusionConnectedAllowed.schema.ts index 2e1831bf64..b313c247cc 100644 --- a/shared/src/inclusionConnectedAllowed/inclusionConnectedAllowed.schema.ts +++ b/shared/src/inclusionConnectedAllowed/inclusionConnectedAllowed.schema.ts @@ -3,6 +3,7 @@ import { absoluteUrlSchema } from "../AbsoluteUrl"; import { agencySchema } from "../agency/agency.schema"; import { discussionIdSchema } from "../discussion/discussion.schema"; import { emailSchema } from "../email/email.schema"; +import { IdToken } from "../inclusionConnect/inclusionConnect.dto"; import { establishmentsRoles } from "../role/role.dto"; import { dateTimeIsoStringSchema } from "../schedule/Schedule.schema"; import { siretSchema } from "../siret/siret.schema"; @@ -17,7 +18,6 @@ import { WithEstablismentsSiretAndName, allAgencyRoles, } from "./inclusionConnectedAllowed.dto"; -import { IdToken } from "../inclusionConnect/inclusionConnect.dto"; export const agencyRoleSchema = z.enum(allAgencyRoles);