@saasbase-io/loginflow-websdk
v1.10.4
Published
Loginflow WebSDK for browser-based SPA applications
Readme
Loginflow WebSDK
A TypeScript SDK for browser-based SPA applications to integrate with Loginflow authentication APIs. Features automatic flow management, state persistence, and token refresh.
Features
- 🚀 Automatic Flow Management: Detects signin/signup flows from URL paths
- 💾 State Persistence: Resumes authentication flows after page refresh
- 🔄 Token Refresh: Background token refresh at 80% of token lifetime
- 🍪 Session Management: Cookie-based sessions with automatic handling
- 📦 Multiple Build Formats: UMD, ESM for flexible integration
- 🔒 TypeScript Support: Full type definitions included
- ⚡ Simple API: Single initialization method with automatic flow setup
Installation
npm install @saasbase-io/loginflow-websdkOr include directly via CDN:
<script src="https://unpkg.com/@saasbase-io/loginflow-websdk/dist/loginflow-websdk.min.js"></script>Quick Start
ES6 Modules
import { LoginflowSDK } from '@saasbase-io/loginflow-websdk';
// Initialize SDK with automatic flow management
const response = await LoginflowSDK.init({
apiUrl: 'https://api.example.com',
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
locale: 'en-US',
// flowType: 'signin' // Optional: override auto-detection
});
// SDK is ready to use
const { sdk, flowType, isResumed } = response;
if (isResumed) {
console.log('Resumed existing flow:', flowType);
} else {
console.log('Started new flow:', flowType);
}
// Process authentication events
const eventResponse = await sdk.processEvent({
event: 'signin',
data: {
username: '[email protected]',
password: 'password'
}
});Browser (UMD)
const response = await LoginflowSDK.LoginflowSDK.init({
apiUrl: 'https://api.example.com',
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
locale: 'en-US'
});
const sdk = response.sdk;React Integration
import { useEffect, useState } from 'react';
import { LoginflowSDK } from '@saasbase-io/loginflow-websdk';
function AuthFlow() {
const [sdk, setSdk] = useState(null);
const [flowState, setFlowState] = useState(null);
useEffect(() => {
const initSDK = async () => {
try {
const response = await LoginflowSDK.init({
apiUrl: process.env.REACT_APP_API_URL,
clientId: process.env.REACT_APP_CLIENT_ID,
clientSecret: process.env.REACT_APP_CLIENT_SECRET,
locale: 'en'
});
setSdk(response.sdk);
setFlowState(response);
} catch (error) {
console.error('SDK init failed:', error);
}
};
initSDK();
return () => sdk?.cleanup();
}, []);
if (!flowState) return <div>Loading...</div>;
return (
<div>
{flowState.isResumed && <p>Welcome back!</p>}
{/* Render UI based on flowState.render_spec */}
</div>
);
}API Reference
Static Initialization
LoginflowSDK.init(config: LoginflowConfig): Promise<InitSDKResponse>Config Options:
apiUrl(string, required): Base URL of the Loginflow APIclientId(string, required): Your application's client IDclientSecret(string, required): Your application's client secretlocale(string, optional): Locale for the authentication flow (default: 'en')flowType('signin' | 'signup', optional): Override automatic flow detectionapiKey(string, optional): API key for authenticationtimeout(number, optional): Request timeout in milliseconds (default: 30000)headers(object, optional): Additional headers to include in all requests
Response:
{
sdk: LoginflowSDK; // SDK instance ready to use
flowType: FlowType; // Detected or specified flow type
isResumed: boolean; // Whether an existing flow was resumed
state: string; // Current flow state
render_spec?: any; // UI rendering instructions
auth_result?: AuthResult; // Authentication result (if completed)
redirect_url?: string; // Redirect URL (if applicable)
}Instance Methods
processEvent(request: ProcessEventRequest): Promise
Processes events within an active authentication flow.
Parameters:
{
event: string; // Event type (e.g., 'signin', 'signup', 'verify_otp', 'resume')
data?: { // Event-specific data
[key: string]: any;
}
}Response:
{
state: string; // Current flow state
render_spec?: any; // Updated UI rendering instructions
auth_result?: AuthResult; // Authentication result (if completed)
redirect_url?: string; // Redirect URL for OAuth flows
}startFlow(request: StartFlowRequest): Promise
Manually starts a new authentication flow (advanced usage).
Note: Most applications should use the automatic flow management via init().
getCurrentSession(): AuthSession | null
Returns the current authenticated session with tokens.
const session = sdk.getCurrentSession();
if (session) {
console.log('Access token:', session.access_token);
console.log('Expires at:', new Date(session.expires_at));
}getAuthenticatedUser(): User | null
Returns the authenticated user information from the ID token.
const user = sdk.getAuthenticatedUser();
if (user) {
console.log('User email:', user.email);
console.log('User name:', user.name);
}isAuthenticated(): boolean
Checks if the user is currently authenticated.
if (sdk.isAuthenticated()) {
// User is logged in
}cleanup(): void
Cleanup method to call when unmounting/destroying the SDK instance.
// Clean up timers and pending operations
sdk.cleanup();Flow Management
The SDK automatically manages authentication flows with intelligent detection and persistence.
Automatic Flow Detection
The SDK detects the flow type from the URL path:
/signin,/login→ Sign-in flow/signup,/register→ Sign-up flow
State Persistence
- Separate Storage: Sign-in and sign-up flows are stored separately
- Automatic Resume: Flows resume automatically after page refresh
- 30-Minute Expiry: Flows expire after 30 minutes of inactivity
- Completion Cleanup: Flow states are cleared upon successful authentication
Manual Flow Control
Override automatic detection when needed:
const response = await LoginflowSDK.init({
apiUrl: 'https://api.example.com',
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
locale: 'en',
flowType: 'signup' // Force signup flow regardless of URL
});Token Management
Automatic Token Refresh
The SDK automatically refreshes tokens in the background:
- Triggers at 80% of token lifetime
- Runs silently without user interruption
- Updates stored tokens automatically
- Schedules next refresh cycle
Manual Token Management
// Get current session with tokens
const session = sdk.getCurrentSession();
// Check token expiry
if (session && Date.now() >= session.expires_at) {
console.log('Token expired');
}Error Handling
The SDK throws LoginflowError with structured error information:
try {
const response = await LoginflowSDK.init({ ... });
} catch (error) {
if (error instanceof LoginflowError) {
console.error('Error code:', error.code);
console.error('Error message:', error.message);
console.error('Error details:', error.details);
}
}Common error codes:
CONFIG_ERROR: Invalid SDK configurationVALIDATION_ERROR: Invalid request parametersFLOW_TYPE_ERROR: Unable to determine flow typeNETWORK_ERROR: Network connectivity issuesTIMEOUT: Request timeoutAPI_ERROR: Server-side errorSTART_FLOW_ERROR: Failed to start flowPROCESS_EVENT_ERROR: Failed to process event
Session Management
The SDK automatically handles session cookies. After successful authentication:
- Session maintained through browser cookies
- Uses
credentials: 'include'for all API calls - Tokens stored securely in localStorage
- Automatic cleanup on logout
TypeScript Types
The SDK exports all necessary TypeScript types:
import type {
LoginflowConfig,
InitSDKResponse,
StartFlowRequest,
StartFlowResponse,
ProcessEventRequest,
ProcessEventResponse,
AuthSession,
User,
FlowType,
FlowState
} from '@saasbase-io/loginflow-websdk';Development
Setup
# Install dependencies
npm install
# Build the SDK
npm run build
# Run in development mode
npm run devRunning Examples
# Build the SDK first
npm run build
# Start the example server
npm run example
# Open in your browser:
# - Home: http://localhost:3001
# - Sign In: http://localhost:3001/signin
# - Sign Up: http://localhost:3001/signupAvailable Scripts
npm run build- Build production bundlesnpm run dev- Build and watch for changesnpm run lint- Run ESLintnpm run typecheck- Check TypeScript typesnpm run example- Start example server on port 3001npm test- Run tests (when implemented)
Project Structure
loginflow-websdk/
├── src/
│ ├── index.ts # Main exports
│ ├── loginflow-sdk.ts # SDK implementation
│ ├── http-client.ts # HTTP client wrapper
│ └── types.ts # TypeScript definitions
├── example/
│ ├── signin.html # Sign-in flow example
│ ├── signup.html # Sign-up flow example
│ └── server.js # Example HTTP server
├── dist/ # Built files
│ ├── loginflow-websdk.js # UMD bundle
│ ├── loginflow-websdk.min.js # Minified UMD
│ └── index.esm.js # ES module
└── types/ # Generated TypeScript declarationsBrowser Support
The SDK supports all modern browsers with ES2015+ support:
- Chrome 51+
- Firefox 54+
- Safari 10+
- Edge 15+
Migration Guide
From v1.0 to v1.1+
The main change is moving from a two-step initialization to a single async init:
Before (v1.0):
const sdk = new LoginflowSDK({ apiUrl: '...' });
const flow = await sdk.initializeFlow({
clientId: '...',
clientSecret: '...'
});After (v1.1+):
const { sdk } = await LoginflowSDK.init({
apiUrl: '...',
clientId: '...',
clientSecret: '...'
});Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Development Workflow
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Code Style
- Use TypeScript for all new code
- Follow existing code formatting
- Add tests for new features
- Update documentation as needed
License
MIT
Support
For issues and questions:
- GitHub Issues: Report a bug
- Documentation: Full API docs
