{"_id":"@anuj304/pramaan","name":"@anuj304/pramaan","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@anuj304/pramaan","version":"1.0.0","description":"Official Node.js SDK for Pramaan OAuth 2.0 and OpenID Connect Identity Provider","main":"./dist/index.js","types":"./dist/index.d.ts","type":"module","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"scripts":{"build":"tsc --build","clean":"node -e \"const fs = require('fs'); fs.rmSync('./dist', { recursive: true, force: true });\"","typecheck":"tsc --project tsconfig.test.json","test":"tsx --test tests/**/*.test.ts","prepublishOnly":"npm run clean && npm run build"},"keywords":["pramaan","oauth2","oidc","openid-connect","identity","authentication","pkce","jwt","idp","sso"],"author":{"name":"Anuj Acharjee"},"license":"MIT","dependencies":{"jose":"^5.9.6"},"devDependencies":{"@types/node":"^22.10.1","tsx":"^4.19.2","typescript":"^5.7.2"},"engines":{"node":">=18.0.0"},"gitHead":"5c26289d08602ef223a97bcd05c229314c2c54f6","_id":"@anuj304/pramaan@1.0.0","_nodeVersion":"22.22.0","_npmVersion":"11.8.0","dist":{"integrity":"sha512-YL/nL0nCvc5E9BwIcfiuu/RrHNb8ahUhmZKeFPKdvED+xjVeUmFb1CZ3opaXKnZKfk9gSeHJMPS6YkIGJD88KQ==","shasum":"7f85cbf7cc70170c21874666d810172b6d8cd054","tarball":"https://registry.npmjs.org/@anuj304/pramaan/-/pramaan-1.0.0.tgz","fileCount":55,"unpackedSize":107491,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDZvF0udeyKJFPf8kP4h7H9Hf8p7rKvN4XMoeE5UTUWUwIgdMjtW1Y3NRyQ4vFJqro4IedwP8hj8HR5dBQCLPiP6oI="}]},"_npmUser":{"name":"anuj304","email":"anujacharjee37@gmail.com"},"directories":{},"maintainers":[{"name":"anuj304","email":"anujacharjee37@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pramaan_1.0.0_1788900637113_0.4643201429882393"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-08T20:50:36.864Z","1.0.0":"2026-09-08T20:50:37.251Z","modified":"2026-09-08T20:50:37.480Z"},"maintainers":[{"name":"anuj304","email":"anujacharjee37@gmail.com"}],"description":"Official Node.js SDK for Pramaan OAuth 2.0 and OpenID Connect Identity Provider","keywords":["pramaan","oauth2","oidc","openid-connect","identity","authentication","pkce","jwt","idp","sso"],"author":{"name":"Anuj Acharjee"},"license":"MIT","readme":"# @anuj304/pramaan\n\nThe official Node.js SDK for **Pramaan** — the self-hosted OAuth 2.0 and OpenID Connect Identity Provider.\n\nIntegrate authentication and single sign-on into your Node.js applications with standard Authorization Code flow, automated PKCE (RFC 7636), cryptographic state/nonce verification, JWKS key rotation, and UserInfo profile retrieval.\n\n---\n\n## Features\n\n* 🔍 **Automatic OIDC Discovery**: Dynamically resolves endpoints from `/.well-known/openid-configuration` — no hardcoded URLs.\n* 🛡️ **Built-in PKCE (RFC 7636)**: Secure S256 code challenge and verifier generation to protect against code interception.\n* 🔒 **CSRF & Nonce Protection**: Constant-time `state` validation and strict OIDC `nonce` validation.\n* 🔑 **Cryptographic ID Token Verification**: Validates RS256 signatures, audience, issuer, expiration, and key ID (`kid`) rotation using standard JWKS.\n* 👤 **UserInfo Integration**: Type-safe profile retrieval from the `/userinfo` endpoint.\n* ⚡ **Framework Independent**: Pure TypeScript library compatible with Express, Fastify, NestJS, or raw Node.js HTTP servers.\n* 📦 **Zero Fluff**: Clean API without unnecessary abstractions or database vendor lock-in.\n\n---\n\n## Installation\n\n```bash\nnpm install @anuj304/pramaan\n```\n\nRequires Node.js `>= 18.0.0`.\n\n---\n\n## Quick Start\n\n### 1. Initialize the Client\n\n```ts\nimport { PramaanClient } from '@anuj304/pramaan';\n\nexport const pramaan = new PramaanClient({\n  issuer: 'https://pramaan.anujacharjee.com',\n  clientId: process.env.PRAMAAN_CLIENT_ID!,\n  clientSecret: process.env.PRAMAAN_CLIENT_SECRET, // required for confidential clients\n  redirectUri: 'http://localhost:3000/callback',\n});\n```\n\n### 2. Initiate Login (Create Authorization Request)\n\nGenerate a cryptographically secure authorization URL and transaction state:\n\n```ts\napp.get('/login', async (req, res) => {\n  const auth = await pramaan.createAuthorizationRequest({\n    scope: ['openid', 'profile', 'email'],\n  });\n\n  // Save the transaction in the server-side session\n  req.session.oauth = auth.transaction;\n\n  // Redirect the browser to Pramaan\n  res.redirect(auth.url);\n});\n```\n\n### 3. Handle Callback\n\nExchange the authorization code for tokens, validate state, and verify the ID token:\n\n```ts\napp.get('/callback', async (req, res) => {\n  const tokens = await pramaan.handleCallback({\n    code: req.query.code as string,\n    state: req.query.state as string,\n    transaction: req.session.oauth,\n  });\n\n  // Clear one-time transaction\n  delete req.session.oauth;\n\n  // Store tokens in your server session\n  req.session.tokens = tokens;\n\n  res.redirect('/profile');\n});\n```\n\n### 4. Fetch User Profile\n\nRetrieve authenticated user claims:\n\n```ts\napp.get('/profile', async (req, res) => {\n  const user = await pramaan.getUserInfo(req.session.tokens.accessToken);\n\n  res.json({\n    id: user.sub,\n    name: user.name,\n    email: user.email,\n    picture: user.picture,\n  });\n});\n```\n\n---\n\n## Architecture Flow\n\n```text\nHost Application                       Pramaan IdP\n      │                                     │\n      ├─────── 1. OIDC Discovery ──────────>│ (/.well-known/openid-configuration)\n      │<────── Metadata & Endpoints ────────┤\n      │                                     │\n      ├─────── 2. Redirect to Login ───────>│ (/api/oauth/authorize)\n      │        (PKCE + state + nonce)       │\n      │                                     │ User Authenticates & Consents\n      │<────── 3. Redirect Callback ────────┤ (code + state)\n      │                                     │\n      ├─────── 4. Exchange Code ───────────>│ (/api/oauth/token)\n      │<────── 5. Access & ID Tokens ───────┤\n      │                                     │\n      ├─────── 6. Fetch JWKS ──────────────>│ (/.well-known/jwks.json)\n      │<────── 7. Public Signing Keys ──────┤ (Verify RS256 Signature)\n      │                                     │\n      ├─────── 8. Fetch UserInfo ──────────>│ (/userinfo)\n      │<────── 9. Profile Claims ───────────┤\n```\n\n---\n\n## Security Best Practices\n\n1. **Keep Secrets Server-Side**: Never initialize `PramaanClient` with a `clientSecret` in browser, client-side, or mobile apps.\n2. **Use Server Sessions**: Persist `auth.transaction` and issued `tokens` inside encrypted server-side sessions (e.g. `express-session` with Redis/cookie store). Never store tokens in browser `localStorage`.\n3. **Always Verify State & Nonce**: The SDK's `handleCallback()` method performs constant-time state comparison to mitigate timing attacks and prevent CSRF login attacks.\n4. **HTTPS in Production**: The SDK enforces `https://` for all production issuer URLs, allowing unencrypted `http://` solely on `localhost` and `127.0.0.1`.\n\n---\n\n## API Reference\n\n### `new PramaanClient(config)`\n\n* `issuer` *(string, required)*: Base URL of your Pramaan instance.\n* `clientId` *(string, required)*: Registered OAuth Client ID.\n* `clientSecret` *(string, optional)*: Client Secret for confidential clients.\n* `redirectUri` *(string, optional)*: Default redirect URI for callbacks.\n* `clockTolerance` *(number, optional)*: JWT clock skew tolerance in seconds (default: 5).\n* `timeoutMs` *(number, optional)*: HTTP timeout in ms (default: 10000).\n\n### Methods\n\n* `discover(forceRefresh?: boolean): Promise<DiscoveryDocument>`\n* `createAuthorizationRequest(options?: AuthorizationOptions): Promise<AuthorizationRequest>`\n* `getAuthorizationUrl(options?: AuthorizationOptions): Promise<string>`\n* `handleCallback(options: CallbackOptions): Promise<TokenSet>`\n* `exchangeCode(code: string, codeVerifier: string, redirectUri?: string): Promise<TokenSet>`\n* `verifyIdToken(idToken: string, expectedNonce?: string): Promise<IDTokenClaims>`\n* `getUserInfo(accessToken: string): Promise<UserInfo>`\n* `getLogoutUrl(options?: LogoutOptions): string` *(Throws `UnsupportedFeatureError` until implemented in Pramaan)*\n\n### Error Classes\n\n* `PramaanError`: Base class for all SDK errors.\n* `ConfigurationError`: Invalid initialization options or parameters.\n* `DiscoveryError`: Discovery endpoint network failure or invalid metadata.\n* `OAuthError`: Standard OAuth 2.0 error returned by server (`error`, `error_description`, `error_uri`).\n* `TokenValidationError`: ID token signature verification or claims mismatch.\n* `StateMismatchError`: State parameter does not match the transaction.\n* `NonceMismatchError`: ID token nonce does not match the transaction.\n* `UnsupportedFeatureError`: Calling an endpoint not yet supported by Pramaan.\n\n---\n\n## Examples\n\nSee the [`examples/express`](examples/express/) directory for a full working Express implementation.\n\n---\n\n## Current Protocol Limitations\n\n* **RP-Initiated Logout**: Pramaan does not currently support `end_session_endpoint`. Local session cleanup should be performed by the application.\n* **Refresh Tokens**: Pramaan currently issues access tokens and ID tokens only. Refresh token rotation is not yet implemented on the server.\n* **Token Revocation / Introspection**: RFC 7009 / RFC 7662 endpoints are not yet supported.\n\n---\n\n## License\n\n[MIT](LICENSE) © [Anuj Acharjee](https://anujacharjee.com)\n","readmeFilename":"README.md","_rev":"1-d636cf12e65ef95780add082be3f5e21"}