@drmhse/sso-sdk 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +116 -0
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -146,6 +146,122 @@ localStorage.removeItem('sso_token');
146
146
  localStorage.removeItem('sso_refresh_token');
147
147
  ```
148
148
 
149
+ ## Validating Tokens in Your Backend
150
+
151
+ The SSO platform uses **RS256** (RSA with SHA-256) asymmetric signing for JWTs. This means your backend services can validate JWT signatures without needing access to any shared secrets.
152
+
153
+ ### How It Works
154
+
155
+ 1. **Fetch the JWKS**: The SSO platform exposes a public JWKS (JSON Web Key Set) endpoint at `/.well-known/jwks.json` containing the public RSA key(s).
156
+ 2. **Cache the Keys**: Fetch and cache the JWKS in your backend to avoid repeated requests.
157
+ 3. **Verify Tokens**: When a client sends a JWT, extract the `kid` (Key ID) from the token header, find the matching key in your cached JWKS, and verify the signature.
158
+ 4. **Validate Claims**: After signature verification, validate token claims like `exp` (expiration), `iss` (issuer), and `aud` (audience).
159
+
160
+ ### Node.js/Express Example
161
+
162
+ Here's a complete example of JWT validation middleware:
163
+
164
+ ```typescript
165
+ import { expressjwt } from 'express-jwt';
166
+ import jwksRsa from 'jwks-rsa';
167
+
168
+ // Configure JWKS client to fetch public keys
169
+ const jwksClient = jwksRsa({
170
+ cache: true,
171
+ rateLimit: true,
172
+ jwksRequestsPerMinute: 5,
173
+ jwksUri: 'https://sso.example.com/.well-known/jwks.json'
174
+ });
175
+
176
+ // Function to get signing key from JWKS
177
+ function getKey(header, callback) {
178
+ jwksClient.getSigningKey(header.kid, (err, key) => {
179
+ if (err) {
180
+ return callback(err);
181
+ }
182
+ const signingKey = key.getPublicKey();
183
+ callback(null, signingKey);
184
+ });
185
+ }
186
+
187
+ // JWT validation middleware
188
+ const requireAuth = expressjwt({
189
+ secret: getKey,
190
+ algorithms: ['RS256'],
191
+ credentialsRequired: true,
192
+ getToken: (req) => {
193
+ if (req.headers.authorization?.startsWith('Bearer ')) {
194
+ return req.headers.authorization.substring(7);
195
+ }
196
+ return null;
197
+ }
198
+ });
199
+
200
+ // Use in your routes
201
+ app.get('/api/protected', requireAuth, (req, res) => {
202
+ // req.auth contains the decoded JWT claims
203
+ const { sub, email, org, service } = req.auth;
204
+ res.json({ message: `Hello ${email}` });
205
+ });
206
+ ```
207
+
208
+ ### Manual Validation (Node.js)
209
+
210
+ If you prefer to validate manually without middleware:
211
+
212
+ ```typescript
213
+ import jwt from 'jsonwebtoken';
214
+ import jwksRsa from 'jwks-rsa';
215
+
216
+ const jwksClient = jwksRsa({
217
+ jwksUri: 'https://sso.example.com/.well-known/jwks.json'
218
+ });
219
+
220
+ async function validateToken(token: string) {
221
+ try {
222
+ // Decode without verifying to get the kid
223
+ const decoded = jwt.decode(token, { complete: true });
224
+ if (!decoded || !decoded.header.kid) {
225
+ throw new Error('Invalid token: missing kid');
226
+ }
227
+
228
+ // Get the public key for this kid
229
+ const key = await jwksClient.getSigningKey(decoded.header.kid);
230
+ const publicKey = key.getPublicKey();
231
+
232
+ // Verify and decode the token
233
+ const verified = jwt.verify(token, publicKey, {
234
+ algorithms: ['RS256']
235
+ });
236
+
237
+ return verified; // Returns the decoded claims
238
+ } catch (error) {
239
+ console.error('Token validation failed:', error);
240
+ throw error;
241
+ }
242
+ }
243
+
244
+ // Usage
245
+ const claims = await validateToken(req.headers.authorization.split(' ')[1]);
246
+ console.log(claims.email, claims.org, claims.service);
247
+ ```
248
+
249
+ ### Other Languages
250
+
251
+ The same approach works in any language:
252
+
253
+ - **Python**: Use `PyJWT` with `python-jose` or `jwcrypto`
254
+ - **Go**: Use `golang-jwt/jwt` with JWKS support
255
+ - **Java**: Use `java-jwt` or Spring Security with JWKS
256
+ - **Ruby**: Use `jwt` gem with `jwks-ruby`
257
+
258
+ The key steps are always the same:
259
+ 1. Fetch JWKS from `/.well-known/jwks.json`
260
+ 2. Extract `kid` from JWT header
261
+ 3. Find matching key in JWKS
262
+ 4. Verify signature using the public key
263
+ 5. Validate token claims (especially `exp`)
264
+
149
265
  ## API Reference
150
266
 
151
267
  ### Analytics (`sso.analytics`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drmhse/sso-sdk",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Zero-dependency TypeScript SDK for the multi-tenant SSO Platform API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",