# @idp.global/idpclient A TypeScript client library for integrating with the idp.global Identity Provider. Works in both browser and Node.js environments. ## Overview The IdpClient provides a complete API for authentication, session management, and organization operations. It uses WebSocket connections via TypedSocket for real-time, type-safe communication with the IdP server. ## Installation ```bash npm install @idp.global/idpclient # or pnpm add @idp.global/idpclient ``` ## Quick Start ```typescript import { IdpClient } from '@idp.global/idpclient'; // Initialize the client const idpClient = new IdpClient('https://idp.global'); // Enable WebSocket connection await idpClient.enableTypedSocket(); // Check login status const isLoggedIn = await idpClient.determineLoginStatus(); if (isLoggedIn) { const userInfo = await idpClient.whoIs(); console.log('Logged in as:', userInfo.user.data.name); } ``` ## Core Features ### Authentication #### Password Login ```typescript const response = await idpClient.requests.loginWithUserNameAndPassword.fire({ username: 'user@example.com', password: 'securepassword', }); if (response.refreshToken) { await idpClient.refreshJwt(response.refreshToken); console.log('Login successful!'); } else if (response.twoFaNeeded) { console.log('2FA verification required'); } ``` #### Magic Link Login ```typescript // Request magic link await idpClient.requests.loginWithEmail.fire({ email: 'user@example.com', }); // After clicking the email link const result = await idpClient.requests.loginWithEmailAfterToken.fire({ email: 'user@example.com', token: 'token-from-email-link', }); if (result.refreshToken) { await idpClient.refreshJwt(result.refreshToken); } ``` #### API Token Login ```typescript const result = await idpClient.requests.loginWithApiToken.fire({ apiToken: 'your-api-token', }); if (result.jwt) { await idpClient.setJwt(result.jwt); } ``` ### Session Management ```typescript // Get current JWT const jwt = await idpClient.getJwt(); // Get parsed JWT data const jwtData = await idpClient.getJwtData(); console.log('User ID:', jwtData.id); // Refresh JWT (automatic housekeeping) await idpClient.performJwtHousekeeping(); // Manual refresh await idpClient.refreshJwt(); // Logout await idpClient.logout(); ``` ### User Information ```typescript // Get current user details const whoIsResponse = await idpClient.whoIs(); console.log('Name:', whoIsResponse.user.data.name); console.log('Email:', whoIsResponse.user.data.email); // Get user data const userData = await idpClient.requests.getUserData.fire({ jwt: await idpClient.getJwt(), userId: jwtData.id, }); // Update user data await idpClient.requests.setUserData.fire({ jwt: await idpClient.getJwt(), userId: jwtData.id, name: 'New Name', }); ``` ### Organization Management ```typescript // Get user's organizations and roles const orgsAndRoles = await idpClient.getRolesAndOrganizations(); console.log('Organizations:', orgsAndRoles.organizations); console.log('Roles:', orgsAndRoles.roles); // Create a new organization const result = await idpClient.createOrganization( 'My Company', // name 'my-company', // slug 'manifest' // mode: 'checkAvailability' or 'manifest' ); if (result.resultingOrganization) { console.log('Created:', result.resultingOrganization.id); } // Get organization details const orgDetails = await idpClient.requests.getOrganizationById.fire({ jwt: await idpClient.getJwt(), organizationId: 'org-id', }); ``` ### Member & Invitation Management ```typescript // Get organization members const members = await idpClient.requests.getOrgMembers.fire({ jwt: await idpClient.getJwt(), organizationId: 'org-id', }); // Invite a new member await idpClient.requests.createInvitation.fire({ jwt: await idpClient.getJwt(), organizationId: 'org-id', email: 'newmember@example.com', roles: ['member'], }); // Bulk invite members await idpClient.requests.bulkCreateInvitations.fire({ jwt: await idpClient.getJwt(), organizationId: 'org-id', invitations: [ { email: 'user1@example.com', roles: ['member'] }, { email: 'user2@example.com', roles: ['admin'] }, ], }); // Accept an invitation await idpClient.requests.acceptInvitation.fire({ jwt: await idpClient.getJwt(), invitationToken: 'token-from-invite-email', }); // Remove a member await idpClient.requests.removeMember.fire({ jwt: await idpClient.getJwt(), organizationId: 'org-id', userId: 'user-id', }); // Transfer ownership await idpClient.requests.transferOwnership.fire({ jwt: await idpClient.getJwt(), organizationId: 'org-id', newOwnerId: 'new-owner-user-id', }); ``` ### Password Management ```typescript // Request password reset await idpClient.requests.resetPassword.fire({ email: 'user@example.com', }); // Set new password (with token from email) await idpClient.requests.setNewPassword.fire({ email: 'user@example.com', tokenArg: 'reset-token', newPassword: 'newsecurepassword', }); // Change password (when logged in) await idpClient.requests.setNewPassword.fire({ email: 'user@example.com', oldPassword: 'currentpassword', newPassword: 'newsecurepassword', }); ``` ### Session & Device Management ```typescript // Get active sessions const sessions = await idpClient.requests.getUserSessions.fire({ jwt: await idpClient.getJwt(), userId: jwtData.id, }); // Revoke a session await idpClient.requests.revokeSession.fire({ jwt: await idpClient.getJwt(), sessionId: 'session-id', }); // Get device ID const deviceInfo = await idpClient.requests.obtainDeviceId.fire({}); // Attach device to session await idpClient.requests.attachDeviceId.fire({ jwt: await idpClient.getJwt(), deviceId: deviceInfo.deviceId.id, }); ``` ### Cross-Domain Authentication ```typescript // Get transfer token for SSO between apps const transferToken = await idpClient.getTransferToken(); // Switch to another app with authentication await idpClient.getTransferTokenAndSwitchToLocation('https://app.example.com/'); // Process incoming transfer token (in target app) const success = await idpClient.processTransferToken(); if (success) { console.log('Cross-domain login successful'); } ``` ### Billing Integration ```typescript // Get billing plan for an organization const billingPlan = await idpClient.requests.getBillingPlan.fire({ jwt: await idpClient.getJwt(), organizationId: 'org-id', }); // Get Paddle configuration const paddleConfig = await idpClient.requests.getPaddleConfig.fire({ jwt: await idpClient.getJwt(), }); // Update payment method await idpClient.updatePaddleCheckoutId('org-id', 'checkout-id'); ``` ### Admin Operations (Global Admins Only) ```typescript // Check if user is global admin const isAdmin = await idpClient.requests.checkGlobalAdmin.fire({ jwt: await idpClient.getJwt(), }); // Get platform statistics const stats = await idpClient.requests.getGlobalAppStats.fire({ jwt: await idpClient.getJwt(), }); // Create a global app await idpClient.requests.createGlobalApp.fire({ jwt: await idpClient.getJwt(), name: 'My App', description: 'App description', }); // Suspend a user await idpClient.requests.suspendUser.fire({ jwt: await idpClient.getJwt(), userId: 'user-id', }); ``` ## Reactive Subscriptions The client provides RxJS subjects for reactive updates: ```typescript // Subscribe to login status changes idpClient.statusObservable.subscribe((status) => { console.log('Login status changed:', status); }); // Subscribe to roles updates idpClient.rolesReplaySubject.subscribe((roles) => { console.log('Roles updated:', roles); }); // Subscribe to organizations updates idpClient.organizationsReplaySubject.subscribe((orgs) => { console.log('Organizations updated:', orgs); }); ``` ## API Reference ### IdpClient Class | Method | Description | |--------|-------------| | `enableTypedSocket()` | Initialize WebSocket connection | | `determineLoginStatus(requireLogin?)` | Check if user is logged in | | `getJwt()` | Get stored JWT string | | `getJwtData()` | Get parsed JWT data | | `setJwt(jwt)` | Store JWT | | `deleteJwt()` | Remove stored JWT | | `refreshJwt(refreshToken?)` | Refresh the JWT | | `performJwtHousekeeping()` | Auto-refresh JWT if needed | | `logout()` | End session and redirect | | `whoIs()` | Get current user info | | `getRolesAndOrganizations()` | Get user's orgs and roles | | `createOrganization(name, slug, mode)` | Create new organization | | `getTransferToken(appData?)` | Get SSO transfer token | | `processTransferToken()` | Process incoming transfer token | | `stop()` | Close WebSocket connection | ### IdpRequests Class Access via `idpClient.requests.*`: **Authentication**: `loginWithUserNameAndPassword`, `loginWithEmail`, `loginWithEmailAfterToken`, `loginWithApiToken`, `resetPassword`, `setNewPassword` **User**: `getUserData`, `setUserData`, `getUserSessions`, `revokeSession`, `getUserActivity` **Organization**: `getOrganizationById`, `updateOrganization`, `createInvitation`, `bulkCreateInvitations`, `getOrgMembers`, `getOrgInvitations`, `acceptInvitation`, `cancelInvitation`, `resendInvitation`, `removeMember`, `updateMemberRoles`, `transferOwnership` **Billing**: `getBillingPlan`, `getPaddleConfig` **Admin**: `checkGlobalAdmin`, `getGlobalAppStats`, `createGlobalApp`, `updateGlobalApp`, `deleteGlobalApp`, `suspendUser`, `deleteSuspendedUser` ## License and Legal Information This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](../LICENSE) file. **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file. ### Trademarks This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar. ### Company Information Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany For any legal inquiries or further information, please contact us via email at hello@task.vc. By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.