Cognito Server Side (requires client secret)
This implementation requires a trusted backend. I encountered security issue while learning how to create a login to secure a CLI Tool. So this code ain’t used, but I thought it was nice to keep it documented for future implementation.
// https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html
// https://docs.aws.amazon.com/cognito/latest/developerguide/login-endpoint.html
import { type Context, Hono } from "hono";
import { logger } from "hono/logger";
import * as client from "npm:openid-client";
import { TokenEndpointResponse } from "npm:openid-client";
import open from "npm:open";
const app = new Hono();
app.use(logger());
let user: TokenEndpointResponse;
const code_verifier: string = client.randomPKCECodeVerifier();
const state: string = client.randomState();
const config: client.Configuration = await client.discovery(
new URL(
"https://cognito-idp.ca-central-1.amazonaws.com/<user-pool-id>",
),
"<client-id>",
"<client-secret>", // Should be secured. (SSM/secret manager)
);
const parameters: Record<string, string> = {
redirect_uri: "http://localhost:13567/redirect_uri",
scope: "email openid phone",
state,
code_challenge: await client.calculatePKCECodeChallenge(code_verifier),
code_challenge_method: "S256",
};
const redirectTo: URL = client.buildAuthorizationUrl(config, parameters);
console.log(redirectTo);
await open(redirectTo.href);
app.get("/redirect_uri", async (c: Context) => {
console.log("received", c.req.url);
const tokens: client.TokenEndpointResponse =
await client.authorizationCodeGrant(config, new URL(c.req.url), {
pkceCodeVerifier: code_verifier,
expectedState: state,
});
console.log("Token Endpoint Response", tokens);
user = tokens;
return c.text("Ok", 200);
});
app.onError((err: Error, c: Context) => {
console.error("GLOBAL ERROR HANDLING", err);
return c.text("not ok", 500);
});
Deno.serve({ port: 13567, hostname: "0.0.0.0" }, app.fetch);