@zezosoft/zezo-oauth-node
v1.0.2
Published
Express.js adapter for Zezo OAuth and OpenID Connect.
Readme
@zezosoft/zezo-oauth-node
Express.js adapter for Zezo OAuth/OIDC.
Provider configuration
There is intentionally no issuer option in this package. The Zezo provider/issuer is fixed and configured by @zezosoft/oauth-core.
Install
npm install @zezosoft/zezo-oauth-node cookie-parserSetup
import express from 'express';
import cookieParser from 'cookie-parser';
import { ZezoOAuth } from '@zezosoft/zezo-oauth-node';
const app = express();
app.use(express.json());
app.use(cookieParser());
export const zezoAuth = new ZezoOAuth({
clientId: process.env.ZEZO_CLIENT_ID!,
clientSecret: process.env.ZEZO_CLIENT_SECRET!,
callbackURL: 'http://localhost:5050/api/v1/auth/zezo/callback',
scopes: ['openid', 'profile', 'email'],
});No issuer is passed.
Login/callback
router.get('/zezo', zezoAuth.login());
router.get(
'/zezo/callback',
zezoAuth.callback(),
asyncWrapper(userController.zezoCallback as unknown as RequestHandler),
);After the callback middleware succeeds:
req.zezoUser
req.zezoTokensare available.
TIE controller
async zezoCallback(req: ZezoRequest, res: Response, next: NextFunction) {
try {
const zezoUser = req.zezoUser;
if (!zezoUser) {
return next(new createHttpError.Unauthorized('Zezo authentication failed'));
}
let user = await UserModel.findOne({
providerId: zezoUser.sub,
authProvider: 'zezo',
});
if (!user) {
user = await UserModel.create({
name: zezoUser.name,
email: zezoUser.email,
providerId: zezoUser.sub,
authProvider: 'zezo',
profilePicture: zezoUser.picture,
role: Roles.USER,
isEmailVerified: zezoUser.email_verified,
});
}
const tieToken = jwtHelper.signAccessTokenV1({
sub: String(user._id),
role: user.role,
aud: 'tie-api',
});
// Prefer a secure HTTP-only session or one-time exchange code
// instead of putting the JWT in a URL query parameter.
return res.redirect(`${process.env.FRONTEND_URL}/auth/success`);
} catch (error) {
return next(error);
}
}Protected Zezo-token route
router.get(
'/profile',
zezoAuth.authenticate(),
(req: ZezoRequest, res) => {
res.json({ user: req.zezoUser });
},
);Important production note
authenticate() uses the core package's user-info operation. For a resource server, your core should additionally expose cryptographic JWT verification using Zezo JWKS and validate iss, aud, exp, and scopes. Do not trust an unverified JWT payload.
The OAuth callback should also cryptographically validate the ID-token signature and nonce in @zezosoft/oauth-core before req.zezoUser is considered authenticated.
