From 938c0ab801f2ffdf15313ba7e71281d14ab250da Mon Sep 17 00:00:00 2001 From: Agustin Mendez Date: Thu, 7 Oct 2021 13:48:41 -0300 Subject: [PATCH] wip --- src/controllers/handlers/ping-handler.ts | 11 ++++++- src/controllers/routes.ts | 5 +++ src/logic/authentication-middleware.ts | 42 ++++++++++++++++++++++++ src/logic/getUser.ts | 17 ++++++++++ src/types.ts | 13 ++++++-- 5 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 src/logic/authentication-middleware.ts create mode 100644 src/logic/getUser.ts diff --git a/src/controllers/handlers/ping-handler.ts b/src/controllers/handlers/ping-handler.ts index d72e69e..ca4655c 100644 --- a/src/controllers/handlers/ping-handler.ts +++ b/src/controllers/handlers/ping-handler.ts @@ -1,7 +1,12 @@ import { HandlerContextWithPath } from "../../types" // handlers arguments only type what they need, to make unit testing easier -export async function pingHandler(context: Pick, "url" | "components">) { +export async function pingHandler( + context: Pick< + HandlerContextWithPath<"metrics", "/ping", "authenticationData">, + "url" | "components" | "authenticationData" + > +) { const { url, components: { metrics }, @@ -11,6 +16,10 @@ export async function pingHandler(context: Pick(getUserFromToken), pingHandler)) + return router } diff --git a/src/logic/authentication-middleware.ts b/src/logic/authentication-middleware.ts new file mode 100644 index 0000000..6739b1c --- /dev/null +++ b/src/logic/authentication-middleware.ts @@ -0,0 +1,42 @@ +/** + * This file may be a library on its own. It is recommended that if you are + * creating microservices, you may extract this logic to a package that can + * be reused across servers. + */ + +import { IHttpServerComponent as h } from "@well-known-components/interfaces" + +export type TokenBasedAuthData = { + bearerToken: string + authData: T +} + +export function basicAuthenticationMiddleware }, T = {}>( + getUser: (context: Ctx, bearerToken: string) => Promise +): h.IRequestHandler { + return async (ctx, next) => { + const auth = ctx.request.headers.get("authorization") + + // mising auth header + if (!auth) return { status: 401 } + + const bearerTokenMatch = /^[Bb]earer\s+(.+)$/.exec(auth) + + // invalid bearer token + if (!bearerTokenMatch) return { status: 401 } + + const bearerToken = bearerTokenMatch[1] + + const authData = await getUser(ctx, bearerToken) + + // invalid authData + if (!authData) return { status: 401 } + + ctx.authenticationData = { + bearerToken, + authData, + } + + return next() + } +} diff --git a/src/logic/getUser.ts b/src/logic/getUser.ts new file mode 100644 index 0000000..ec1af05 --- /dev/null +++ b/src/logic/getUser.ts @@ -0,0 +1,17 @@ +import { PickComponents } from "../types" + +export type UserData = { + name: string +} + +export async function getUserFromToken(_ctx: PickComponents<"config">, token: string): Promise { + // use ctx.component.config or database or any other component to get the user from the token + if (token == "tester") { + return { + name: "beta-tester", + } + } + + // return null or throw in case of failure + return null +} diff --git a/src/types.ts b/src/types.ts index aacc78f..15522c1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,10 +6,13 @@ import type { IBaseComponent, IMetricsComponent, } from "@well-known-components/interfaces" +import { UserData } from "./logic/getUser" +import { TokenBasedAuthData } from "./logic/authentication-middleware" import { metricDeclarations } from "./metrics" export type GlobalContext = { components: BaseComponents + authenticationData?: TokenBasedAuthData } // components used in every environment @@ -35,12 +38,18 @@ export type TestComponents = BaseComponents & { // this type simplifies the typings of http handlers export type HandlerContextWithPath< ComponentNames extends keyof AppComponents, - Path extends string = any + Path extends string = any, + GlobalContextKeys extends keyof GlobalContext = any > = IHttpServerComponent.PathAwareContext< IHttpServerComponent.DefaultContext<{ components: Pick }>, Path -> +> & + Omit, "components"> + +export type PickComponents = Ctx & { + components: Pick +} export type Context = IHttpServerComponent.PathAwareContext