From 8559aea7c3e034ef949f3e942438183dbf3561a7 Mon Sep 17 00:00:00 2001 From: Grant Date: Tue, 28 May 2024 12:50:14 -0600 Subject: [PATCH] handle callback openid errors (fixes #34) --- packages/server/src/api.ts | 65 +++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/packages/server/src/api.ts b/packages/server/src/api.ts index 4e499ea..ade5172 100644 --- a/packages/server/src/api.ts +++ b/packages/server/src/api.ts @@ -1,6 +1,8 @@ import { Router } from "express"; import { prisma } from "./lib/prisma"; import { OpenID } from "./lib/oidc"; +import { TokenSet, errors as OIDC_Errors } from "openid-client"; +import { Logger } from "./lib/Logger"; const app = Router(); @@ -20,13 +22,66 @@ app.get("/login", (req, res) => { // TODO: logout endpoint app.get("/callback", async (req, res) => { + // TODO: return proper UIs for errors intead of raw JSON (#35) // const { code } = req.query; - const params = OpenID.client.callbackParams(req); - const exchange = await OpenID.client.callback( - OpenID.getRedirectUrl(), - params - ); + let exchange: TokenSet; + + try { + const params = OpenID.client.callbackParams(req); + exchange = await OpenID.client.callback(OpenID.getRedirectUrl(), params); + } catch (e) { + if (e instanceof OIDC_Errors.RPError) { + // client error + + res.status(400).json({ + success: false, + error: e.name, + error_description: e.message, + }); + return; + } + + if (e instanceof OIDC_Errors.OPError) { + // server error + + switch (e.error) { + case "invalid_client": + // this happens when we're configured with invalid credentials + Logger.error( + "OpenID is improperly configured. Cannot exchange tokens, do I have valid credetials?" + ); + res.status(500).json({ + success: false, + error: "internal server error", + error_description: "I'm misconfigured.", + }); + return; + case "invalid_grant": + res.status(400).json({ + success: false, + error: "invalid_grant", + error_description: "retry /api/login", + }); + return; + } + + res.status(400).json({ + success: false, + error: e.error, + error_description: e.error_description, + }); + return; + } + + res.status(500).json({ + success: false, + error: "unknown error", + error_description: "report this", + }); + return; + } + if (!exchange || !exchange.access_token) { return res.status(400).json({ success: false,