Webux Lab

By Studio Webux

Cognito authentication for server side authentication

TG
Tommy Gingras Studio Webux 2025-01-19

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);

Search