UNPKG

ciscodeapps-auth

Version:

A login library with local login, Microsoft Entra ID authentication, password reset, and roles/permissions for multi-tenant applications.

157 lines (128 loc) 6.24 kB
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) 1) 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="<your PAT with Packaging:Read>" 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). 2) Install the package npm i @ciscodeapps/auth-service 3) 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":"a@b.com","password":"Secret123!","tenantId":"t-001","name":"Alice"}' curl -X POST http://localhost:3000/api/auth/login \ -H 'Content-Type: application/json' \ -d '{"email":"a@b.com","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.