Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a91dd9dda6 | |||
| 5462257398 |
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-12-16 - 1.14.0 - feat(docs)
|
||||
add package READMEs and publish metadata; update web package publish order
|
||||
|
||||
- Add comprehensive README for ts_web (web components/UI)
|
||||
- Add README for ts_idpclient (TypeScript client)
|
||||
- Add README for ts_interfaces (type definitions/interfaces)
|
||||
- Add tspublish.json for ts_idpcli (@idp.global/cli) and ts_idpclient (@idp.global/client)
|
||||
- Update ts_web/tspublish.json order from 4 to 5
|
||||
|
||||
## 2025-12-15 - 1.13.0 - feat(oidc)
|
||||
feat(oidc): add OIDC provider (OidcManager, endpoints, and interfaces)
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@idp.global/idp.global",
|
||||
"version": "1.13.0",
|
||||
"version": "1.14.0",
|
||||
"description": "An identity provider software managing user authentications, registrations, and sessions.",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
|
||||
@@ -1,312 +1,328 @@
|
||||
# @idp.global/idp.global
|
||||
|
||||
An identity provider software managing user authentications, registrations, and sessions.
|
||||
🔐 **A modern, open-source Identity Provider (IdP) SaaS platform** for managing user authentication, registrations, sessions, and organization-based access control.
|
||||
|
||||
## Install
|
||||
Built with TypeScript and designed for modern web applications, idp.global provides a complete identity management solution that you can self-host or use as a service.
|
||||
|
||||
To install `@idp.global/idp.global`, you can run the following command in your terminal:
|
||||
## Issue Reporting and Security
|
||||
|
||||
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
||||
|
||||
## ✨ Features
|
||||
|
||||
### 🔑 Authentication & Authorization
|
||||
- **Multiple Login Methods**: Email/password, email magic links, API tokens
|
||||
- **JWT-Based Sessions**: Secure token management with automatic refresh
|
||||
- **Two-Factor Authentication**: Enhanced security with 2FA support
|
||||
- **Password Reset**: Secure password recovery flow
|
||||
- **Device Management**: Track and manage authenticated devices
|
||||
|
||||
### 🏢 Organization Management
|
||||
- **Multi-Tenant Architecture**: Support multiple organizations per user
|
||||
- **Role-Based Access Control (RBAC)**: Fine-grained permissions system
|
||||
- **Organization Roles**: Admin, member, and custom role support
|
||||
- **Member Invitations**: Bulk invite and manage team members
|
||||
- **Ownership Transfer**: Seamlessly transfer organization ownership
|
||||
|
||||
### 🔗 Third-Party Integration
|
||||
- **OpenID Connect (OIDC) Provider**: Full OIDC compliance for third-party apps
|
||||
- Discovery endpoint (`/.well-known/openid-configuration`)
|
||||
- JWKS endpoint for token verification
|
||||
- Authorization code flow with PKCE
|
||||
- Token refresh and revocation
|
||||
- **OAuth 2.0**: Standard OAuth flows for app authorization
|
||||
- **Supported Scopes**: `openid`, `profile`, `email`, `organizations`, `roles`
|
||||
|
||||
### 💳 Billing Integration
|
||||
- **Paddle Integration**: Built-in payment processing support
|
||||
- **Billing Plans**: Flexible subscription management
|
||||
- **Checkout Flows**: Streamlined payment experiences
|
||||
|
||||
### 🎨 Modern Web UI
|
||||
- **Responsive Design**: Beautiful UI components built with `@design.estate/dees-catalog`
|
||||
- **Account Management**: User profile, settings, and preferences
|
||||
- **Organization Dashboard**: Manage members, roles, and apps
|
||||
- **Admin Panel**: Global administration interface
|
||||
|
||||
### 📡 Real-Time Communication
|
||||
- **WebSocket Support**: Real-time updates via TypedSocket
|
||||
- **Typed API Requests**: Type-safe client-server communication
|
||||
- **Public Key Distribution**: Automatic JWT key rotation notifications
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
idp.global is built as a modular TypeScript monorepo:
|
||||
|
||||
```
|
||||
├── ts/ # Server-side code (Node.js)
|
||||
│ └── reception/ # Core identity management logic
|
||||
├── ts_interfaces/ # Shared TypeScript interfaces (published as @idp.global/interfaces)
|
||||
├── ts_idpclient/ # Browser/Node client library (published as @idp.global/idpclient)
|
||||
├── ts_idpcli/ # Command-line interface tool
|
||||
└── ts_web/ # Web frontend (published as @idp.global/web)
|
||||
```
|
||||
|
||||
### Core Managers
|
||||
|
||||
| Manager | Responsibility |
|
||||
|---------|----------------|
|
||||
| `JwtManager` | JWT generation, validation, and key management |
|
||||
| `LoginSessionManager` | Session creation and authentication |
|
||||
| `UserManager` | User CRUD and profile management |
|
||||
| `OrganizationManager` | Organization lifecycle management |
|
||||
| `RoleManager` | RBAC and permission management |
|
||||
| `OidcManager` | OpenID Connect provider functionality |
|
||||
| `AppManager` | OAuth client app registration |
|
||||
| `BillingPlanManager` | Subscription and payment handling |
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### 🐳 Docker Deployment (Recommended)
|
||||
|
||||
The easiest way to run idp.global is using Docker:
|
||||
|
||||
```bash
|
||||
npm install @idp.global/idp.global
|
||||
# Pull the latest image
|
||||
docker pull code.foss.global/idp.global/idp.global
|
||||
|
||||
# Run with environment variables
|
||||
docker run -d \
|
||||
-p 2999:2999 \
|
||||
-e MONGODB_URL=mongodb://your-mongo:27017/idp \
|
||||
-e IDP_BASEURL=https://your-domain.com \
|
||||
-e INSTANCE_NAME=idp.global \
|
||||
code.foss.global/idp.global/idp.global
|
||||
```
|
||||
|
||||
This will download and install the necessary dependencies along with the module to your project.
|
||||
### Environment Variables
|
||||
|
||||
## Usage
|
||||
| Variable | Description | Required |
|
||||
|----------|-------------|----------|
|
||||
| `MONGODB_URL` | MongoDB connection string | ✅ Yes |
|
||||
| `IDP_BASEURL` | Public URL of your idp.global instance | ✅ Yes |
|
||||
| `INSTANCE_NAME` | Name for this IDP instance | No (default: `idp.global`) |
|
||||
| `SERVEZONE_PLATFROM_AUTHORIZATION` | ServeZone platform auth token | No |
|
||||
|
||||
To use `@idp.global/idp.global`, one needs to understand its key components and functionalities. Below, we'll guide you through setting up, logging in, registering, and managing users and organizations within an IDP (Identity Provider) environment using this package.
|
||||
### Docker Compose Example
|
||||
|
||||
### Setting Up the Environment
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
idp:
|
||||
image: code.foss.global/idp.global/idp.global
|
||||
ports:
|
||||
- "2999:2999"
|
||||
environment:
|
||||
MONGODB_URL: mongodb://mongo:27017/idp
|
||||
IDP_BASEURL: https://idp.yourdomain.com
|
||||
INSTANCE_NAME: my-idp
|
||||
depends_on:
|
||||
- mongo
|
||||
|
||||
First, let's set up the environment:
|
||||
mongo:
|
||||
image: mongo:7
|
||||
volumes:
|
||||
- mongo-data:/data/db
|
||||
|
||||
```typescript
|
||||
// Import the necessary modules
|
||||
import * as serviceworker from '@api.global/typedserver/web_serviceworker_client';
|
||||
import * as domtools from '@design.estate/dees-domtools';
|
||||
import { html, render } from '@design.estate/dees-element';
|
||||
import { IdpWelcome } from './elements/idp-welcome.js';
|
||||
|
||||
// Define an asynchronous run function
|
||||
const run = async () => {
|
||||
// Set up DOM tools
|
||||
const domtoolsInstance = await domtools.DomTools.setupDomTools();
|
||||
domtools.elementBasic.setup();
|
||||
|
||||
// Configure website information
|
||||
domtoolsInstance.setWebsiteInfo({
|
||||
metaObject: {
|
||||
title: 'idp.global',
|
||||
description: 'the code that runs idp.global',
|
||||
canonicalDomain: 'https://idp.global',
|
||||
ldCompany: {
|
||||
name: 'Task Venture Capital GmbH',
|
||||
status: 'active',
|
||||
contact: {
|
||||
address: {
|
||||
name: 'Task Venture Capital GmbH',
|
||||
city: 'Grasberg',
|
||||
country: 'Germany',
|
||||
houseNumber: '24',
|
||||
postalCode: '28879',
|
||||
streetName: 'Eickedorfer Vorweide',
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Set up the service worker
|
||||
const serviceWorker = await serviceworker.getServiceworkerClient();
|
||||
|
||||
// Render the main template
|
||||
const mainTemplate = html`
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
--background-accent: #303f9f;
|
||||
}
|
||||
</style>
|
||||
<idp-welcome></idp-welcome>
|
||||
`;
|
||||
|
||||
render(mainTemplate, document.body);
|
||||
};
|
||||
|
||||
// Run the function
|
||||
run();
|
||||
volumes:
|
||||
mongo-data:
|
||||
```
|
||||
|
||||
### Using the IDP Client
|
||||
The server listens on port 2999 by default.
|
||||
|
||||
The IDP Client is essential to communicate with the IDP server. Below is a sample of how to set up and use the IDP client:
|
||||
## 📦 Published Packages
|
||||
|
||||
This monorepo publishes the following npm packages:
|
||||
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| `@idp.global/interfaces` | TypeScript interfaces for API contracts |
|
||||
| `@idp.global/idpclient` | Client library for browser and Node.js |
|
||||
| `@idp.global/web` | Web UI components |
|
||||
|
||||
## 💻 Client Usage
|
||||
|
||||
### Browser Client
|
||||
|
||||
```typescript
|
||||
import { IdpState } from './idp.state.js';
|
||||
import * as plugins from './plugins.js';
|
||||
import { IdpClient } from '@idp.global/idpclient';
|
||||
|
||||
// Instantiate IdpState which provides a singleton instance
|
||||
export class IdpDemo {
|
||||
private idpState = IdpState.getSingletonInstance();
|
||||
// Initialize the client
|
||||
const idpClient = new IdpClient('https://idp.global');
|
||||
|
||||
// Function to initialize and use IdpClient
|
||||
public async demo() {
|
||||
// Fetch the client instance
|
||||
const { idpClient } = this.idpState;
|
||||
// Handler for login
|
||||
const handleLogin = async () => {
|
||||
const response = await idpClient.requests.loginWithUserNameAndPassword.fire({
|
||||
// Enable WebSocket connection
|
||||
await idpClient.enableTypedSocket();
|
||||
|
||||
// Check login status
|
||||
const isLoggedIn = await idpClient.determineLoginStatus();
|
||||
|
||||
// Login with email and password
|
||||
const response = await idpClient.requests.loginWithUserNameAndPassword.fire({
|
||||
username: 'user@example.com',
|
||||
password: 'password123',
|
||||
});
|
||||
if (response.refreshToken) {
|
||||
await idpClient.storeJwt(response.jwt);
|
||||
console.log("Logged in successfully, JWT stored.");
|
||||
} else {
|
||||
console.log("Login failed.");
|
||||
}
|
||||
};
|
||||
// Execute login handler
|
||||
await handleLogin();
|
||||
}
|
||||
password: 'securepassword'
|
||||
});
|
||||
|
||||
if (response.refreshToken) {
|
||||
await idpClient.refreshJwt(response.refreshToken);
|
||||
console.log('✅ Login successful!');
|
||||
}
|
||||
|
||||
// Instantiate and run demo
|
||||
const demo = new IdpDemo();
|
||||
demo.demo();
|
||||
// Get current user info
|
||||
const userInfo = await idpClient.whoIs();
|
||||
console.log('User:', userInfo.user);
|
||||
|
||||
// Get user's organizations
|
||||
const orgs = await idpClient.getRolesAndOrganizations();
|
||||
console.log('Organizations:', orgs.organizations);
|
||||
```
|
||||
|
||||
### Managing User Authentication
|
||||
|
||||
Several functionalities are available for managing user authentication. These include registering, logging in, and refreshing JWTs.
|
||||
|
||||
#### Registration Process
|
||||
|
||||
The registration process is typically more involved and requires steps such as email validation, setting user-specific data, and verifying OTPs for additional security.
|
||||
### Organization Management
|
||||
|
||||
```typescript
|
||||
import * as plugins from './plugins.js';
|
||||
import { IdpState } from './idp.state.js';
|
||||
// Create a new organization
|
||||
const result = await idpClient.createOrganization('My Company', 'my-company', 'manifest');
|
||||
console.log('Created:', result.resultingOrganization);
|
||||
|
||||
// Registration stepper element
|
||||
export class IdpRegistrationStepper extends plugins.DeesElement {
|
||||
private idpState = IdpState.getSingletonInstance();
|
||||
// Invite members
|
||||
await idpClient.requests.createInvitation.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
organizationId: 'org-id',
|
||||
email: 'newmember@example.com',
|
||||
roles: ['member']
|
||||
});
|
||||
```
|
||||
|
||||
public async firstUpdated() {
|
||||
await this.domtoolsPromise;
|
||||
this.domtools.router.on(`/finishregistration`, async (routeArg) => {
|
||||
const validationToken = routeArg.queryParams.validationtoken;
|
||||
if (!validationToken) {
|
||||
this.renderErrorMessage("Validation token not found.");
|
||||
return;
|
||||
}
|
||||
const emailResponse = await this.validateEmail(validationToken);
|
||||
if (!emailResponse.email) {
|
||||
this.renderErrorMessage("Invalid validation token.");
|
||||
return;
|
||||
}
|
||||
await this.renderRegistrationForm(emailResponse.email);
|
||||
});
|
||||
}
|
||||
### CLI Tool
|
||||
|
||||
private async validateEmail(token: string) {
|
||||
return await this.idpState.idpClient.requests.afterRegistrationEmailClicked.fire({
|
||||
token
|
||||
});
|
||||
}
|
||||
The `ts_idpcli` module provides a command-line interface:
|
||||
|
||||
private async renderRegistrationForm(email: string) {
|
||||
const template = plugins.html`
|
||||
<dees-form @formData="${async (event) => await this.handleFormSubmission(event, email)}">
|
||||
<dees-input-text key="First Name" label="First Name" required></dees-input-text>
|
||||
<dees-input-text key="Last Name" label="Last Name" required></dees-input-text>
|
||||
<dees-form-submit>Next</dees-form-submit>
|
||||
</dees-form>
|
||||
`;
|
||||
this.render(template, this.shadowRoot);
|
||||
}
|
||||
```bash
|
||||
# Login
|
||||
idp login
|
||||
|
||||
private async handleFormSubmission(event: FormDataEvent, email: string) {
|
||||
const formData = (event.target as any).getFormData();
|
||||
await this.idpState.idpClient.requests.setData.fire({
|
||||
token: this.storedData.validationTokenUrlParam,
|
||||
userData: {
|
||||
email,
|
||||
first_name: formData.FirstName,
|
||||
last_name: formData.LastName,
|
||||
},
|
||||
});
|
||||
// Proceed to the next steps as per the registration flow
|
||||
}
|
||||
# Show current user
|
||||
idp whoami
|
||||
|
||||
private renderErrorMessage(message: string) {
|
||||
const template = plugins.html`<div>Error: ${message}</div>`;
|
||||
this.render(template, this.shadowRoot);
|
||||
}
|
||||
# List organizations
|
||||
idp orgs
|
||||
|
||||
# List organization members
|
||||
idp members --org <org-id>
|
||||
|
||||
# Invite a user
|
||||
idp invite --org <org-id> --email user@example.com
|
||||
```
|
||||
|
||||
## 🔐 OIDC Integration
|
||||
|
||||
idp.global implements a full OpenID Connect provider. Third-party applications can use it for SSO:
|
||||
|
||||
### Discovery Document
|
||||
|
||||
```
|
||||
GET /.well-known/openid-configuration
|
||||
```
|
||||
|
||||
### Authorization Flow
|
||||
|
||||
```
|
||||
GET /oauth/authorize?
|
||||
client_id=your-client-id&
|
||||
redirect_uri=https://yourapp.com/callback&
|
||||
response_type=code&
|
||||
scope=openid profile email organizations&
|
||||
state=random-state&
|
||||
code_challenge=PKCE_CHALLENGE&
|
||||
code_challenge_method=S256
|
||||
```
|
||||
|
||||
### Token Exchange
|
||||
|
||||
```
|
||||
POST /oauth/token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=authorization_code&
|
||||
code=AUTHORIZATION_CODE&
|
||||
redirect_uri=https://yourapp.com/callback&
|
||||
client_id=your-client-id&
|
||||
client_secret=your-client-secret&
|
||||
code_verifier=PKCE_VERIFIER
|
||||
```
|
||||
|
||||
### UserInfo
|
||||
|
||||
```
|
||||
GET /oauth/userinfo
|
||||
Authorization: Bearer ACCESS_TOKEN
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"sub": "user-id",
|
||||
"name": "John Doe",
|
||||
"email": "john@example.com",
|
||||
"email_verified": true,
|
||||
"organizations": [
|
||||
{ "id": "org-1", "name": "Acme Corp", "slug": "acme", "roles": ["admin"] }
|
||||
],
|
||||
"roles": ["user"]
|
||||
}
|
||||
```
|
||||
|
||||
### User Management
|
||||
## 🛠️ Tech Stack
|
||||
|
||||
Managing user data including roles, organizations, and billing plans is essential in any identity provider software.
|
||||
- **Runtime**: Node.js with ES Modules
|
||||
- **Language**: TypeScript (strict mode)
|
||||
- **Database**: MongoDB via `@push.rocks/smartdata`
|
||||
- **Web Server**: `@api.global/typedserver`
|
||||
- **Real-time**: `@api.global/typedsocket` (WebSocket)
|
||||
- **JWT**: `@push.rocks/smartjwt` (RS256 signing)
|
||||
- **Frontend**: `@design.estate/dees-element` (Web Components)
|
||||
- **Build**: `@git.zone/tsbuild` + `@git.zone/tsbundle`
|
||||
|
||||
#### Getting User Data
|
||||
## 📚 API Reference
|
||||
|
||||
```typescript
|
||||
import * as plugins from './plugins.js';
|
||||
### Request Interfaces
|
||||
|
||||
const fetchUserData = async (jwt: string) => {
|
||||
const user = await plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_GetUserData>(
|
||||
`/getUserData`, 'POST').fire({jwt});
|
||||
console.log(user);
|
||||
};
|
||||
All API requests are type-safe. See `ts_interfaces/request/` for the complete API:
|
||||
|
||||
fetchUserData('<JWT_TOKEN_HERE>');
|
||||
```
|
||||
- **Authentication**: `IReq_LoginWithEmail`, `IReq_LoginWithApiToken`, `IReq_RefreshJwt`
|
||||
- **Registration**: `IReq_FirstRegistration`, `IReq_FinishRegistration`
|
||||
- **User Management**: `IReq_GetUserData`, `IReq_SetUserData`, `IReq_GetUserSessions`
|
||||
- **Organizations**: `IReq_CreateOrganization`, `IReq_GetOrgMembers`, `IReq_CreateInvitation`
|
||||
- **Apps & OAuth**: `IReq_GetGlobalApps`, `IReq_CreateGlobalApp`
|
||||
- **Billing**: `IReq_GetBillingPlan`, `IReq_UpdatePaymentMethod`
|
||||
|
||||
#### Creating an Organization
|
||||
### Data Models
|
||||
|
||||
```typescript
|
||||
import { IdpState } from './idp.state.js';
|
||||
See `ts_interfaces/data/` for all data structures:
|
||||
|
||||
export class OrganizationManager {
|
||||
private idpState = IdpState.getSingletonInstance();
|
||||
|
||||
public async createOrganization(name: string, slug: string, jwt: string) {
|
||||
const response = await this.idpState.idpClient.requests.createOrganization.fire({
|
||||
jwt: jwt,
|
||||
organizationName: name,
|
||||
organizationSlug: slug,
|
||||
action: 'manifest',
|
||||
});
|
||||
if (response.resultingOrganization) {
|
||||
console.log(`Organization ${name} created successfully.`);
|
||||
} else {
|
||||
console.log(`Organization creation failed.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
const organizationManager = new OrganizationManager();
|
||||
organizationManager.createOrganization('Dev Org', 'dev-org', '<JWT_TOKEN_HERE>');
|
||||
```
|
||||
|
||||
### Managing JWTs
|
||||
|
||||
The `@idp.global/idp.global` package involves managing JSON Web Tokens (JWTs) for session handling and security.
|
||||
|
||||
#### Refreshing JWTs
|
||||
|
||||
```typescript
|
||||
import { IdpClient } from './idp.client.js';
|
||||
|
||||
export const refreshJwt = async (client: IdpClient) => {
|
||||
const currentJwt = await client.getJwt();
|
||||
if (!currentJwt) return null;
|
||||
const response = await client.requests.refreshJwt.fire({
|
||||
refreshToken: currentJwt.data.refreshToken
|
||||
});
|
||||
if (response.jwt) {
|
||||
await client.storeJwt(response.jwt);
|
||||
console.log("JWT refreshed and stored.");
|
||||
return response.jwt;
|
||||
} else {
|
||||
console.log("JWT refresh failed.");
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Usage
|
||||
const idpClient = new IdpClient('https://reception.lossless.one/typedrequest');
|
||||
refreshJwt(idpClient);
|
||||
```
|
||||
|
||||
### Handling Authentication Tokens
|
||||
|
||||
Handling tokens (JWTs, refresh tokens, transfer tokens) securely is crucial for maintaining session integrity.
|
||||
|
||||
#### Exchanging Refresh Token for Transfer Token
|
||||
|
||||
```typescript
|
||||
import { IdpClient } from './idp.client.js';
|
||||
|
||||
const getTransferToken = async (client: IdpClient) => {
|
||||
const refreshToken = await client.getJwt().data.refreshToken;
|
||||
const response = await client.requests.obtainOneTimeToken.fire({
|
||||
refreshToken
|
||||
});
|
||||
if(response.transferToken) {
|
||||
console.log("Obtained Transfer Token: ", response.transferToken);
|
||||
return response.transferToken;
|
||||
} else {
|
||||
console.log("Failed to obtain Transfer Token.");
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Usage
|
||||
const idpClient = new IdpClient('https://reception.lossless.one/typedrequest');
|
||||
getTransferToken(idpClient);
|
||||
```
|
||||
|
||||
This comprehensive guide should help you understand the detailed setup and usage of the `@idp.global/idp.global` module effectively.
|
||||
- `IUser` - User profile and credentials
|
||||
- `IOrganization` - Organization entity
|
||||
- `IRole` - User roles within organizations
|
||||
- `IJwt` - JWT token structure
|
||||
- `IApp` - OAuth application definitions
|
||||
- `IOidcAccessToken`, `IAuthorizationCode` - OIDC tokens
|
||||
|
||||
## License and Legal Information
|
||||
|
||||
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
||||
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 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, and any usage must be approved in writing by Task Venture Capital GmbH.
|
||||
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
|
||||
Registered at District Court Bremen HRB 35230 HB, Germany
|
||||
|
||||
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||||
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.
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@idp.global/idp.global',
|
||||
version: '1.13.0',
|
||||
version: '1.14.0',
|
||||
description: 'An identity provider software managing user authentications, registrations, and sessions.'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "@idp.global/cli",
|
||||
"order": 4
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
# @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
|
||||
|
||||
MIT - See the main repository for full license details.
|
||||
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"name": "@idp.global/client",
|
||||
"order": 3
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
# @idp.global/interfaces
|
||||
|
||||
TypeScript interfaces and type definitions for the idp.global Identity Provider platform.
|
||||
|
||||
## Overview
|
||||
|
||||
This package provides the complete type system for idp.global, including data models, API request/response interfaces, and OIDC definitions. Use this package when building applications that integrate with idp.global or when you need type-safe interactions with the IdP API.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @idp.global/interfaces
|
||||
# or
|
||||
pnpm add @idp.global/interfaces
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import { data, request, tags } from '@idp.global/interfaces';
|
||||
|
||||
// Data interfaces
|
||||
const user: data.IUser = {
|
||||
id: 'user_123',
|
||||
data: {
|
||||
name: 'John Doe',
|
||||
username: 'johndoe',
|
||||
email: 'john@example.com',
|
||||
status: 'active',
|
||||
connectedOrgs: ['org_1', 'org_2'],
|
||||
},
|
||||
};
|
||||
|
||||
// Organization interface
|
||||
const org: data.IOrganization = {
|
||||
id: 'org_1',
|
||||
data: {
|
||||
name: 'Acme Corp',
|
||||
slug: 'acme',
|
||||
billingPlanId: 'plan_free',
|
||||
roleIds: ['role_admin', 'role_member'],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Package Structure
|
||||
|
||||
```
|
||||
ts_interfaces/
|
||||
├── data/ # Data model interfaces
|
||||
│ ├── loint-reception.user.ts # User profiles
|
||||
│ ├── loint-reception.organization.ts # Organizations
|
||||
│ ├── loint-reception.role.ts # RBAC roles
|
||||
│ ├── loint-reception.app.ts # OAuth applications
|
||||
│ ├── loint-reception.oidc.ts # OIDC tokens & flows
|
||||
│ ├── loint-reception.jwt.ts # JWT structures
|
||||
│ ├── loint-reception.loginsession.ts # Login sessions
|
||||
│ ├── loint-reception.billingplan.ts # Billing plans
|
||||
│ ├── loint-reception.device.ts # Device management
|
||||
│ ├── loint-reception.activity.ts # Activity logs
|
||||
│ ├── loint-reception.userinvitation.ts # Invitations
|
||||
│ └── loint-reception.appconnection.ts # App connections
|
||||
├── request/ # API request/response interfaces
|
||||
│ ├── loint-reception.login.ts # Authentication
|
||||
│ ├── loint-reception.registration.ts # User registration
|
||||
│ ├── loint-reception.user.ts # User management
|
||||
│ ├── loint-reception.organization.ts # Org management
|
||||
│ ├── loint-reception.jwt.ts # JWT operations
|
||||
│ ├── loint-reception.apitoken.ts # API tokens
|
||||
│ ├── loint-reception.app.ts # App management
|
||||
│ ├── loint-reception.billingplan.ts # Billing
|
||||
│ └── loint-reception.admin.ts # Admin operations
|
||||
└── tags/ # Tag definitions
|
||||
```
|
||||
|
||||
## Data Interfaces
|
||||
|
||||
### User (`IUser`)
|
||||
|
||||
```typescript
|
||||
interface IUser {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
username: string;
|
||||
email: string;
|
||||
mobileNumber?: string;
|
||||
password?: string; // Only during initial setting
|
||||
passwordHash?: string; // For validation
|
||||
status: 'new' | 'active' | 'deleted' | 'suspended';
|
||||
connectedOrgs: string[]; // Organization IDs
|
||||
isGlobalAdmin?: boolean; // Platform admin flag
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Organization (`IOrganization`)
|
||||
|
||||
```typescript
|
||||
interface IOrganization {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
slug: string;
|
||||
billingPlanId: string;
|
||||
roleIds: string[];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Role (`IRole`)
|
||||
|
||||
```typescript
|
||||
interface IRole {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
organizationId: string;
|
||||
userId: string;
|
||||
permissions: string[];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### OAuth Application Types
|
||||
|
||||
```typescript
|
||||
// Global platform apps (maintained by platform admins)
|
||||
interface IGlobalApp {
|
||||
id: string;
|
||||
type: 'globalApp';
|
||||
data: {
|
||||
name: string;
|
||||
description: string;
|
||||
iconBase64?: string;
|
||||
oauthCredentials?: IOAuthCredentials;
|
||||
};
|
||||
}
|
||||
|
||||
// Partner apps (third-party integrations)
|
||||
interface IPartnerApp {
|
||||
id: string;
|
||||
type: 'partnerApp';
|
||||
data: {
|
||||
name: string;
|
||||
description: string;
|
||||
ownerOrganizationId: string;
|
||||
oauthCredentials?: IOAuthCredentials;
|
||||
};
|
||||
}
|
||||
|
||||
// Custom OIDC clients
|
||||
interface ICustomOidcApp {
|
||||
id: string;
|
||||
type: 'customOidcApp';
|
||||
data: {
|
||||
name: string;
|
||||
description: string;
|
||||
ownerOrganizationId: string;
|
||||
oauthCredentials: IOAuthCredentials;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### OAuth Credentials
|
||||
|
||||
```typescript
|
||||
interface IOAuthCredentials {
|
||||
clientId: string;
|
||||
clientSecretHash: string;
|
||||
redirectUris: string[];
|
||||
scopes: string[];
|
||||
grantTypes: ('authorization_code' | 'refresh_token' | 'client_credentials')[];
|
||||
}
|
||||
```
|
||||
|
||||
## OIDC Interfaces
|
||||
|
||||
### Authorization Code
|
||||
|
||||
```typescript
|
||||
interface IAuthorizationCode {
|
||||
code: string;
|
||||
clientId: string;
|
||||
userId: string;
|
||||
scopes: string[];
|
||||
redirectUri: string;
|
||||
codeChallenge?: string;
|
||||
codeChallengeMethod?: 'S256';
|
||||
expiresAt: number;
|
||||
used: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### Token Response
|
||||
|
||||
```typescript
|
||||
interface ITokenResponse {
|
||||
access_token: string;
|
||||
token_type: 'Bearer';
|
||||
expires_in: number;
|
||||
refresh_token?: string;
|
||||
id_token?: string;
|
||||
scope: string;
|
||||
}
|
||||
```
|
||||
|
||||
### UserInfo Response
|
||||
|
||||
```typescript
|
||||
interface IUserInfoResponse {
|
||||
sub: string;
|
||||
name?: string;
|
||||
preferred_username?: string;
|
||||
email?: string;
|
||||
email_verified?: boolean;
|
||||
organizations?: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
roles: string[];
|
||||
}>;
|
||||
roles?: string[];
|
||||
}
|
||||
```
|
||||
|
||||
### ID Token Claims
|
||||
|
||||
```typescript
|
||||
interface IIdTokenClaims {
|
||||
iss: string; // Issuer
|
||||
sub: string; // Subject (user ID)
|
||||
aud: string; // Audience (client ID)
|
||||
exp: number; // Expiration time
|
||||
iat: number; // Issued at
|
||||
nonce?: string; // Replay protection
|
||||
name?: string;
|
||||
email?: string;
|
||||
email_verified?: boolean;
|
||||
organizations?: Array<{...}>;
|
||||
roles?: string[];
|
||||
}
|
||||
```
|
||||
|
||||
## Request Interfaces
|
||||
|
||||
All API requests follow the TypedRequest pattern:
|
||||
|
||||
```typescript
|
||||
interface IReq_LoginWithEmailOrUsernameAndPassword {
|
||||
method: 'loginWithEmailOrUsernameAndPassword';
|
||||
request: {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
response: {
|
||||
refreshToken?: string;
|
||||
twoFaNeeded: boolean;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Authentication Requests
|
||||
|
||||
| Interface | Method | Description |
|
||||
|-----------|--------|-------------|
|
||||
| `IReq_LoginWithEmailOrUsernameAndPassword` | `loginWithEmailOrUsernameAndPassword` | Password login |
|
||||
| `IReq_LoginWithEmail` | `loginWithEmail` | Magic link request |
|
||||
| `IReq_LoginWithEmailAfterEmailTokenAquired` | `loginWithEmailAfterEmailTokenAquired` | Magic link verification |
|
||||
| `IReq_LoginWithApiToken` | `loginWithApiToken` | API token login |
|
||||
| `IReq_RefreshJwt` | `refreshJwt` | Refresh access token |
|
||||
| `ILogoutRequest` | `logout` | End session |
|
||||
|
||||
### User Management Requests
|
||||
|
||||
| Interface | Method | Description |
|
||||
|-----------|--------|-------------|
|
||||
| `IReq_GetUserData` | `getUserData` | Get current user |
|
||||
| `IReq_SetUserData` | `setUserData` | Update user profile |
|
||||
| `IReq_GetUserSessions` | `getUserSessions` | List active sessions |
|
||||
| `IReq_ResetPassword` | `resetPassword` | Request password reset |
|
||||
| `IReq_SetNewPassword` | `setNewPassword` | Set new password |
|
||||
|
||||
### Organization Requests
|
||||
|
||||
| Interface | Method | Description |
|
||||
|-----------|--------|-------------|
|
||||
| `IReq_CreateOrganization` | `createOrganization` | Create new org |
|
||||
| `IReq_GetOrgMembers` | `getOrgMembers` | List org members |
|
||||
| `IReq_CreateInvitation` | `createInvitation` | Invite user |
|
||||
| `IReq_AcceptInvitation` | `acceptInvitation` | Accept invite |
|
||||
|
||||
### JWT Operations
|
||||
|
||||
| Interface | Method | Description |
|
||||
|-----------|--------|-------------|
|
||||
| `IReq_GetPublicKeyForValidation` | `getPublicKeyForValidation` | Get JWT public key |
|
||||
| `IReq_GetJwtIdBlocklist` | `getJwtIdBlocklist` | Get revoked token IDs |
|
||||
|
||||
## Supported OIDC Scopes
|
||||
|
||||
| Scope | Description |
|
||||
|-------|-------------|
|
||||
| `openid` | Required for OIDC flows |
|
||||
| `profile` | User's name and username |
|
||||
| `email` | User's email address |
|
||||
| `organizations` | User's organization memberships |
|
||||
| `roles` | User's roles within organizations |
|
||||
|
||||
## License
|
||||
|
||||
MIT - See the main repository for full license details.
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@idp.global/idp.global',
|
||||
version: '1.13.0',
|
||||
version: '1.14.0',
|
||||
description: 'An identity provider software managing user authentications, registrations, and sessions.'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
# @idp.global/web
|
||||
|
||||
Web Components and UI elements for the idp.global Identity Provider platform. Built with `@design.estate/dees-element` and the dees-catalog component library.
|
||||
|
||||
## Overview
|
||||
|
||||
This package provides the complete web interface for idp.global, including authentication flows, account management, and organization administration. All components are built as Web Components using the Lit-based `dees-element` framework.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @idp.global/web
|
||||
# or
|
||||
pnpm add @idp.global/web
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
ts_web/
|
||||
├── index.ts # Application entry point
|
||||
├── plugins.ts # Plugin imports
|
||||
├── views/
|
||||
│ ├── viewcontainer.ts # Main view router
|
||||
│ └── index.ts
|
||||
├── elements/ # Web Components
|
||||
│ ├── idp-loginprompt.ts # Login form
|
||||
│ ├── idp-registerprompt.ts # Registration form
|
||||
│ ├── idp-registration-stepper.ts # Multi-step registration
|
||||
│ ├── idp-centercontainer.ts # Centered layout container
|
||||
│ ├── idp-transfermanager.ts # SSO transfer handling
|
||||
│ ├── idp-welcome.ts # Welcome/landing page
|
||||
│ └── account/ # Account dashboard components
|
||||
│ ├── content.ts # Main account layout
|
||||
│ ├── navigation.ts # Sidebar navigation
|
||||
│ ├── org-select-modal.ts # Organization switcher
|
||||
│ ├── create-org-modal.ts # Create organization dialog
|
||||
│ ├── bulk-invite-modal.ts # Bulk member invite dialog
|
||||
│ └── views/ # Account sub-views
|
||||
│ ├── baseview.ts # Base view class
|
||||
│ ├── usersview.ts # User profile view
|
||||
│ ├── orgview.ts # Organization details
|
||||
│ ├── orgsetup.ts # Organization setup
|
||||
│ ├── appsview.ts # Connected apps
|
||||
│ ├── adminview.ts # Global admin panel
|
||||
│ ├── subscriptions.ts # Billing subscriptions
|
||||
│ └── paddlesetup.ts # Payment setup
|
||||
└── states/
|
||||
├── idp.state.ts # Main application state
|
||||
└── accountstate.ts # Account dashboard state
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### Authentication Components
|
||||
|
||||
#### `<idp-loginprompt>`
|
||||
|
||||
Login form supporting password and magic link authentication.
|
||||
|
||||
```html
|
||||
<idp-loginprompt></idp-loginprompt>
|
||||
```
|
||||
|
||||
Features:
|
||||
- Email/username + password login
|
||||
- Magic link (passwordless) authentication
|
||||
- Automatic button text based on password presence
|
||||
- Form validation and error handling
|
||||
- Redirect to registration
|
||||
|
||||
#### `<idp-registerprompt>`
|
||||
|
||||
Initial registration form for new users.
|
||||
|
||||
```html
|
||||
<idp-registerprompt></idp-registerprompt>
|
||||
```
|
||||
|
||||
#### `<idp-registration-stepper>`
|
||||
|
||||
Multi-step registration wizard for completing user profile.
|
||||
|
||||
```html
|
||||
<idp-registration-stepper></idp-registration-stepper>
|
||||
```
|
||||
|
||||
Steps include:
|
||||
- Profile information
|
||||
- Email verification
|
||||
- Mobile verification (optional)
|
||||
- Password setup
|
||||
|
||||
### Layout Components
|
||||
|
||||
#### `<idp-viewcontainer>`
|
||||
|
||||
Main view container that handles routing between views.
|
||||
|
||||
```html
|
||||
<idp-viewcontainer></idp-viewcontainer>
|
||||
```
|
||||
|
||||
Supported views:
|
||||
- `welcome` - Landing page
|
||||
- `login` - Login form
|
||||
- `register` - Registration form
|
||||
- `finishregistration` - Registration stepper
|
||||
- `account` - Account dashboard
|
||||
|
||||
#### `<idp-centercontainer>`
|
||||
|
||||
Centered container with animation support for forms.
|
||||
|
||||
```html
|
||||
<idp-centercontainer>
|
||||
<h2>Your Content</h2>
|
||||
<form>...</form>
|
||||
</idp-centercontainer>
|
||||
```
|
||||
|
||||
Methods:
|
||||
- `show()` - Animate container into view
|
||||
- `hide()` - Animate container out of view
|
||||
|
||||
### Account Dashboard Components
|
||||
|
||||
#### `<idp-account-content>`
|
||||
|
||||
Main account dashboard layout with navigation.
|
||||
|
||||
```html
|
||||
<idp-account-content></idp-account-content>
|
||||
```
|
||||
|
||||
#### Navigation Views
|
||||
|
||||
| Component | Route | Description |
|
||||
|-----------|-------|-------------|
|
||||
| `<idp-usersview>` | `/account/users` | User profile management |
|
||||
| `<idp-orgview>` | `/account/org` | Organization details |
|
||||
| `<idp-orgsetup>` | `/account/orgsetup` | Organization configuration |
|
||||
| `<idp-appsview>` | `/account/apps` | Connected applications |
|
||||
| `<idp-adminview>` | `/account/admin` | Global admin panel |
|
||||
| `<idp-subscriptions>` | `/account/subscriptions` | Billing management |
|
||||
| `<idp-paddlesetup>` | `/account/paddle` | Payment method setup |
|
||||
|
||||
### Modal Components
|
||||
|
||||
#### `<idp-org-select-modal>`
|
||||
|
||||
Organization switcher modal for users with multiple organizations.
|
||||
|
||||
#### `<idp-create-org-modal>`
|
||||
|
||||
Dialog for creating new organizations with slug validation.
|
||||
|
||||
#### `<idp-bulk-invite-modal>`
|
||||
|
||||
Bulk invitation dialog for inviting multiple members at once.
|
||||
|
||||
## State Management
|
||||
|
||||
### IdpState
|
||||
|
||||
Central application state using `@push.rocks/smartstate`.
|
||||
|
||||
```typescript
|
||||
import { IdpState } from '@idp.global/web';
|
||||
|
||||
const idpState = await IdpState.getSingletonInstance();
|
||||
|
||||
// Access IdP client
|
||||
const isLoggedIn = await idpState.idpClient.determineLoginStatus();
|
||||
|
||||
// Access router
|
||||
idpState.domtools.router.pushUrl('/login');
|
||||
|
||||
// Subscribe to view changes
|
||||
idpState.mainStatePart.select(s => s.view).subscribe(view => {
|
||||
console.log('Current view:', view);
|
||||
});
|
||||
```
|
||||
|
||||
### AccountState
|
||||
|
||||
State for the account dashboard section.
|
||||
|
||||
```typescript
|
||||
import { AccountState } from '@idp.global/web';
|
||||
|
||||
const accountState = await AccountState.getSingletonInstance();
|
||||
|
||||
// Access current organization
|
||||
const currentOrg = accountState.currentOrganization;
|
||||
|
||||
// Access user roles
|
||||
const roles = accountState.userRoles;
|
||||
```
|
||||
|
||||
## Styling
|
||||
|
||||
Components use CSS custom properties for theming:
|
||||
|
||||
```css
|
||||
:host {
|
||||
--foreground: hsl(0 0% 98%);
|
||||
--muted-foreground: hsl(240 5% 64.9%);
|
||||
--background-accent: #303f9f;
|
||||
}
|
||||
```
|
||||
|
||||
All components include:
|
||||
- Dark mode by default
|
||||
- Geist Sans font family
|
||||
- Smooth animations
|
||||
- Responsive layouts
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `@design.estate/dees-element` - Web Component base class
|
||||
- `@design.estate/dees-catalog` - UI component library
|
||||
- `@design.estate/dees-domtools` - DOM utilities and routing
|
||||
- `@idp.global/idpclient` - IdP client library
|
||||
- `@idp.global/interfaces` - TypeScript interfaces
|
||||
- `@push.rocks/smartstate` - State management
|
||||
- `@uptime.link/webwidget` - Status widget
|
||||
|
||||
## Views and Routes
|
||||
|
||||
| Route | View | Component |
|
||||
|-------|------|-----------|
|
||||
| `/` | `welcome` | `IdpWelcome` |
|
||||
| `/login` | `login` | `IdpLoginPrompt` |
|
||||
| `/register` | `register` | `IdpRegistrationPrompt` |
|
||||
| `/finishregistration` | `finishregistration` | `IdpRegistrationStepper` |
|
||||
| `/account` | `account` | `IdpAccountContent` |
|
||||
| `/logout` | - | Logout handler |
|
||||
|
||||
## Building
|
||||
|
||||
The web module is bundled using `@git.zone/tsbundle`:
|
||||
|
||||
```bash
|
||||
# Development with hot reload
|
||||
pnpm watch
|
||||
|
||||
# Production build
|
||||
pnpm build
|
||||
```
|
||||
|
||||
The bundled output is served from `dist_ts_web/` by the TypedServer.
|
||||
|
||||
## License
|
||||
|
||||
MIT - See the main repository for full license details.
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"order": 4
|
||||
"order": 5
|
||||
}
|
||||
Reference in New Issue
Block a user