From 3448af6e170b4e054a3eeb42e713c4880e48b41f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 30 Jan 2024 17:03:46 +0100 Subject: [PATCH] beps/0003: add a few usage patterns for HttpAuthService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .../README.md | 104 +++++++++++++++++- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/beps/0003-auth-architecture-evolution/README.md b/beps/0003-auth-architecture-evolution/README.md index cc076acae1..fb188e05fd 100644 --- a/beps/0003-auth-architecture-evolution/README.md +++ b/beps/0003-auth-architecture-evolution/README.md @@ -71,7 +71,7 @@ For service-to-service communication we will move away from reusing user tokens ## Design Details -### AuthService (WIP) +### `AuthService` (WIP) The new `AuthService` interface is defined as follows: @@ -96,9 +96,11 @@ export interface AuthService { } ``` -TODO: add usage patterns for this service +#### Usage Patterns -### HttpAuthService (WIP) +TODO + +### `HttpAuthService` (WIP) The new `HttpAuthService` interface is defined as follows: @@ -119,13 +121,105 @@ export interface HttpAuthService { options?: HttpAuthServiceMiddlewareOptions, ): BackstageCredentials; - requestHeaders(credentials: BackstageCredentials): Record; + requestHeaders( + credentials: BackstageCredentials, + ): Promise>; issueUserCookie(res: Response): Promise; } ``` -TODO: add usage patterns for this service +#### Usage Patterns + +All of these usages patterns are from the perspective of a plugin backend. + +**Authenticate incoming request that requires user authentication** + +```ts +// Adding the middleware separately like this makes it apply to ALL +// routes added below it. You can also add it between the path and the +// handler below, to make it apply only for that particular path. +router.use(httpAuth.middleware({ allow: ['user'] })); + +router.get('/read-data', (req, res) => { + // TODO: user can currently be undefined, figure out best pattern to avoid that + const { user } = httpAuth.credentials(req); + console.log( + `User ref=${user.userEntityRef} ownership=${user.ownershipEntityRefs}`, + ); + // ... +}); +``` + +**Forward the user credentials from an incoming requests to upstream plugin backend** + +```ts +router.get( + '/read-data', + // Here, the middleware applies to the current path only + httpAuth.middleware({ allow: ['user'] }), + (req, res) => { + const entity = await catalogClient.getEntityByRef(req.params.entityRef, { + credentials: httpAuth.credentials(req), + }); + // ... + }, +); +``` + +**Allow both user and service request** + +```ts +router.get( + '/read-data', + httpAuth.middleware({ allow: ['user', 'service'] }), + (req, res) => { + const credentials = httpAuth.credentials(req); + if (credentials.user) { + res.json( + // Silly example just to highlight separate code paths for user and + // service requests + todoStore.listOwnedTodos({ owner: credentials.user.userEntityRef }), + ); + } else { + res.json(todoStore.listTodos()); + } + }, +); +``` + +**Issuing a cookie and allowing user cookie auth on a separate endpoint** + +```ts +router.get('/cookie', httpAuth.middleware({ allow: ['user'] }), (req, res) => { + await httpAuth.issueUserCookie(res); + res.json({ ok: true }); +}); + +// Separate endpoint that serves static content, allowing user cookie auth as +// well as regular user auth +router.use( + '/static', + httpAuth.middleware({ allow: ['user', 'user-cookie'] }), + express.static(staticContentDir), +); +``` + +**Passing along user identity from a cookie in an upstream request** + +```ts +router.get( + '/read-data', + httpAuth.middleware({ allow: ['user-cookie'] }), + (req, res) => { + const { cookieUser } = httpAuth.credentials(req); + console.log( + `User ref=${user.userEntityRef} ownership=${user.ownershipEntityRefs}`, + ); + // ... + }, +); +``` ## Release Plan