https://github.com/gw31415/hono-oidc-simple
Simplifies the implementation of OIDC auth in Hono
https://github.com/gw31415/hono-oidc-simple
honojs oidc
Last synced: about 1 month ago
JSON representation
Simplifies the implementation of OIDC auth in Hono
- Host: GitHub
- URL: https://github.com/gw31415/hono-oidc-simple
- Owner: gw31415
- License: apache-2.0
- Created: 2024-12-07T07:39:54.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-04-28T14:48:58.000Z (about 1 year ago)
- Last Synced: 2025-09-14T22:53:21.827Z (9 months ago)
- Topics: honojs, oidc
- Language: TypeScript
- Homepage:
- Size: 81.1 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @gw31415/hono-oidc-simple
[](https://badge.fury.io/js/@gw31415%2Fhono-oidc-simple)
[](https://opensource.org/licenses/Apache-2.0)
`@gw31415/hono-oidc-simple` simplifies the implementation of OpenID Connect
(OIDC) authentication in Hono-based applications. It provides tools for managing
tokens, user sessions, and handling login and logout easily.
---
## Features
- Zero Dependency: No `dependencies` in `package.json`. Only `devDependencies` or
`peerDependencies` (`hono`) are used.
- Middleware Creation: Provides middleware and handlers for managing user
authentication states.
- Customizable: Abstract methods allow flexibility in how tokens are stored or
retrieved.
- Multi-Runtime Support: Works with below runtimes:
- [x] Bun
- [x] Cloudflare Workers
- [x] Deno
- [x] Node.js
## Installation
```bash
npm i @gw31415/hono-oidc-simple
```
## Usage
Please check the example project: [`gw31415/hono-oidc-simple-example`](https://github.com/gw31415/hono-oidc-simple-example).
### Setup and Create Middleware of OIDC
```ts
/** Cookie expiration period */
const COOKIE_MAXAGE = 60 * 60 * 24 * 30 * 6; // 6 months
/** Set-up OIDC */
const oidc = OIDC((c) => {
const envs = env<{
OIDC_GOOGLE_CLIENT: string;
OIDC_GOOGLE_SECRET: string;
}>(c);
return {
issuers: [
{
issuer: "https://accounts.google.com",
authEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
tokenEndpoint: "https://oauth2.googleapis.com/token",
tokenRevocationEndpoint: "https://oauth2.googleapis.com/revoke",
useLocalJwt: false,
createClaims: async (c, tokens) => {
const idToken: string | undefined = await token.getIDToken(c);
if (idToken) {
const jwks = createRemoteJWKSet(
new URL("https://www.googleapis.com/oauth2/v3/certs"),
);
try
{
const { payload } = await jwtVerify(idToken, jwks, {
issuer: "https://accounts.google.com",
audience: envs.OIDC_GOOGLE_CLIENT,
});
return payload as Claims;
} catch (e) {
console.error(e);
}
}
return undefined;
},
scopes: ["openid", "email", "profile"],
client_id: envs.OIDC_GOOGLE_CLIENT,
client_secret: envs.OIDC_GOOGLE_SECRET,
},
],
getIssUrl: () => "https://accounts.google.com",
clientSideTokenStore: {
getRefreshToken: (c) => getCookie(c, "refresh_token"),
getIDToken: (c) => getCookie(c, "jwt"),
setRefreshToken: (c, token) => {
if (!token) {
deleteCookie(c, "refresh_token");
return;
}
const reqUrl = new URL(c.req.url);
const opts: CookieOptions = {
path: "/",
sameSite: "Lax",
httpOnly: true,
secure: reqUrl.hostname !== "localhost",
maxAge: COOKIE_MAXAGE,
};
setCookie(c, "refresh_token", token, opts);
},
setIDToken: (c, token) => {
if (!token) {
deleteCookie(c, "jwt");
return;
}
const reqUrl = new URL(c.req.url);
const secure = reqUrl.hostname !== "localhost";
return setCookie(c, "jwt", token, {
path: "/",
sameSite: "Lax",
httpOnly: true,
secure,
maxAge: COOKIE_MAXAGE,
});
},
},
};
});
```
### Create your Middlewares to get the claims
```ts
type Middleware = OIDCMiddlewareType;
/**
* @param iss OIDC Issuer URL
*/
export const loginRoute = (iss: IssuerType) =>
createRoute(
oidc.loginHandler(iss, (res, c) => {
if (res.type === "ERR") {
const error = res.error;
switch (error) {
case "Unauthorized":
return c.redirect("/");
case "OAuthServerError":
return c.text(`Error: ${error}`, { status: 500 });
default:
return c.text("Invalid state", { status: 500 });
}
}
return c.redirect("/");
}),
);
export const logoutRoute = createRoute(
oidc.logoutHandler((c) => {
return c.redirect("/");
}),
);
export const useClaims = oidc.useClaims;
/** Middleware to specify pages that require login */
export const loginRequired: Middleware = every(useClaims, (async (c, next) => {
if (!c.var.claims) {
return c.render(
,
{ title: "Login Required" },
);
}
return await next();
}) satisfies Middleware);
```
## License
Apache-2.0