@ciscode/authentication-kit
v1.1.0
Published
A login library with local login, Microsoft Entra ID authentication, password reset, and roles/permissions for multi-tenant applications.
Maintainers
Readme
Auth Service (Express · JWT · Multi‑Tenant · RBAC) Internal package — private to the company. This package is not published on npmjs. Install it only from the company’s Azure Artifacts feed using a project or user-level .npmrc.
Authentication & authorization service for Node/Express apps. Provides local email/password auth with lockout, JWT access tokens + refresh, tenant scoping, RBAC, and optional Microsoft Entra (Azure AD) OAuth.
Features Local auth (email/password) with account lockout policy. JWT access tokens (Bearer) and refresh endpoint (cookie or body). Multi-tenant scope on requests. RBAC (roles → permission strings). Microsoft Entra (Azure AD) OAuth (optional). MongoDB/Mongoose models. Routes are mounted under:
/api/auth (auth, password reset) /api/users (user admin) /api/auth/roles and /api/auth/permissions (RBAC) Installation (Azure Artifacts only)
- Configure .npmrc Do not commit real tokens. Prefer ~/.npmrc or generate .npmrc in CI using secrets.
For developers (user-level ~/.npmrc):
registry=https://registry.npmjs.org/
Route @ciscodeapps scope to the private feed
@ciscodeapps:registry=https://pkgs.dev.azure.com/CISCODEAPPS/Templates/_packaging/testfeed/npm/registry/
//pkgs.dev.azure.com/CISCODEAPPS/Templates/_packaging/testfeed/npm/registry/:_authToken=${AZURE_ARTIFACTS_PAT} always-auth=true Set the token as an environment variable before installing:
export AZURE_ARTIFACTS_PAT="" You can also use the username/_password form:
//pkgs.dev.azure.com/...:username=AzureDevOps //pkgs.dev.azure.com/...:_password=${BASE64_PAT} //pkgs.dev.azure.com/...:email=not-used@localhost where BASE64_PAT=$(printf %s "$AZURE_ARTIFACTS_PAT" | base64).
- Install the package npm i @ciscodeapps/auth-service
- Required environment variables (host app) Create a .env in the host project:
Server
PORT=3000 NODE_ENV=development BASE_URL=http://localhost:3000
Database (the service connects to this on startup)
MONGO_URI_T=mongodb://127.0.0.1:27017/auth_service
JWT
JWT_SECRET=change_me JWT_ACCESS_TOKEN_EXPIRES_IN=15m JWT_REFRESH_SECRET=change_me_too JWT_REFRESH_TOKEN_EXPIRES_IN=7d
Lockout policy
MAX_FAILED_LOGIN_ATTEMPTS=5 ACCOUNT_LOCK_TIME_MINUTES=15
(Optional) Microsoft Entra ID (Azure AD)
MICROSOFT_TENANT=organizations MICROSOFT_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx MICROSOFT_CLIENT_SECRET=your-secret MICROSOFT_CALLBACK_URL=${BASE_URL}/api/auth/microsoft/callback Use inside an existing Express app Your package exports an Express app that already parses JSON, connects to Mongo, and mounts its routes. Just mount it:
// server.js (host app) require('dotenv').config(); const express = require('express'); const authApp = require('@ciscodeapps/auth-service');
const app = express(); app.use(authApp); // exposes /api/auth, /api/users, /api/auth/roles, /api/auth/permissions
app.get('/health', (_, res) => res.json({ ok: true })); app.listen(process.env.PORT || 3000, () => console.log('Host app on', process.env.PORT || 3000) ); Prefer mounting the service. If you need to run it standalone, you can also start this package directly (it calls connectDB() on import).
What’s included (routes & behavior) Auth POST /api/auth/register – Create a user (email/password). POST /api/auth/login – Local login. On success, returns accessToken and may set a refreshToken httpOnly cookie. POST /api/auth/verify-otp – If OTP/step-up is enabled, verifies the code and completes login. POST /api/auth/refresh-token – New access token from a valid refresh token (cookie or body). POST /api/auth/request-password-reset – Sends a reset token (e.g., by email). PATCH /api/auth/reset-password – Consumes the reset token and sets a new password. GET /api/auth/microsoft → GET /api/auth/microsoft/callback – Optional Microsoft Entra OAuth; issues first-party tokens. Users GET /api/users – List users (tenant-scoped, paginated). POST /api/users – Create a user (requires permission). Additional CRUD endpoints as exposed by controllers. Roles & Permissions GET/POST /api/auth/roles – Manage roles (name, tenantId, permissions: string[]). GET /api/auth/permissions – List permission strings and metadata. Protecting your own routes (host app) const authenticate = require('@ciscodeapps/auth-service/src/middleware/authenticate'); // JWT const { hasPermission } = require('@ciscodeapps/auth-service/src/middleware/rbac.middleware'); // RBAC
app.get('/reports', authenticate, hasPermission('reports:read'), (req, res) => res.json({ ok: true }) ); Tenant scope comes from the JWT payload (e.g., tenantId) and is used inside controllers/guards to filter queries.
Quick start (smoke tests) Start your host app:
node server.js Register & Login
curl -X POST http://localhost:3000/api/auth/register
-H 'Content-Type: application/json'
-d '{"email":"[email protected]","password":"Secret123!","tenantId":"t-001","name":"Alice"}'
curl -X POST http://localhost:3000/api/auth/login
-H 'Content-Type: application/json'
-d '{"email":"[email protected]","password":"Secret123!","tenantId":"t-001"}'
=> { "accessToken": "...", "refreshToken": "..." }
Call a protected route
ACCESS=<paste_access_token_here> curl http://localhost:3000/api/users -H "Authorization: Bearer $ACCESS" Refresh token
curl -X POST http://localhost:3000/api/auth/refresh-token
-H 'Content-Type: application/json'
-d '{"refreshToken":"<paste_refresh_token_here>"}'
=> { "accessToken": "..." }
Microsoft OAuth (optional) - Visit: http://localhost:3000/api/auth/microsoft → complete sign-in.
- Callback: ${BASE_URL}/api/auth/microsoft/callback returns tokens (and may set the refresh cookie).
CI/CD (Azure Pipelines)
azure-pipelines.yml (snippet)
task: npmAuthenticate@0 inputs: workingFile: .npmrc # optional; the task wires npm auth for subsequent steps
script: npm ci displayName: Install deps (For GitHub Actions, write a ~/.npmrc with the token from secrets.AZURE_ARTIFACTS_PAT before npm ci.)
Security notes Never commit real PATs. Use env vars or CI secrets. Run behind HTTPS. Rotate JWT & refresh secrets periodically. Limit login attempts; log auth events for auditing. License Internal — Company proprietary.
