SSO Integration Specification: Client Application ➔ IDENTIK ➔ Pinter

This document contains the complete technical specification for Single Sign-On (SSO) integration between External Client Applications (e.g., Sentra, Portal, etc.), IDENTIK (FusionAuth), and Pinter Backend (FastAPI). It serves as a standard guide for any client application development team to implement integration independently.

1. Architecture & Logic Flow (High-Level Sequence)

This integration uses a hybrid token-exchange method to ensure maximum security without exposing sensitive credentials (Client Secret) to the frontend/browser.

2. Prerequisites (Client Application Registration in Pinter)

Before integration begins, the Pinter Admin Team must register the new client application in the Pinter database applications table to generate an Application ID (Client ID) and Client Secret specific to that client application. These credentials are then provided to the client application development team for installation in their backend.
WARNING SECURITY & CREDENTIAL ISOLATION:
  • The Client Secret registered in Pinter MUST NOT BE THE SAME as the Client Secret used by the client application to access IDENTIK (FusionAuth).
  • Pinter must not and will never store or know the API Key/Client Secret belonging to the client application in IDENTIK. This prevents cross-system privilege abuse.
  • The credentials below are dedicated (special) credentials created only for the direct trust relationship between Client BE and Pinter BE.

Example SQL Script for Application Registration in Pinter DB (Manual Registration):

NOTE: Client application registration can also be performed by a Pinter Super Admin directly via the Pinter Admin Dashboard.

3. API Specification & Payload (Step-by-Step API Spec)

Step 1: Authorization Code Exchange (Client Backend ➔ IDENTIK SSO)

After the user successfully authenticates on the IDENTIK page, the Client Frontend receives the code parameter (Authorization Code) from the redirect URI. The Client Backend must exchange this code with IDENTIK SSO to obtain the original OIDC token.
  • Endpoint: POST <IDENTIK_SSO_BASE_URL>/oauth/token
  • Method: POST
  • Headers:
  • Request Body (form-urlencoded):
  • Response (JSON) from IDENTIK:
NOTE: The Client Backend must decode the id_token (a RS256 JWT from IDENTIK) to extract user information:
  • sub: Unique user ID in IDENTIK (e.g., "usr-910a3b-281a")
  • name: User’s full name (e.g., "Ahmad Saripuddin")
  • email: User’s official email (e.g., "ahmad.sarip@pupuk-indonesia.com")

Step 2: Local Custom JWT Creation (Client Backend)

Since Pinter uses symmetric verification (HS256) with the application shared secret (client_secret), the Client Backend must wrap the user data obtained from IDENTIK into a new Custom JWT signed independently by the Client Backend.

JWT Creation Parameters:

  • Algorithm: HS256
  • Secret Key: pinter-special-secret-for-client-998877 (Must exactly match the client_secret registered in Pinter’s applications table).
  • JWT Payload (Claims):

Implementation Examples:

Node.js (using jsonwebtoken library):
Python (using PyJWT library):

Step 3: Token Exchange at Pinter (Client Backend/Frontend ➔ Pinter BE)

The Client sends the created Custom JWT to the Pinter token exchange endpoint. At this step, Pinter automatically performs JIT (Just-In-Time) Provisioning (if the user has never accessed Pinter before, their account will be created automatically in the Pinter database with the standard role L4 Navigator).
  • Endpoint: POST <PINTER_API_BASE_URL>/api/v2/auth/sso/jwt
  • Method: POST
  • Headers:
  • Request Body:
  • Response (JSON):
TIP: The access_token returned from Pinter above is the official token authorized to access Pinter resources fully on behalf of that user. It has a standard expiry (e.g., 1 hour) and must be stored by the Client Frontend for Chatbot API calls.

Step 4: Accessing Chatbot API (Client Frontend ➔ Pinter BE)

After obtaining the access_token from Pinter, the Client Frontend can directly call Pinter Chatbot APIs to create conversation sessions and send messages.

4.1 Create New Conversation Session (Create Conversation)

  • Endpoint: POST <PINTER_API_BASE_URL>/api/v2/conversations
  • Method: POST
  • Headers:
  • Request Body:
  • Response (JSON):

4.2 Send Message & Receive Streaming Response (Send Message via SSE)

For an interactive user experience, Pinter’s message sending endpoint uses SSE (Server-Sent Events) protocol so the bot’s response can be streamed word-by-word in realtime.
  • Endpoint: POST <PINTER_API_BASE_URL>/api/v2/conversations/conv-7f83ad-1029/send
  • Method: POST
  • Headers:
  • Request Body:
  • Response (text/event-stream):

4.3 Get Conversation List (List Conversations)

Retrieves all conversation sessions (chat sessions) created by the user. Based on access control flow, if the user enters through an external client application, this endpoint only returns conversations created in that client application.
  • Endpoint: GET <PINTER_API_BASE_URL>/api/v2/conversations
  • Method: GET
  • Headers:
  • Query Parameters:
    • search (optional string): Search keyword for conversation title.
    • limit (optional integer, default 50): Maximum number of records returned.
    • offset (optional integer, default 0): Offset for pagination.
  • Response (JSON):

4.4 Get Message History (Get History Chat / Messages)

Retrieves the complete message history within a conversation session in chronological order.
  • Endpoint: GET <PINTER_API_BASE_URL>/api/v2/conversations/{conversation_id}/messages
  • Method: GET
  • Headers:
  • Query Parameters:
    • limit (optional integer, default 50): Maximum number of messages returned.
    • offset (optional integer, default 0): Offset for pagination.
  • Response (JSON):

4.5 Cancel Chat Response (Cancel Chat / Streaming SSE Abort)

Since message sending uses HTTP streaming (Server-Sent Events), cancelling a chat response (cancel/stop generating) on the client side is done by aborting the running HTTP streaming connection.
  • Frontend Mechanism: Use AbortController on Fetch API (or .close() method on EventSource) to cancel the request.
  • JavaScript/TypeScript Example:
  • Backend Mechanism: Pinter Backend detects the lost TCP client connection in realtime, terminates the model/agent execution loop, and releases memory allocation and resources associated with that request.

4. Integration Architecture Benefits

  1. Maximum Security: Pinter’s Client Secret (client_secret) is stored securely only in the client application backend and Pinter backend, never exposed to the frontend browser/user.
  2. Just-In-Time Provisioning: Users from the client application don’t need manual account creation in Pinter. The moment they first click the Pinter feature from your client application, their account is automatically created with name and email synced from IDENTIK.
  3. SSE Streaming Support: Using the genuine Pinter token from the exchange allows the Client Frontend to leverage HTTP streaming (SSE) directly and securely for extremely fast and responsive chat interactions.