@bklarjs/jwt
v1.0.3
Published
A JWT-based authentication middleware designed for the Bklar web framework.
Maintainers
Readme
@bklarjs/jwt
Official JWT (JSON Web Token) authentication middleware for the bklar framework.
It allows you to protect routes, verify tokens, and handle user authentication with a clear, simple, and secure API.
✨ Features
- 🔒 Secure by Default: Built on top of
jose, a modern, secure, and Web Cryptography API-based library for JWTs. - 🧩 Simple Integration: Add authentication to any route with just a few lines of code.
- 🔧 Flexible Configuration: Customize token retrieval, validation algorithms, and optional authentication (
passthroughmode). - 🧰 Helper Functions Included: Comes with
sign,verify, anddecodehelpers for a complete authentication solution out of the box. - 🛡️ Full TypeScript Support: Automatically augments the
bklarContext to provide a strongly-typedctx.state.jwtpayload in your protected routes.
📦 Installation
This package is designed to work with bklar. You'll need both installed in your project.
bun add bklar @bklarjs/jwt🚀 Usage
Using the middleware involves two main steps: creating tokens (e.g., during login) and verifying them to protect routes.
1. Protecting a Route
First, create an instance of the JWT middleware and apply it to a route you want to protect.
import { Bklar } from "bklar";
import { jwt } from "@bklarjs/jwt";
const app = Bklar();
// It's highly recommended to use an environment variable for your secret.
const JWT_SECRET = "a-very-strong-secret-key";
// Create an instance of the auth middleware with your secret
const authMiddleware = jwt({ secret: JWT_SECRET });
app.get(
"/profile",
(ctx) => {
// If we reach this handler, the token is valid.
// The decoded JWT payload is available at `ctx.state.jwt`.
const userPayload = ctx.state.jwt;
return ctx.json({
message: "Welcome to your protected profile!",
user: userPayload,
});
},
{
middlewares: [authMiddleware],
}
);
app.listen(3000);To access this route, a client must provide a valid JWT in the Authorization header:
Authorization: Bearer <your-token>
2. Creating a Token (Login Flow)
To get a token, you typically create a /login endpoint. This package includes a sign helper to make this easy.
import { Bklar } from "bklar";
import { jwt, sign } from "@bklarjs/jwt";
import { z } from "zod";
const app = Bklar();
const JWT_SECRET = "a-very-strong-secret-key";
// Example user service (in a real app, this would query a database)
const UserService = {
login: async (email: string, pass: string) => {
if (email === "[email protected]" && pass === "password123") {
return { id: "user_123", email, role: "user" };
}
return null;
},
};
// Login endpoint to generate a token
app.post(
"/login",
async (ctx) => {
const { email, password } = ctx.body;
const user = await UserService.login(email, password);
if (!user) {
// The bklar error handler will catch this and respond with a 401.
throw new UnauthorizedError("Invalid email or password");
}
// Sign a new token for the authenticated user
const token = await sign(
{ sub: user.id, email: user.email, role: user.role },
JWT_SECRET,
"HS256",
{ expiresIn: "1h" } // Token is valid for 1 hour
);
return ctx.json({ token });
},
{
schemas: {
body: z.object({
email: z.string().email(),
password: z.string(),
}),
},
}
);
app.listen(3000);⚙️ Configuration Options
The jwt() factory accepts an options object:
secret: (Required) AstringorUint8Arrayused to sign and verify tokens.algorithms: An optional array of allowed signing algorithms (e.g.,['HS256', 'HS512']). Defaults to['HS256'].passthrough: A boolean. Iftrue, the middleware will not throw an error if the token is missing or invalid.ctx.state.jwtwill simply beundefined. Useful for routes with optional authentication. Defaults tofalse.getToken: A custom function(ctx: Context) => string | undefinedto extract the token from the request. By default, it looks for a Bearer token in theAuthorizationheader.
Example: Optional Authentication
const optionalAuth = jwt({ secret: JWT_SECRET, passthrough: true });
app.get(
"/posts/:id",
(ctx) => {
if (ctx.state.jwt) {
// User is logged in, show personalized content
return ctx.json({
content: "A post.",
personalizedFor: ctx.state.jwt.sub,
});
}
// User is a guest, show public content
return ctx.json({ content: "A post." });
},
{ middlewares: [optionalAuth] }
);🧰 API Reference
This package exports the following:
jwt(options: JWTOptions): Middleware: The main factory function that creates the authentication middleware.sign(payload, secret, alg, options): An async function to create and sign a new JWT.verify(token, secret, algorithms): An async function to verify a token. It throws an error if invalid or returns the payload if valid.decode(token): A synchronous function that decodes a token's payload without verifying its signature. Use with caution.
🤝 Contributing
Contributions are welcome! Please open an issue or submit a Pull Request to the main bklar repository.
📄 License
This project is licensed under the MIT License.
