Understanding how the IPification Showcase works at a high level.
- What is this app?
- How it works
- Key Components
- Authentication Flows
- Configuration
- Security
- Extending the App
- Technical Details
A showcase/demo application for IPification authentication services. It demonstrates:
- β Multiple authentication methods (IP, IM, SIM)
- β Phone number verification flows
- β QR code authentication for desktop
- β Multi-server support (stage, live, etc.)
Tech stack: Node.js + Express + Pug templates
βββββββββββββββ ββββββββββββββββ βββββββββββββββββββ
β Browser ββββββββββ This App ββββββββββ IPification API β
β β β (Express) β β (OAuth Server) β
βββββββββββββββ ββββββββββββββββ βββββββββββββββββββ
Flow:
1. User clicks button
2. App redirects to IPification
3. User authenticates
4. IPification redirects back
5. App shows user info
- Pug Templates: Login page, user info page
- JavaScript: Button handlers, QR code, phone input
- CSS: Styling and animations
- Express Routes: Handle auth flow
- Session Management: Track user state
- OAuth2 Client: Talk to IPification
- WebSocket: For QR code flow (desktop β mobile)
- auth_servers: Which IPification servers to use
- clients: Which auth flows to enable
- locale: UI text customization
For the IP phone-verification walkthrough, request examples, and source map, see PNV via IP.
User clicks button
β
/auth/start (redirects to IPification)
β
User authenticates on IPification
β
/auth/callback (receives code)
β
Exchange code for user info
β
Show user info page
Desktop: Generate QR code with auth URL
Mobile: Scan QR β authenticate
Desktop: Receives notification via WebSocket β shows result
User clicks SIM button
β
Browser requests SIM credential
β
User confirms on device
β
Show verified phone number
Three main config files:
- config/default.json - Your setup (auth servers, clients, credentials)
- config/locale.json - UI text labels
- config/app_config.json - App behavior settings
See CONFIG_DEFAULT_JSON_SAMPLE.md for details.
- β OAuth2 authorization code flow
- State parameter for callback/result correlation; the standard web flow does not compare it against a saved session value (see PNV limitations)
- β Session management
- β HTTPS recommended for production
- β Helmet.js security headers
- Add client config in
config/default.json - Add button in
views/login.pug - Done! Routes handle it automatically
- Add to
auth_serversarray in config - Restart app
- Dropdown appears automatically
- Edit
config/locale.json - Or override in
config/default.json - Restart app
π Click for detailed architecture diagrams and module structure
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Express Application β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Routes β β Middleware β β Views β β
β β β β β β (Pug) β β
β β - auth.js β β - Session β β - login.pug β β
β β - user.js β β - Helmet β β - info.pug β β
β β - ts43.js β β - Logger β β - qr_*.pug β β
β β β β - Parser β β β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Services β β Libraries β β Socket.io β β
β β β β β β β β
β β - DataStore β β - Axios β β - Real-time β β
β β β β - GeoIP β β Events β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββ ββββββββββββ ββββββββββββββββ ββββββββββββ
β Browser β β Express β β IPification β β Browser β
ββββββ¬βββββ ββββββ¬ββββββ ββββββββ¬ββββββββ ββββββ¬ββββββ
β β β β
β GET /auth/startβ β β
ββββββββββββββββ>β β β
β β Build Auth URL β β
β βββββββββββββββββββ>β β
β β β β
β 302 Redirect β β β
β<ββββββββββββββββ€ β β
β β β β
β β β User Auth β
β β β<ββββββββββββββββββ€
β β β β
β β Callback β β
β β<βββββββββββββββββββ€ β
β β β β
β β Exchange Code β β
β βββββββββββββββββββ>β β
β β β β
β β Access Token β β
β β<βββββββββββββββββββ€ β
β β β β
β β Get User Info β β
β βββββββββββββββββββ>β β
β β β β
β β User Info β β
β β<βββββββββββββββββββ€ β
β β β β
β 302 Redirect β β β
β<ββββββββββββββββ€ β β
β β β β
β GET /auth/complete β β
ββββββββββββββββ>β β β
β β β β
β 302 Redirect β β β
β<ββββββββββββββββ€ β β
β β β β
β GET /user/info β β β
ββββββββββββββββ>β β β
β β β β
β HTML Response β β β
β<ββββββββββββββββ€ β β
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ
β Desktop β β Express β β Mobile β βExpress β
β Browser β β Server β β Device β β Socket β
ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ
β β β β
β GET /auth/start β β β
ββββββββββββββββ>β β β
β β β β
β QR Code Display β β β
β<ββββββββββββββββ€ β β
β β β β
β Socket: init β β β
ββββββββββββββββ>β β β
β β Join Room β β
β βββββββββββββββββ>β β
β β β β
β β β Scan QR & Auth β
β β βββββββββββββββββ>β
β β β β
β β Callback β β
β β<ββββββββββββββββββββββββββββββββββ€
β β β β
β β Socket: url β β
β βββββββββββββββββ>β β
β β β β
β Socket Event β β β
β<ββββββββββββββββ€ β β
β β β β
β Navigate to URL β β β
ββββββββββββββββ>β β β
β β β β
β User Info β β β
β<ββββββββββββββββ€ β β
Request β Session Middleware β Session Store β Request Object
β
ββ> res.locals (template variables)
Browser β Generate State β /auth/start β Include in Auth URL
β
ββ> IPification
β
Callback ββββββββββββββββββββββββββββββββββββββββββββββββββ
β
ββ> Store User Info with State Key
β
Complete β Retrieve User Info β Data Store
Key Format: Value:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{state} { userInfo, client_id, ... }
{state}-user-info { raw user info object }
- Helmet.js: HTTP security headers
- Session Management: Secure session cookies
- State Parameter: Callback/result correlation; no standard web session-state comparison
- Input Validation: Parameter validation
- Secret Keys: Environment-based secrets
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Security Measures β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. State Parameter (Result Correlation) β
β - Generated on client β
β - Not compared against browser-session state β
β β
β 2. OAuth2 Authorization Code Flow β
β - Short-lived authorization codes β
β - Server-side token exchange β
β β
β 3. Session Management β
β - HttpOnly cookies β
β - Secure flag (HTTPS) β
β β
β 4. Secret Management β
β - Environment variables β
β - Git-ignored config files β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
app.js remains the application assembly point: it validates configuration, configures shared middleware and views, and explicitly registers the route prefixes.
| Module | Responsibility |
|---|---|
middleware/appLocals.js |
Create request locals with inherited client credentials, locale, base URL, and server/flow lookup helpers |
bootstrap/playIntegrity.js |
Initialize and mount Play Integrity only when PLAY_INTEGRITY_ENABLED=true, with the configured verification and attempt services |
Request locals run before the feature and general routes. Play Integrity is mounted before the general body parsers so its own 16 KB JSON parser and safe payload error responses take precedence. The TS43 auth rate limiter remains immediately before the TS43 router, and the application error handler remains last.
- Purpose: Register authentication endpoints; delegate HTTP handling to the web and API modules below.
- Key Functions:
GET /auth/login: Render login pageGET /auth/start: Initiate OAuth flowGET /auth/callback/:userFlow/:serverId: Handle OAuth callbackGET /auth/complete: Complete authenticationGET /auth/qrcode/complete: Render QR success pageGET /auth/qrcode/error: Render QR error pagePOST /auth/mobile/login: Mobile login endpointPOST /auth/s2s/signin: Server-to-server sign-in
| Module | Responsibility |
|---|---|
routes/auth/webHandlers.js |
Login/start/callback/completion handlers, page rendering, session updates, and QR socket notifications |
routes/auth/apiHandlers.js |
Mobile login and S2S sign-in HTTP responses |
services/authService.js |
Build authorization URLs and exchange authorization codes through utils/httpClient.js; no Express or cache access |
services/authResultStore.js |
Save formatted results and raw userinfo, read S2S userinfo, and poll for completion results using the existing memory cache |
The callback exchanges the provider code and fetches userinfo before saving the formatted response under state and raw userinfo under ${state}-user-info. After both writes complete, a backchannel request returns an empty 200 response. Otherwise, QR callbacks notify the desktop through Socket.IO and render the mobile result through a redirect; ordinary web callbacks redirect to /auth/complete. The desktop also uses /auth/complete to adopt the stored result into its browser session and continue to /user/info.
Completion polls the result cache up to five times, waiting one second after each miss, including the final miss. Reads retain the cached entries. Mobile login exchanges the code directly and returns userinfo without using this completion cache.
- Purpose: User information display
- Key Functions:
GET /user/info: Display authenticated user info
- Purpose: Register the TS43 endpoints and delegate to
routes/ts43/handlers.js. - Key Functions:
POST /ts43/auth: Initiate TS43 authenticationPOST /ts43/token: Exchange VP tokenPOST /ts43/log: Logging endpoint
- Purpose: Register the SMS endpoints and delegate to
routes/sms/handlers.js. - Key Functions:
POST /sms/auth: Initiate SMS authenticationPOST /sms/token: Submit the SMS code and exchange the CIBA request for userinfoPOST /sms/log: Logging endpoint
| Module | Responsibility |
|---|---|
routes/ts43/handlers.js, routes/sms/handlers.js |
Resolve server/client configuration, handle requests and responses, format display data, and update browser sessions |
services/ts43Service.js |
Start CIBA authentication, fetch DCQL data and build the digital request, then submit the VP callback and exchange for token/userinfo |
services/smsService.js |
Start CIBA SMS authentication, then submit the SMS callback and exchange for token/userinfo |
Both services expose startAuthentication and exchangeToken and operate without Express request/response objects. Provider callbacks are best-effort: a callback error is logged, then the token exchange still runs. The handlers retain the demo's existing session behavior: token/userinfo errors also populate an authenticated session with formatted error data. This extraction preserves those behaviors and the endpoint-specific error bodies; it does not introduce a shared CIBA abstraction.
- Purpose: Temporary data storage
- Implementation: In-memory cache using
cache-manager - TTL: 60 minutes
- Usage: Store authentication state and user information
- Purpose: Auth server lookup and validation utilities
- Key Functions:
getAuthServer(authServers, serverId): Get server by ID or default to firstgetAuthServerIds(authServers): Get all available server IDshasAuthServer(authServers, serverId): Check if server exists
- Purpose: Configuration validation on application startup
- Key Functions:
validateConfig(config): Main validation entry pointvalidateAuthServers(authServers): Validate auth servers arrayvalidateClients(clients): Validate client configurationsvalidateRealm(realm): Validate realm configurationvalidateCredentials(config): Validate OAuth credentials
- Behavior: Throws error and prevents app startup if validation fails
- Purpose: General utility functions
- Key Functions:
deepMerge(target, source): Deep merge objectsfindClientByUserFlow(clients, userFlow): Find client by flow IDfindClientByClientId(clients, clientId): Find client by client ID
- Purpose: Application constants
- Contents: HTTP status codes, error messages, retry settings
- Purpose: WebSocket server for real-time communication
- Implementation: Socket.io
- Channels: Room-based (
auth:{state}) - Events:
init: Client joins roommessages: Server sends events
1. Environment Variables (.env)
2. config/default.json
3. Default values in code
On application startup, configuration is validated using utils/validateConfig.js:
- Required Fields:
realm,auth_servers,client_id,client_secret,clients - Auth Servers: Must have at least one server with valid
idandurl - Clients: Must have unique
user_flowvalues - Behavior: App crashes on startup if validation fails
See Sample Config Reference for field descriptions.
app.js β require('config') β config/default.json
β
ββ> res.locals β Available in templates
Error Occurred
β
ββ> Try-Catch Block
β β
β ββ> Log Error
β β
β ββ> Error Handler Middleware
β β
β ββ> HTTP Error Response
β
ββ> OAuth Errors
β
ββ> Redirect to Login with Error Message
- Data Store: In-memory cache with 60-minute TTL
- Session Store: Memory-based (consider Redis for production)
- Static Assets: Express static middleware
- Redis Integration: Replace in-memory cache with Redis
- Session Store: Use Redis session store for scalability
- Rate Limiting: Implement rate limiting middleware
- Connection Pooling: Configure HTTP client connection pooling
βββββββββββββββββββββββββββββββββββββββββββ
β Docker Compose Stack β
βββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββ βββββββββββββββ β
β β App ββββββββ Redis β β
β β Container β β Container β β
β β Port: 8080 β β Port: 6379 β β
β βββββββββββββββ βββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββ
- Environment Variables: Use secrets management
- HTTPS: Configure reverse proxy (nginx/traefik)
- Load Balancing: Multiple app instances
- Monitoring: Application performance monitoring
- Logging: Centralized logging system
- Add client configuration to
config/default.json(see Sample Config Reference) - Add UI button in
views/login.pug - Add JavaScript handler in
public/js/login.js - Flow automatically handled by existing routes
- Extend
routes/auth.jswith new endpoint - Implement OAuth2/OIDC flow
- Add UI components
- Update documentation
- Modify
views/info.pugtemplate - Update
routes/user.jsif needed - Customize styling in
public/css/
- express: Web framework
- express-session: Session management
- socket.io: WebSocket server
- axios: HTTP client
- pug: Template engine
- config: Configuration management
- helmet: Security headers
- cookie-parser: Cookie parsing
- uuid: UUID generation
- geoip-lite: GeoIP lookup
- cache-manager: Caching abstraction
- Redis Integration: Replace in-memory cache
- Rate Limiting: Add rate limiting middleware
- API Versioning: Implement API versioning
- OpenAPI Documentation: Generate OpenAPI specs
- Testing: Add unit and integration tests
- Monitoring: Add application monitoring
- Logging: Structured logging with correlation IDs