import { OAuthApp, createAWSLambdaAPIGatewayV2Handler } from "../src/"; import { URL } from "url"; import { APIGatewayProxyEventV2 } from "aws-lambda"; describe("createAWSLambdaAPIGatewayV2Handler(app)", () => { it("supports oauth app", async () => { const app = new OAuthApp({ clientType: "oauth-app", clientId: "0123", clientSecret: "0123secret", }); createAWSLambdaAPIGatewayV2Handler(app); }); it("supports github app", async () => { const app = new OAuthApp({ clientType: "github-app", clientId: "0123", clientSecret: "0123secret", }); createAWSLambdaAPIGatewayV2Handler(app); }); it("fail-over to default unhandled request handler", async () => { const appMock = {}; const handleRequest = createAWSLambdaAPIGatewayV2Handler( appMock as unknown as OAuthApp ); const response = await handleRequest({ requestContext: { http: { method: "GET" }, stage: "prod" }, rawPath: "/prod/unknown", } as APIGatewayProxyEventV2); expect(response.statusCode).toBe(404); }); it("allow pre-flight requests", async () => { const app = new OAuthApp({ clientId: "0123", clientSecret: "0123secret" }); const handleRequest = createAWSLambdaAPIGatewayV2Handler(app); const response = await handleRequest({ requestContext: { http: { method: "OPTIONS" }, stage: "prod" }, rawPath: "/prod/api/github/oauth/token", } as APIGatewayProxyEventV2); expect(response.statusCode).toStrictEqual(200); expect(response.headers!["access-control-allow-origin"]).toBe("*"); expect(response.headers!["access-control-allow-methods"]).toBe("*"); expect(response.headers!["access-control-allow-headers"]).toBe( "Content-Type, User-Agent, Authorization" ); }); it("supports $default stage", async () => { const app = new OAuthApp({ clientId: "0123", clientSecret: "0123secret" }); const handleRequest = createAWSLambdaAPIGatewayV2Handler(app); const response = await handleRequest({ requestContext: { http: { method: "GET" }, stage: "$default" }, rawPath: "/api/github/oauth/login", } as APIGatewayProxyEventV2); expect(response.statusCode).toBe(302); const url = new URL(response.headers!.location as string); expect(url.origin).toBe("https://github.com"); expect(url.pathname).toBe("/login/oauth/authorize"); expect(url.searchParams.get("client_id")).toBe("0123"); expect(url.searchParams.get("state")).toMatch(/^\w+$/); expect(url.searchParams.get("scope")).toBeNull(); }); it("supports named stage", async () => { const app = new OAuthApp({ clientId: "0123", clientSecret: "0123secret" }); const handleRequest = createAWSLambdaAPIGatewayV2Handler(app); const response = await handleRequest({ requestContext: { http: { method: "GET" }, stage: "prod" }, rawPath: "/prod/api/github/oauth/login", } as APIGatewayProxyEventV2); expect(response.statusCode).toBe(302); const url = new URL(response.headers!.location as string); expect(url.origin).toBe("https://github.com"); expect(url.pathname).toBe("/login/oauth/authorize"); expect(url.searchParams.get("client_id")).toBe("0123"); expect(url.searchParams.get("state")).toMatch(/^\w+$/); expect(url.searchParams.get("scope")).toBeNull(); }); it("passes query string to generic request handler correctly", async () => { const app = new OAuthApp({ clientId: "0123", clientSecret: "0123secret" }); const handleRequest = createAWSLambdaAPIGatewayV2Handler(app); const response = await handleRequest({ requestContext: { http: { method: "GET" }, stage: "prod" }, rawPath: "/prod/api/github/oauth/login", rawQueryString: "state=mystate123&scopes=one,two,three", } as APIGatewayProxyEventV2); expect(response.statusCode).toBe(302); const url = new URL(response.headers!.location as string); expect(url.origin).toBe("https://github.com"); expect(url.pathname).toBe("/login/oauth/authorize"); expect(url.searchParams.get("client_id")).toBe("0123"); expect(url.searchParams.get("state")).toBe("mystate123"); expect(url.searchParams.get("scope")).toBe("one,two,three"); }); });