@zshn-dev/auth-server
v1.1.0
Published
Angular-first auth server SDK — Express router for GitHub OAuth
Maintainers
Readme
@zshn-dev/auth-server
GitHub OAuth + JWT authentication middleware for Express.
Installation
npm install @zshn-dev/auth-serverQuick Start
import express from 'express';
import { createAuthRouter, verifyJwt } from '@zshn-dev/auth-server';
const config = {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
jwtSecret: process.env.JWT_SECRET!,
callbackUrl: 'http://localhost:3000/auth/github/callback',
afterLoginUrl: 'http://localhost:4200/auth/callback',
};
const app = express();
// Mount the auth router at /auth
app.use('/auth', createAuthRouter(config));
// Protect routes with JWT middleware
app.get('/api/me', verifyJwt(config), (req, res) => {
res.json({ user: req.user });
});
app.listen(3000, () => console.log('Server running on http://localhost:3000'));After a successful login, GitHub redirects to callbackUrl, which exchanges the OAuth code for a JWT and then redirects the user to:
<afterLoginUrl>?token=<jwt>API Reference
createAuthRouter(config: AuthServerConfig): Router
Returns an Express Router. Mount it at /auth:
app.use('/auth', createAuthRouter(config));Routes:
| Method | Path | Description |
| ------ | ----------------- | ------------------------------------------------------------------------ |
| GET | /github | Redirects the user to the GitHub OAuth authorization page |
| GET | /github/callback| Exchanges the OAuth code for a JWT; redirects to afterLoginUrl?token=… |
AuthServerConfig
| Property | Type | Required | Default | Description |
| ----------------- | ----------------------------------------------- | -------- | -------------- | -------------------------------------------------------------- |
| clientId | string | ✅ | — | GitHub OAuth App client ID |
| clientSecret | string | ✅ | — | GitHub OAuth App client secret |
| jwtSecret | string | ✅ | — | Secret used to sign/verify JWTs — must be 32+ characters |
| callbackUrl | string | ✅ | — | Full URL GitHub redirects to after authorization |
| afterLoginUrl | string | ✅ | — | URL of your frontend app; receives ?token=<jwt> on success |
| transformUser | (profile: GitHubProfile) => Partial<User> | ❌ | — | Optional hook to customize the JWT payload from the GitHub profile |
| stateCookieName | string | ❌ | oauth_state | Name of the cookie used to store the OAuth CSRF state value |
verifyJwt(config: AuthServerConfig): RequestHandler
Returns an Express middleware that validates a JWT on every request.
- Reads the
Authorization: Bearer <token>header - Verifies the token against
config.jwtSecret - Sets
req.user(typed asJwtPayload) on success - Returns
401 Unauthorizedif the token is missing, invalid, or expired
app.get('/api/profile', verifyJwt(config), (req, res) => {
res.json(req.user);
});transformUser Hook
Use transformUser to control which fields from the GitHub profile are included in the JWT payload:
import { createAuthRouter, GitHubProfile } from '@zshn-dev/auth-server';
app.use('/auth', createAuthRouter({
...config,
transformUser: (profile: GitHubProfile) => ({
id: profile.id,
login: profile.login,
name: profile.name,
avatarUrl: profile.avatar_url,
email: profile.email,
}),
}));The returned object is merged into the JWT payload and later available on req.user.
Environment Variables
Never hardcode secrets. Use a .env file (via dotenv) or your deployment platform's secret management:
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
# Must be at least 32 characters
JWT_SECRET=a_very_long_random_secret_at_least_32_charsimport 'dotenv/config';
const config = {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
jwtSecret: process.env.JWT_SECRET!,
callbackUrl: process.env.CALLBACK_URL ?? 'http://localhost:3000/auth/github/callback',
afterLoginUrl: process.env.AFTER_LOGIN_URL ?? 'http://localhost:4200/auth/callback',
};Add .env to your .gitignore to avoid committing secrets:
.env