# JWT Authentication Nelnet Payment Services (NPS) uses **Bearer authentication with JSON Web Tokens (JWTs)** for all backend API requests. This document explains: - How JWT authentication works in NPS - How to construct and sign a JWT - How JWTs are used to create session tokens - How authentication and transaction context are separated ## Overview div strong Key idea: br JWTs authenticate em who you are . Request fields like code entityId determine em who you are acting as . All NPS backend APIs require a **short-lived JWT** passed in the `Authorization` header. ```http Authorization: Bearer ``` JWTs are: - Signed using **HMAC SHA-512** - Generated by your backend - Created using your **API Key ID** and **API Key** > JWTs are never created or used in client-side code. ## Authentication Model NPS authentication follows a simple, layered model: - **API Key ID** → identifies who you are - **API Key (secret)** → proves who you are - **JWT** → short-lived proof of authorization JWTs are intentionally short-lived and are created on demand by your backend. ## JWT Requirements ### Signing Algorithm - **Algorithm:** `HS512` (HMAC SHA-512) No custom JWT headers are required. Standard JWT libraries automatically generate the correct header. ## JWT Claims ### Required Claims | Claim | Description | | --- | --- | | `sub` | API Key ID | | `iat` | Issued-at timestamp (seconds since epoch) | ### Optional (Recommended) Claims | Claim | Description | | --- | --- | | `exp` | Expiration timestamp | div strong Note: br If code exp is omitted, the expiration defaults to the value configured when the API key was created. ## Example: Creating a JWT (Node.js) ```js import jwt from 'jsonwebtoken'; function createJwt() { const now = Math.floor(Date.now() / 1000); const payload = { sub: process.env.NPS_API_KEY_ID, iat: now, exp: now + 300 // 5 minutes }; return jwt.sign(payload, process.env.NPS_API_KEY, { algorithm: 'HS512' }); } ``` ## Creating a Session Token Using a JWT JWTs are used to authenticate backend requests, including requests that create a **tokenization session** for use with the NPS JavaScript SDK. div strong Key idea: br JWTs stay on the server. Session tokens are the only credentials exposed to the browser. After generating a JWT, your backend requests a session from NPS: ```js const jwt = createJwt(); const response = await fetch('https://api.nelnetpay.com/tokenization/session', { method: 'POST', headers: { Authorization: `Bearer ${jwt}`, 'Content-Type': 'application/json' } }); const data = await response.json(); return { sessionId: data.session.id, sessionToken: data.session.token, expiresAt: data.session.expiresAt }; ``` The returned session token is: - Short-lived - Single-session - Safe to return to the browser ## Using the JWT in API Requests JWTs are used for all **backend API calls**. ```http POST https://api.nelnetpay.com/payments Authorization: Bearer Content-Type: application/json ``` ## Using the Session Token in the SDK The **session token** is used exclusively by the client-side SDK to authorize tokenization within the embedded iframe. ```js const nps = new NPS({ sessionId, sessionToken, onReady: () => console.log('Payment form ready'), onTokenizationComplete: handleTokenization, onError: handleError }); ``` div strong Session token characteristics: ul li Authorize tokenization in the browser li Are short-lived and single-purpose li Cannot be used to call backend APIs ## JWT Expiration Behavior JWT expiration is enforced strictly. - Tokens are valid **only** within their allowed window - Expired tokens return `401 Unauthorized` - Tokens cannot be refreshed — create a new one ### Best Practices - Use **short-lived tokens** (1–5 minutes) - Generate JWTs on demand - Cache briefly if needed, never long-term ## API Key–Defined Limits Each API key defines limits that JWTs cannot exceed: - **JWT token duration** - **Allowed services** (Payments, Reporting) - **Key start and end dates** JWT claims are validated against these limits at request time. ## Platform vs Merchant Authentication div strong Key idea: br Authentication and transaction context are intentionally separated. JWTs authenticate **who you are**, not **who you are acting as**. ```json { "entityId": 1325691045, "transactionType": "SALE", "amount": 49.99 } ``` - JWT → authenticates the platform or parent entity - `entityId` → specifies the merchant context This enables secure multi-merchant and platform integrations. ## Security Best Practices - Store API keys in a secure secrets manager - Rotate API keys periodically - Never log JWTs or API secrets - Use separate keys for production and non-production ## Error Responses If authentication fails, APIs return: ```http 401 Unauthorized ``` Common causes: - Expired JWT - Invalid signature - Incorrect `sub` - JWT signed with the wrong API key ## Summary - All backend NPS APIs use **Bearer JWT authentication** - Frontend SDKs use **session tokens**, not JWTs - JWTs are signed using **HS512** - API Key ID → `sub` - API Key → signing secret - JWTs are short-lived and non-refreshable - `entityId` controls transaction context, not authentication