
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@flycatch/auth-core
Advanced tools
A unified authentication module for Express.js, NestJS frameworks, supporting JWT, session-based, and Google OAuth login.
Auth-Core is a unified authentication middleware for Node.js applications, supporting JWT-based authentication, session-based authentication, and OAuth 2.0 authentication. This package simplifies authentication management by providing middleware functions that handle authentication flows seamlessly.
npm install @flycatch/auth-core
const express = require("express");
const { config, verify } = require("@flycatch/auth-core");
const bcrypt = require("bcrypt");
const app = express();
const userRepository = {
async find(email) {
return {
id: "123",
email,
username: "exampleUser",
grants: ["read_user"],
is2faEnabled: false,
};
},
};
app.use(
config({
jwt: {
enabled: true,
secret: "my_jwt_secret",
expiresIn: "1h",
refresh: true,
prefix: "/auth/jwt",
tokenBlacklist: {
enabled: false, // Set to true for server-side logout
},
},
session: {
enabled: false,
prefix: "/auth/session",
secret: "my_session_secret",
resave: false,
saveUninitialized: true,
cookie: { secure: false, maxAge: 60000 },
},
oauth2: {
enabled: true,
baseURL: "http://localhost:3000",
prefix: "/auth",
successRedirect: "http://localhost:3000/oauth-success",
failureRedirect: "http://localhost:3000/oauth-failure",
defaultRole: "ROLE_USER",
onSuccess(info)=>{
const {profile, existingUser,} =info;
if(existingUser){
return existingUser;
}
// Logic to create new user
reateUser(profile)
},
onfailure(info)=>{
// Logic to be executed onFailure
},
providers: {
google: {
clientID: "GOOGLE_CLIENT_ID",
clientSecret: "GOOGLE_CLIENT_SECRET",
callbackURL: "/auth/google/callback",
scope: ["profile", "email"],
},
},
},
twoFA: {
enabled: false,
prefix: "/auth/2fa",
otpLength: 6,
otpExpiresIn: "5m",
storeOtp: async (userId, otp, expiresInMs) => {
// Implement OTP storage logic
console.log(
`Storing OTP ${otp} for user ${userId}, expires in ${expiresInMs}ms`
);
},
getStoredOtp: async (userId) => {
// Implement OTP retrieval logic
return null;
},
},
userService: {
loadUser: async (email) => userRepository.find(email),
createUser: async (profile) => {
return {
id: "new-user-id",
email: profile.email,
username: profile.username,
grants: [profile.defaultRole || "ROLE_USER"],
};
},
},
passwordChecker: async (inputPassword, storedPassword) =>
bcrypt.compare(inputPassword, storedPassword),
logs: true,
})
);
// Protected Route
app.get("/user", verify(), (req, res) => {
res.json({ message: "Access granted", user: req.user });
});
// Protected Route with specific permission
app.get("/admin", verify("admin"), (req, res) => {
res.json({ message: "Admin access granted", user: req.user });
});
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
jwt: {
enabled: true,
secret: "my_jwt_secret",
expiresIn: "1h",
refresh: true,
refreshExpiresIn: "7d",
prefix: "/auth/jwt",
revokeOnRefresh: true,
tokenBlacklist: {
enabled: false,
storageService: {
add: async (token, expiresAt) => { /* Custom add logic */ },
has: async (token) => { /* Custom check logic */ },
remove: async (token) => { /* Custom remove logic */ },
clear: async () => { /* Custom clear logic */ },
},
onLogoutAll: async (userId) => { /* Custom logout all logic */ },
}
}
session: {
enabled: true,
prefix: "/auth/session",
secret: "my_session_secret",
resave: false,
saveUninitialized: false,
cookie: {
secure: false,
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}
}
Note: Session authentication supports multiple concurrent sessions per user. Each login creates a new independent session.
oauth2: {
enabled: true,
baseURL: "http://localhost:3000",
prefix: "/auth",
successRedirect: "http://localhost:3000/oauth-success",
failureRedirect: "http://localhost:3000/oauth-failure",
onSuccess(info)=>{
const {profile, existingUser,} =info;
if(existingUser){
return existingUser;
}
// Logic to create new user
createUser(profile)
},
onfailure(info)=>{
// Logic to be executed onFailure
}
defaultRole: "ROLE_USER",
setRefreshCookie: true,
appendTokensInRedirect: false,
providers: {
google: {
clientID: "GOOGLE_CLIENT_ID",
clientSecret: "GOOGLE_CLIENT_SECRET",
callbackURL: "/auth/google/callback",
scope: ["profile", "email"],
},
github: {
clientID: "GITHUB_CLIENT_ID",
clientSecret: "GITHUB_CLIENT_SECRET",
callbackURL: "/auth/github/callback",
},
},
}
twoFA: {
enabled: true,
otpLength: 6,
otpType: "numeric",
otpExpiresIn: "5m",
transport: async (otp, user) => {
console.log(`Send OTP ${otp} to ${user.email}`);
},
storeOtp: async (userId, otp, expiresInMs) => {
// Implement OTP storage
},
getStoredOtp: async (userId) => {
// Implement OTP retrieval
return null;
},
clearOtp: async (userId) => {
// Implement OTP cleanup
},
}
userService: {
loadUser: async (email) => userRepository.find(email),
createUser: async (profile) => {
// Create new user during OAuth flow
return {
id: "new-user-id",
email: profile.email,
username: profile.username,
grants: [profile.defaultRole || "ROLE_USER"],
};
},
}
passwordChecker: async (inputPassword, storedPassword) =>
bcrypt.compare(inputPassword, storedPassword);
All endpoints use the configured prefix. Default prefixes shown below:
/auth/jwt/login - Initiate user login (sends OTP if 2FA enabled, else returns tokens)/auth/jwt/verify - Verify OTP for 2FA and return tokens/auth/jwt/refresh - Refresh access token/auth/jwt/logout - Logout (simple or with blacklisting)/auth/jwt/logout-all - Logout all sessions (requires blacklisting enabled)/auth/session/login - Initiate user login (sends OTP if 2FA enabled, else creates session)/auth/session/verify - Verify OTP for 2FA and create session/auth/session/logout - Logout current session/auth/{provider} - Initiate OAuth login/auth/{provider}/callback - OAuth callback/auth/error - OAuth error redirect/auth/token - to get token from temporary code/login endpoints trigger OTP generation and transport./verify endpoints to validate OTP and complete login./auth/jwt/login./auth/jwt/verify.Authorization: Bearer <token> header./auth/session/login./auth/session/verify./auth/{provider}./auth/{provider}/callback.{prefix}/token with a POST request and payload:{
"code": "code-from-redirect-url"
}
// Protect any route
app.get("/protected", verify(), (req, res) => {
res.json({ user: req.user });
});
// Require specific permission
app.get("/admin", verify("admin_access"), (req, res) => {
res.json({ message: "Admin only" });
});
Contributions are welcome! Please fork the repository and submit a pull request with your improvements.
This project is licensed under the GPL-3.0 License.
FAQs
A unified authentication module for Express.js, NestJS frameworks, supporting JWT, session-based, and Google OAuth login.
We found that @flycatch/auth-core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.