@famgia/omnify-client-sso-react 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +264 -0
- package/dist/index.d.mts +366 -0
- package/dist/index.d.ts +366 -0
- package/dist/index.js +655 -0
- package/dist/index.mjs +611 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# @omnify/sso-react
|
|
2
|
+
|
|
3
|
+
React components and hooks for Omnify SSO integration.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @omnify/sso-react
|
|
9
|
+
# or
|
|
10
|
+
yarn add @omnify/sso-react
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @omnify/sso-react
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### 1. Wrap your app with SsoProvider
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
// app/layout.tsx or _app.tsx
|
|
21
|
+
import { SsoProvider } from '@omnify/sso-react';
|
|
22
|
+
|
|
23
|
+
const ssoConfig = {
|
|
24
|
+
apiUrl: process.env.NEXT_PUBLIC_API_URL!,
|
|
25
|
+
consoleUrl: process.env.NEXT_PUBLIC_SSO_CONSOLE_URL!,
|
|
26
|
+
serviceSlug: process.env.NEXT_PUBLIC_SSO_SERVICE_SLUG!,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default function RootLayout({ children }) {
|
|
30
|
+
return (
|
|
31
|
+
<SsoProvider config={ssoConfig}>
|
|
32
|
+
{children}
|
|
33
|
+
</SsoProvider>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2. Create callback page
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
// app/sso/callback/page.tsx
|
|
42
|
+
import { SsoCallback } from '@omnify/sso-react';
|
|
43
|
+
|
|
44
|
+
export default function CallbackPage() {
|
|
45
|
+
return (
|
|
46
|
+
<SsoCallback
|
|
47
|
+
redirectTo="/dashboard"
|
|
48
|
+
onSuccess={(user) => console.log('Logged in:', user)}
|
|
49
|
+
onError={(error) => console.error('Login failed:', error)}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3. Use hooks in your components
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { useAuth, useOrganization, useSso } from '@omnify/sso-react';
|
|
59
|
+
|
|
60
|
+
function Header() {
|
|
61
|
+
const { user, isAuthenticated, login, logout } = useAuth();
|
|
62
|
+
const { currentOrg } = useOrganization();
|
|
63
|
+
|
|
64
|
+
if (!isAuthenticated) {
|
|
65
|
+
return <button onClick={() => login()}>Login</button>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<div>
|
|
70
|
+
<span>Welcome, {user?.name}</span>
|
|
71
|
+
<span>Org: {currentOrg?.name}</span>
|
|
72
|
+
<button onClick={() => logout()}>Logout</button>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Components
|
|
79
|
+
|
|
80
|
+
### SsoProvider
|
|
81
|
+
|
|
82
|
+
Wraps your app and provides SSO context.
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
<SsoProvider
|
|
86
|
+
config={{
|
|
87
|
+
apiUrl: 'https://api.yourservice.com',
|
|
88
|
+
consoleUrl: 'https://auth.console.com',
|
|
89
|
+
serviceSlug: 'your-service',
|
|
90
|
+
storage: 'localStorage', // or 'sessionStorage'
|
|
91
|
+
storageKey: 'sso_selected_org',
|
|
92
|
+
}}
|
|
93
|
+
onAuthChange={(isAuthenticated, user) => {
|
|
94
|
+
console.log('Auth changed:', isAuthenticated, user);
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
{children}
|
|
98
|
+
</SsoProvider>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### SsoCallback
|
|
102
|
+
|
|
103
|
+
Handles the SSO callback and token exchange.
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
<SsoCallback
|
|
107
|
+
redirectTo="/dashboard"
|
|
108
|
+
onSuccess={(user, organizations) => {}}
|
|
109
|
+
onError={(error) => {}}
|
|
110
|
+
loadingComponent={<CustomLoader />}
|
|
111
|
+
errorComponent={(error) => <CustomError error={error} />}
|
|
112
|
+
/>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### OrganizationSwitcher
|
|
116
|
+
|
|
117
|
+
Dropdown for switching between organizations. Only renders if user has multiple orgs.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
// Basic
|
|
121
|
+
<OrganizationSwitcher />
|
|
122
|
+
|
|
123
|
+
// Custom rendering
|
|
124
|
+
<OrganizationSwitcher
|
|
125
|
+
renderTrigger={(currentOrg, isOpen) => (
|
|
126
|
+
<button>{currentOrg?.name} {isOpen ? '▲' : '▼'}</button>
|
|
127
|
+
)}
|
|
128
|
+
renderOption={(org, isSelected) => (
|
|
129
|
+
<div className={isSelected ? 'selected' : ''}>{org.name}</div>
|
|
130
|
+
)}
|
|
131
|
+
onChange={(org) => console.log('Switched to:', org.name)}
|
|
132
|
+
/>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### ProtectedRoute
|
|
136
|
+
|
|
137
|
+
Wraps content that requires authentication.
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
// Basic
|
|
141
|
+
<ProtectedRoute>
|
|
142
|
+
<Dashboard />
|
|
143
|
+
</ProtectedRoute>
|
|
144
|
+
|
|
145
|
+
// With role requirement
|
|
146
|
+
<ProtectedRoute requiredRole="admin">
|
|
147
|
+
<AdminPanel />
|
|
148
|
+
</ProtectedRoute>
|
|
149
|
+
|
|
150
|
+
// Custom fallbacks
|
|
151
|
+
<ProtectedRoute
|
|
152
|
+
fallback={<Spinner />}
|
|
153
|
+
loginFallback={<CustomLoginPage />}
|
|
154
|
+
onAccessDenied={(reason) => console.log(reason)}
|
|
155
|
+
>
|
|
156
|
+
<ProtectedContent />
|
|
157
|
+
</ProtectedRoute>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Hooks
|
|
161
|
+
|
|
162
|
+
### useAuth
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
const {
|
|
166
|
+
user, // SsoUser | null
|
|
167
|
+
isLoading, // boolean
|
|
168
|
+
isAuthenticated,// boolean
|
|
169
|
+
login, // (redirectTo?: string) => void
|
|
170
|
+
logout, // () => Promise<void>
|
|
171
|
+
globalLogout, // (redirectTo?: string) => void
|
|
172
|
+
refreshUser, // () => Promise<void>
|
|
173
|
+
} = useAuth();
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### useOrganization
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
const {
|
|
180
|
+
organizations, // SsoOrganization[]
|
|
181
|
+
currentOrg, // SsoOrganization | null
|
|
182
|
+
hasMultipleOrgs, // boolean
|
|
183
|
+
switchOrg, // (orgSlug: string) => void
|
|
184
|
+
currentRole, // string | null
|
|
185
|
+
hasRole, // (role: string) => boolean
|
|
186
|
+
} = useOrganization();
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### useSso
|
|
190
|
+
|
|
191
|
+
Combined hook with all functionality.
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
const {
|
|
195
|
+
// Auth
|
|
196
|
+
user, isLoading, isAuthenticated, login, logout, globalLogout, refreshUser,
|
|
197
|
+
// Organization
|
|
198
|
+
organizations, currentOrg, hasMultipleOrgs, switchOrg,
|
|
199
|
+
// Utilities
|
|
200
|
+
getHeaders, config,
|
|
201
|
+
} = useSso();
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Making API Requests
|
|
205
|
+
|
|
206
|
+
Use `getHeaders()` to include the organization header in your requests:
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
const { getHeaders } = useSso();
|
|
210
|
+
|
|
211
|
+
// With fetch
|
|
212
|
+
const response = await fetch('/api/data', {
|
|
213
|
+
headers: {
|
|
214
|
+
...getHeaders(),
|
|
215
|
+
'Content-Type': 'application/json',
|
|
216
|
+
},
|
|
217
|
+
credentials: 'include',
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// With axios
|
|
221
|
+
const response = await axios.get('/api/data', {
|
|
222
|
+
headers: getHeaders(),
|
|
223
|
+
withCredentials: true,
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Types
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
interface SsoUser {
|
|
231
|
+
id: number;
|
|
232
|
+
consoleUserId: number;
|
|
233
|
+
email: string;
|
|
234
|
+
name: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
interface SsoOrganization {
|
|
238
|
+
id: number;
|
|
239
|
+
slug: string;
|
|
240
|
+
name: string;
|
|
241
|
+
orgRole: string;
|
|
242
|
+
serviceRole: string | null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
interface SsoConfig {
|
|
246
|
+
apiUrl: string;
|
|
247
|
+
consoleUrl: string;
|
|
248
|
+
serviceSlug: string;
|
|
249
|
+
storage?: 'localStorage' | 'sessionStorage';
|
|
250
|
+
storageKey?: string;
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Environment Variables
|
|
255
|
+
|
|
256
|
+
```env
|
|
257
|
+
NEXT_PUBLIC_API_URL=https://api.yourservice.com
|
|
258
|
+
NEXT_PUBLIC_SSO_CONSOLE_URL=https://auth.console.com
|
|
259
|
+
NEXT_PUBLIC_SSO_SERVICE_SLUG=your-service
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## License
|
|
263
|
+
|
|
264
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* User information from SSO
|
|
6
|
+
*/
|
|
7
|
+
interface SsoUser {
|
|
8
|
+
id: number;
|
|
9
|
+
consoleUserId: number;
|
|
10
|
+
email: string;
|
|
11
|
+
name: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Organization with user's access information
|
|
15
|
+
*/
|
|
16
|
+
interface SsoOrganization {
|
|
17
|
+
id: number;
|
|
18
|
+
slug: string;
|
|
19
|
+
name: string;
|
|
20
|
+
orgRole: string;
|
|
21
|
+
serviceRole: string | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* SSO Provider configuration
|
|
25
|
+
*/
|
|
26
|
+
interface SsoConfig {
|
|
27
|
+
/** Service backend API URL */
|
|
28
|
+
apiUrl: string;
|
|
29
|
+
/** Console URL for SSO redirects */
|
|
30
|
+
consoleUrl: string;
|
|
31
|
+
/** Service slug registered in Console */
|
|
32
|
+
serviceSlug: string;
|
|
33
|
+
/** Storage type for selected org */
|
|
34
|
+
storage?: 'localStorage' | 'sessionStorage';
|
|
35
|
+
/** Key name for storing selected org */
|
|
36
|
+
storageKey?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* SSO Context value
|
|
40
|
+
*/
|
|
41
|
+
interface SsoContextValue {
|
|
42
|
+
/** Current authenticated user */
|
|
43
|
+
user: SsoUser | null;
|
|
44
|
+
/** List of organizations user has access to */
|
|
45
|
+
organizations: SsoOrganization[];
|
|
46
|
+
/** Currently selected organization */
|
|
47
|
+
currentOrg: SsoOrganization | null;
|
|
48
|
+
/** Loading state */
|
|
49
|
+
isLoading: boolean;
|
|
50
|
+
/** Authentication state */
|
|
51
|
+
isAuthenticated: boolean;
|
|
52
|
+
/** Configuration */
|
|
53
|
+
config: SsoConfig;
|
|
54
|
+
/** Redirect to Console login */
|
|
55
|
+
login: (redirectTo?: string) => void;
|
|
56
|
+
/** Logout from service */
|
|
57
|
+
logout: () => Promise<void>;
|
|
58
|
+
/** Global logout (logout from Console too) */
|
|
59
|
+
globalLogout: (redirectTo?: string) => void;
|
|
60
|
+
/** Switch to different organization */
|
|
61
|
+
switchOrg: (orgSlug: string) => void;
|
|
62
|
+
/** Refresh user data */
|
|
63
|
+
refreshUser: () => Promise<void>;
|
|
64
|
+
/** Get headers for API requests */
|
|
65
|
+
getHeaders: () => Record<string, string>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* SSO Callback response from backend
|
|
69
|
+
*/
|
|
70
|
+
interface SsoCallbackResponse {
|
|
71
|
+
user: {
|
|
72
|
+
id: number;
|
|
73
|
+
console_user_id: number;
|
|
74
|
+
email: string;
|
|
75
|
+
name: string;
|
|
76
|
+
};
|
|
77
|
+
organizations: Array<{
|
|
78
|
+
organization_id: number;
|
|
79
|
+
organization_slug: string;
|
|
80
|
+
organization_name: string;
|
|
81
|
+
org_role: string;
|
|
82
|
+
service_role: string | null;
|
|
83
|
+
}>;
|
|
84
|
+
token?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Props for SsoProvider
|
|
88
|
+
*/
|
|
89
|
+
interface SsoProviderProps {
|
|
90
|
+
children: React.ReactNode;
|
|
91
|
+
config: SsoConfig;
|
|
92
|
+
/** Called when auth state changes */
|
|
93
|
+
onAuthChange?: (isAuthenticated: boolean, user: SsoUser | null) => void;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Props for SsoCallback component
|
|
97
|
+
*/
|
|
98
|
+
interface SsoCallbackProps {
|
|
99
|
+
/** Called on successful login */
|
|
100
|
+
onSuccess?: (user: SsoUser, organizations: SsoOrganization[]) => void;
|
|
101
|
+
/** Called on error */
|
|
102
|
+
onError?: (error: Error) => void;
|
|
103
|
+
/** Redirect path after login */
|
|
104
|
+
redirectTo?: string;
|
|
105
|
+
/** Loading component */
|
|
106
|
+
loadingComponent?: React.ReactNode;
|
|
107
|
+
/** Error component */
|
|
108
|
+
errorComponent?: (error: Error) => React.ReactNode;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Props for OrganizationSwitcher component
|
|
112
|
+
*/
|
|
113
|
+
interface OrganizationSwitcherProps {
|
|
114
|
+
className?: string;
|
|
115
|
+
/** Custom trigger render */
|
|
116
|
+
renderTrigger?: (currentOrg: SsoOrganization | null, isOpen: boolean) => React.ReactNode;
|
|
117
|
+
/** Custom option render */
|
|
118
|
+
renderOption?: (org: SsoOrganization, isSelected: boolean) => React.ReactNode;
|
|
119
|
+
/** Called when org changes */
|
|
120
|
+
onChange?: (org: SsoOrganization) => void;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Props for ProtectedRoute component
|
|
124
|
+
*/
|
|
125
|
+
interface ProtectedRouteProps {
|
|
126
|
+
children: React.ReactNode;
|
|
127
|
+
/** Component to show when loading */
|
|
128
|
+
fallback?: React.ReactNode;
|
|
129
|
+
/** Component to show when not authenticated */
|
|
130
|
+
loginFallback?: React.ReactNode;
|
|
131
|
+
/** Required role to access */
|
|
132
|
+
requiredRole?: string;
|
|
133
|
+
/** Required permission to access */
|
|
134
|
+
requiredPermission?: string;
|
|
135
|
+
/** Called when access is denied */
|
|
136
|
+
onAccessDenied?: (reason: 'unauthenticated' | 'insufficient_role' | 'missing_permission') => void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* SSO Context
|
|
141
|
+
*/
|
|
142
|
+
declare const SsoContext: react.Context<SsoContextValue | null>;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* SSO Provider component
|
|
146
|
+
*/
|
|
147
|
+
declare function SsoProvider({ children, config, onAuthChange }: SsoProviderProps): react_jsx_runtime.JSX.Element;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Hook for authentication actions and state
|
|
151
|
+
*/
|
|
152
|
+
interface UseAuthReturn {
|
|
153
|
+
/** Current user or null */
|
|
154
|
+
user: SsoUser | null;
|
|
155
|
+
/** Whether auth is being loaded */
|
|
156
|
+
isLoading: boolean;
|
|
157
|
+
/** Whether user is authenticated */
|
|
158
|
+
isAuthenticated: boolean;
|
|
159
|
+
/** Redirect to login */
|
|
160
|
+
login: (redirectTo?: string) => void;
|
|
161
|
+
/** Logout from service only */
|
|
162
|
+
logout: () => Promise<void>;
|
|
163
|
+
/** Logout from service and Console */
|
|
164
|
+
globalLogout: (redirectTo?: string) => void;
|
|
165
|
+
/** Refresh user data */
|
|
166
|
+
refreshUser: () => Promise<void>;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Hook for authentication
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```tsx
|
|
173
|
+
* function LoginButton() {
|
|
174
|
+
* const { isAuthenticated, login, logout, user } = useAuth();
|
|
175
|
+
*
|
|
176
|
+
* if (isAuthenticated) {
|
|
177
|
+
* return (
|
|
178
|
+
* <div>
|
|
179
|
+
* <span>Hello, {user?.name}</span>
|
|
180
|
+
* <button onClick={() => logout()}>Logout</button>
|
|
181
|
+
* </div>
|
|
182
|
+
* );
|
|
183
|
+
* }
|
|
184
|
+
*
|
|
185
|
+
* return <button onClick={() => login()}>Login</button>;
|
|
186
|
+
* }
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
declare function useAuth(): UseAuthReturn;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Hook return type for organization management
|
|
193
|
+
*/
|
|
194
|
+
interface UseOrganizationReturn {
|
|
195
|
+
/** List of organizations user has access to */
|
|
196
|
+
organizations: SsoOrganization[];
|
|
197
|
+
/** Currently selected organization */
|
|
198
|
+
currentOrg: SsoOrganization | null;
|
|
199
|
+
/** Whether user has multiple organizations */
|
|
200
|
+
hasMultipleOrgs: boolean;
|
|
201
|
+
/** Switch to a different organization */
|
|
202
|
+
switchOrg: (orgSlug: string) => void;
|
|
203
|
+
/** Get current org's role */
|
|
204
|
+
currentRole: string | null;
|
|
205
|
+
/** Check if user has at least the given role in current org */
|
|
206
|
+
hasRole: (role: string) => boolean;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Hook for organization management
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```tsx
|
|
213
|
+
* function OrgInfo() {
|
|
214
|
+
* const { currentOrg, organizations, switchOrg, hasRole } = useOrganization();
|
|
215
|
+
*
|
|
216
|
+
* return (
|
|
217
|
+
* <div>
|
|
218
|
+
* <p>Current: {currentOrg?.name}</p>
|
|
219
|
+
* {hasRole('admin') && <AdminPanel />}
|
|
220
|
+
* <select onChange={(e) => switchOrg(e.target.value)}>
|
|
221
|
+
* {organizations.map((org) => (
|
|
222
|
+
* <option key={org.slug} value={org.slug}>{org.name}</option>
|
|
223
|
+
* ))}
|
|
224
|
+
* </select>
|
|
225
|
+
* </div>
|
|
226
|
+
* );
|
|
227
|
+
* }
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
declare function useOrganization(): UseOrganizationReturn;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Combined SSO hook return type
|
|
234
|
+
*/
|
|
235
|
+
interface UseSsoReturn {
|
|
236
|
+
user: SsoUser | null;
|
|
237
|
+
isLoading: boolean;
|
|
238
|
+
isAuthenticated: boolean;
|
|
239
|
+
login: (redirectTo?: string) => void;
|
|
240
|
+
logout: () => Promise<void>;
|
|
241
|
+
globalLogout: (redirectTo?: string) => void;
|
|
242
|
+
refreshUser: () => Promise<void>;
|
|
243
|
+
organizations: SsoOrganization[];
|
|
244
|
+
currentOrg: SsoOrganization | null;
|
|
245
|
+
hasMultipleOrgs: boolean;
|
|
246
|
+
switchOrg: (orgSlug: string) => void;
|
|
247
|
+
getHeaders: () => Record<string, string>;
|
|
248
|
+
config: SsoConfig;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Combined hook for all SSO functionality
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```tsx
|
|
255
|
+
* function MyComponent() {
|
|
256
|
+
* const {
|
|
257
|
+
* user,
|
|
258
|
+
* isAuthenticated,
|
|
259
|
+
* currentOrg,
|
|
260
|
+
* getHeaders,
|
|
261
|
+
* login,
|
|
262
|
+
* logout,
|
|
263
|
+
* } = useSso();
|
|
264
|
+
*
|
|
265
|
+
* const fetchData = async () => {
|
|
266
|
+
* const response = await fetch('/api/data', {
|
|
267
|
+
* headers: getHeaders(),
|
|
268
|
+
* });
|
|
269
|
+
* // ...
|
|
270
|
+
* };
|
|
271
|
+
*
|
|
272
|
+
* if (!isAuthenticated) {
|
|
273
|
+
* return <button onClick={() => login()}>Login</button>;
|
|
274
|
+
* }
|
|
275
|
+
*
|
|
276
|
+
* return (
|
|
277
|
+
* <div>
|
|
278
|
+
* <p>Welcome, {user?.name}</p>
|
|
279
|
+
* <p>Organization: {currentOrg?.name}</p>
|
|
280
|
+
* <button onClick={() => logout()}>Logout</button>
|
|
281
|
+
* </div>
|
|
282
|
+
* );
|
|
283
|
+
* }
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
declare function useSso(): UseSsoReturn;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* SSO Callback component
|
|
290
|
+
*
|
|
291
|
+
* Place this component at your callback route (e.g., /sso/callback)
|
|
292
|
+
* It handles the SSO code exchange and redirects after successful login.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```tsx
|
|
296
|
+
* // pages/sso/callback.tsx or app/sso/callback/page.tsx
|
|
297
|
+
* export default function CallbackPage() {
|
|
298
|
+
* return (
|
|
299
|
+
* <SsoCallback
|
|
300
|
+
* redirectTo="/dashboard"
|
|
301
|
+
* onSuccess={(user, orgs) => console.log('Logged in:', user)}
|
|
302
|
+
* onError={(error) => console.error('Login failed:', error)}
|
|
303
|
+
* />
|
|
304
|
+
* );
|
|
305
|
+
* }
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
declare function SsoCallback({ onSuccess, onError, redirectTo, loadingComponent, errorComponent, }: SsoCallbackProps): react_jsx_runtime.JSX.Element | null;
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Organization Switcher component using Ant Design
|
|
312
|
+
*
|
|
313
|
+
* A dropdown component for switching between organizations.
|
|
314
|
+
* Only renders if user has access to multiple organizations.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```tsx
|
|
318
|
+
* // Basic usage
|
|
319
|
+
* <OrganizationSwitcher />
|
|
320
|
+
*
|
|
321
|
+
* // With custom styling
|
|
322
|
+
* <OrganizationSwitcher className="my-switcher" />
|
|
323
|
+
*
|
|
324
|
+
* // With custom render
|
|
325
|
+
* <OrganizationSwitcher
|
|
326
|
+
* renderTrigger={(org, isOpen) => (
|
|
327
|
+
* <Button>{org?.name} {isOpen ? '▲' : '▼'}</Button>
|
|
328
|
+
* )}
|
|
329
|
+
* renderOption={(org, isSelected) => (
|
|
330
|
+
* <div className={isSelected ? 'selected' : ''}>{org.name}</div>
|
|
331
|
+
* )}
|
|
332
|
+
* />
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
declare function OrganizationSwitcher({ className, renderTrigger, renderOption, onChange, }: OrganizationSwitcherProps): react_jsx_runtime.JSX.Element | null;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Protected Route component
|
|
339
|
+
*
|
|
340
|
+
* Wraps content that requires authentication and optionally specific roles/permissions.
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```tsx
|
|
344
|
+
* // Basic protection
|
|
345
|
+
* <ProtectedRoute>
|
|
346
|
+
* <Dashboard />
|
|
347
|
+
* </ProtectedRoute>
|
|
348
|
+
*
|
|
349
|
+
* // With role requirement
|
|
350
|
+
* <ProtectedRoute requiredRole="admin">
|
|
351
|
+
* <AdminPanel />
|
|
352
|
+
* </ProtectedRoute>
|
|
353
|
+
*
|
|
354
|
+
* // With custom fallbacks
|
|
355
|
+
* <ProtectedRoute
|
|
356
|
+
* fallback={<Spinner />}
|
|
357
|
+
* loginFallback={<CustomLoginPage />}
|
|
358
|
+
* onAccessDenied={(reason) => console.log(reason)}
|
|
359
|
+
* >
|
|
360
|
+
* <ProtectedContent />
|
|
361
|
+
* </ProtectedRoute>
|
|
362
|
+
* ```
|
|
363
|
+
*/
|
|
364
|
+
declare function ProtectedRoute({ children, fallback, loginFallback, requiredRole, requiredPermission, onAccessDenied, }: ProtectedRouteProps): react_jsx_runtime.JSX.Element;
|
|
365
|
+
|
|
366
|
+
export { OrganizationSwitcher, type OrganizationSwitcherProps, ProtectedRoute, type ProtectedRouteProps, SsoCallback, type SsoCallbackProps, type SsoCallbackResponse, type SsoConfig, SsoContext, type SsoContextValue, type SsoOrganization, SsoProvider, type SsoProviderProps, type SsoUser, type UseAuthReturn, type UseOrganizationReturn, type UseSsoReturn, useAuth, useOrganization, useSso };
|