@insyde/auth-sdk
v2.2.0
Published
Authentication SDK for insyde.one consumer apps
Readme
@insyde/auth-sdk
Authentication and authorization middleware for Express apps consuming JWTs issued by auth.insyde.one.
Install
npm install @insyde/auth-sdkPeer dependencies: express (>=4), jsonwebtoken (>=9).
Usage
authenticate
Validates the JWT from the Authorization: Bearer <token> header, verifies aud (audience) and iss (issuer), and populates req.auth.
import { authenticate } from '@insyde/auth-sdk';
app.use(authenticate({
jwtSecret: process.env.JWT_SECRET!,
audience: 'stage.insyde.one',
// issuer: 'auth.insyde.one', // optional, defaults to 'auth.insyde.one'
}));Options
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| jwtSecret | string | Yes | — | Shared HS256 secret (same as auth-service) |
| audience | string | Yes | — | Expected aud claim (your product's audience) |
| issuer | string | No | 'auth.insyde.one' | Expected iss claim |
After authentication, req.auth contains:
interface AuthPayload {
userId: string;
tenantId: string;
productId: string;
roles: string[];
permissions: string[];
authzRev: number;
globalRole?: 'super_admin';
}requirePermission
Checks that the authenticated user has all of the specified permissions. Supports hierarchy — post.edit.any satisfies a check for post.edit.
import { requirePermission } from '@insyde/auth-sdk';
router.put('/posts/:id', requirePermission('post.edit'), handler);
router.delete('/posts/:id', requirePermission('post.delete', 'post.edit'), handler);super_admin users bypass all permission checks.
requirePermissionWithOwnership
Checks <resource>.<action>.any first, then falls back to <resource>.<action>.own by comparing the resource owner with req.auth.userId.
import { requirePermissionWithOwnership } from '@insyde/auth-sdk';
router.put('/posts/:id',
requirePermissionWithOwnership('post', 'edit', async (req) => {
const post = await Post.findById(req.params.id);
return post?.authorId?.toString();
}),
handler,
);i18n / Translation Keys
Since v2.0.0, all error responses use translation keys instead of hardcoded strings. Your app is responsible for mapping these keys to user-facing messages (e.g., via i18n middleware).
| Key | HTTP Status | Description |
|-----|-------------|-------------|
| auth.token.not_provided | 401 | Missing or invalid Authorization header |
| auth.token.invalid_or_expired | 401 | JWT verification failed (expired, bad signature, wrong audience/issuer) |
| auth.permission.insufficient | 403 | User lacks required permission(s) |
Example: mapping keys to messages
// i18n middleware (after auth SDK middlewares)
const messages: Record<string, Record<string, string>> = {
'pt-BR': {
'auth.token.not_provided': 'Token não fornecido.',
'auth.token.invalid_or_expired': 'Token inválido ou expirado.',
'auth.permission.insufficient': 'Permissão insuficiente.',
},
en: {
'auth.token.not_provided': 'Token not provided.',
'auth.token.invalid_or_expired': 'Invalid or expired token.',
'auth.permission.insufficient': 'Insufficient permission.',
},
};Migrating from v1.x
In v1.x, error responses contained Portuguese strings:
- { "message": "Token não fornecido." }
+ { "message": "auth.token.not_provided" }
- { "message": "Token inválido ou expirado." }
+ { "message": "auth.token.invalid_or_expired" }
- { "message": "Não autenticado." }
+ { "message": "auth.token.not_provided" }
- { "message": "Permissão insuficiente." }
+ { "message": "auth.permission.insufficient" }If your frontend checks response.data.message against the old Portuguese strings, update those checks to use the new keys.
License
Private — insyde.one internal use only.
