@docyrus/app-auth-ui 0.0.1
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/.turbo/turbo-build.log +17 -0
- package/.turbo/turbo-typecheck.log +5 -0
- package/README.md +200 -0
- package/dist/index.d.ts +286 -0
- package/dist/index.js +562 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
- package/src/components/docyrus-auth-provider.tsx +95 -0
- package/src/components/sign-in-button.tsx +62 -0
- package/src/constants.ts +24 -0
- package/src/core/auth-detector.ts +46 -0
- package/src/core/auth-manager.ts +312 -0
- package/src/core/iframe-auth.ts +135 -0
- package/src/core/oauth2-auth.ts +111 -0
- package/src/hooks/use-docyrus-auth.ts +24 -0
- package/src/hooks/use-docyrus-client.ts +15 -0
- package/src/index.ts +35 -0
- package/src/types.ts +60 -0
- package/tsconfig.json +10 -0
- package/tsup.config.ts +15 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
> @docyrus/app-auth-ui@0.0.1 build /Volumes/Developer/tools/docyrus-devkit/packages/app-auth-ui
|
|
3
|
+
> tsup
|
|
4
|
+
|
|
5
|
+
CLI Building entry: src/index.ts
|
|
6
|
+
CLI Using tsconfig: tsconfig.json
|
|
7
|
+
CLI tsup v8.5.1
|
|
8
|
+
CLI Using tsup config: /Volumes/Developer/tools/docyrus-devkit/packages/app-auth-ui/tsup.config.ts
|
|
9
|
+
CLI Target: es2024
|
|
10
|
+
CLI Cleaning output folder
|
|
11
|
+
ESM Build start
|
|
12
|
+
ESM dist/index.js 16.94 KB
|
|
13
|
+
ESM dist/index.js.map 38.56 KB
|
|
14
|
+
ESM ⚡️ Build success in 61ms
|
|
15
|
+
DTS Build start
|
|
16
|
+
DTS ⚡️ Build success in 470ms
|
|
17
|
+
DTS dist/index.d.ts 10.56 KB
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
|
|
2
|
+
> @docyrus/app-auth-ui@0.0.1 typecheck /Volumes/Developer/tools/docyrus-devkit/packages/app-auth-ui
|
|
3
|
+
> eslint src && tsc --noEmit
|
|
4
|
+
|
|
5
|
+
Pages directory cannot be found at /Volumes/Developer/tools/docyrus-devkit/packages/app-auth-ui/pages or /Volumes/Developer/tools/docyrus-devkit/packages/app-auth-ui/src/pages. If using a custom path, please configure with the `no-html-link-for-pages` rule in your eslint config file.
|
package/README.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# @docyrus/app-auth-ui
|
|
2
|
+
|
|
3
|
+
React authentication provider for Docyrus apps. Provides "Sign in with Docyrus" experience with automatic environment detection — standalone apps use OAuth2 Authorization Code + PKCE via page redirect, while iframe-embedded apps receive tokens via `window.postMessage` from the host.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Auto Environment Detection**: Detects standalone vs iframe mode automatically
|
|
8
|
+
- **OAuth2 PKCE**: Full Authorization Code flow with PKCE (S256) for standalone apps
|
|
9
|
+
- **Iframe Auth**: Receives tokens via `postMessage` from `*.docyrus.app` hosts
|
|
10
|
+
- **Token Auto-Refresh**: Proactive token refresh before expiry in both modes
|
|
11
|
+
- **React Hooks**: `useDocyrusAuth()` and `useDocyrusClient()` for easy integration
|
|
12
|
+
- **Ready-to-Use API Client**: Exposes a configured `RestApiClient` from `@docyrus/api-client`
|
|
13
|
+
- **SignInButton**: Unstyled, customizable sign-in button component
|
|
14
|
+
- **TypeScript**: Full type definitions included
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @docyrus/app-auth-ui
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm add @docyrus/app-auth-ui
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Peer Dependencies
|
|
27
|
+
|
|
28
|
+
- `react` >= 18.0.0
|
|
29
|
+
- `@docyrus/api-client` >= 0.0.4
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { DocyrusAuthProvider, useDocyrusAuth, useDocyrusClient, SignInButton } from '@docyrus/app-auth-ui';
|
|
35
|
+
|
|
36
|
+
function App() {
|
|
37
|
+
return (
|
|
38
|
+
<DocyrusAuthProvider>
|
|
39
|
+
<Dashboard />
|
|
40
|
+
</DocyrusAuthProvider>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function Dashboard() {
|
|
45
|
+
const { status, signOut } = useDocyrusAuth();
|
|
46
|
+
const client = useDocyrusClient();
|
|
47
|
+
|
|
48
|
+
if (status === 'loading') return <div>Loading...</div>;
|
|
49
|
+
if (status === 'unauthenticated') return <SignInButton />;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div>
|
|
53
|
+
<p>Authenticated!</p>
|
|
54
|
+
<button onClick={() => client!.get('/v1/users/me').then(console.log)}>
|
|
55
|
+
Fetch user
|
|
56
|
+
</button>
|
|
57
|
+
<button onClick={signOut}>Sign out</button>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Configuration
|
|
64
|
+
|
|
65
|
+
Pass props to `DocyrusAuthProvider` to override defaults:
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
<DocyrusAuthProvider
|
|
69
|
+
apiUrl="https://alpha-api.docyrus.com"
|
|
70
|
+
clientId="your-oauth2-client-id"
|
|
71
|
+
redirectUri="http://localhost:3000/auth/callback"
|
|
72
|
+
scopes={['offline_access', 'Read.All', 'Users.Read']}
|
|
73
|
+
callbackPath="/auth/callback"
|
|
74
|
+
forceMode="standalone"
|
|
75
|
+
>
|
|
76
|
+
<App />
|
|
77
|
+
</DocyrusAuthProvider>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
| Prop | Type | Default | Description |
|
|
81
|
+
|------|------|---------|-------------|
|
|
82
|
+
| `apiUrl` | `string` | `https://alpha-api.docyrus.com` | Docyrus API base URL |
|
|
83
|
+
| `clientId` | `string` | Built-in default | OAuth2 client ID |
|
|
84
|
+
| `redirectUri` | `string` | `window.location.origin + callbackPath` | OAuth2 redirect URI |
|
|
85
|
+
| `scopes` | `string[]` | `['offline_access', 'Read.All', ...]` | OAuth2 scopes |
|
|
86
|
+
| `callbackPath` | `string` | `/auth/callback` | Path to detect OAuth callback |
|
|
87
|
+
| `forceMode` | `'standalone' \| 'iframe'` | Auto-detected | Force a specific auth mode |
|
|
88
|
+
| `storageKeyPrefix` | `string` | `docyrus_oauth2_` | localStorage key prefix |
|
|
89
|
+
| `allowedHostOrigins` | `string[]` | `undefined` | Extra trusted iframe origins |
|
|
90
|
+
|
|
91
|
+
## Hooks
|
|
92
|
+
|
|
93
|
+
### useDocyrusAuth()
|
|
94
|
+
|
|
95
|
+
Returns the full authentication context:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
const {
|
|
99
|
+
status, // 'loading' | 'authenticated' | 'unauthenticated'
|
|
100
|
+
mode, // 'standalone' | 'iframe'
|
|
101
|
+
client, // RestApiClient | null
|
|
102
|
+
tokens, // { accessToken, refreshToken, ... } | null
|
|
103
|
+
signIn, // () => void (redirects to Docyrus login)
|
|
104
|
+
signOut, // () => void
|
|
105
|
+
error // Error | null
|
|
106
|
+
} = useDocyrusAuth();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### useDocyrusClient()
|
|
110
|
+
|
|
111
|
+
Shorthand hook that returns just the API client:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
const client = useDocyrusClient(); // RestApiClient | null
|
|
115
|
+
|
|
116
|
+
if (client) {
|
|
117
|
+
const response = await client.get('/v1/users/me');
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Components
|
|
122
|
+
|
|
123
|
+
### SignInButton
|
|
124
|
+
|
|
125
|
+
Unstyled button that triggers sign-in. Automatically hidden when authenticated or in iframe mode.
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
// Basic
|
|
129
|
+
<SignInButton />
|
|
130
|
+
|
|
131
|
+
// With custom styling
|
|
132
|
+
<SignInButton className="btn btn-primary" label="Log in with Docyrus" />
|
|
133
|
+
|
|
134
|
+
// Render prop for full customization
|
|
135
|
+
<SignInButton>
|
|
136
|
+
{({ signIn, isLoading }) => (
|
|
137
|
+
<button onClick={signIn} disabled={isLoading}>
|
|
138
|
+
{isLoading ? 'Redirecting...' : 'Sign in'}
|
|
139
|
+
</button>
|
|
140
|
+
)}
|
|
141
|
+
</SignInButton>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Auth Modes
|
|
145
|
+
|
|
146
|
+
### Standalone Mode (OAuth2 PKCE)
|
|
147
|
+
|
|
148
|
+
Used when the app runs directly in the browser (not in an iframe). The flow:
|
|
149
|
+
|
|
150
|
+
1. User clicks sign-in
|
|
151
|
+
2. Page redirects to Docyrus authorization endpoint
|
|
152
|
+
3. After login, redirects back with authorization code
|
|
153
|
+
4. Provider automatically exchanges code for tokens
|
|
154
|
+
5. Tokens stored in localStorage, auto-refreshed before expiry
|
|
155
|
+
|
|
156
|
+
### Iframe Mode (postMessage)
|
|
157
|
+
|
|
158
|
+
Used when the app is embedded in an iframe on `*.docyrus.app`. The flow:
|
|
159
|
+
|
|
160
|
+
1. Provider detects iframe environment and validates host origin
|
|
161
|
+
2. Host sends `{ type: 'signin', accessToken, refreshToken }` via `postMessage`
|
|
162
|
+
3. Provider creates API client with received tokens
|
|
163
|
+
4. When tokens expire, provider sends `{ type: 'token-refresh-request' }` to host
|
|
164
|
+
5. Host responds with fresh tokens
|
|
165
|
+
|
|
166
|
+
## Advanced Usage
|
|
167
|
+
|
|
168
|
+
Core classes are exported for advanced use cases:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import {
|
|
172
|
+
AuthManager,
|
|
173
|
+
StandaloneOAuth2Auth,
|
|
174
|
+
IframeAuth,
|
|
175
|
+
detectAuthMode
|
|
176
|
+
} from '@docyrus/app-auth-ui';
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Development
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Install dependencies
|
|
183
|
+
pnpm install
|
|
184
|
+
|
|
185
|
+
# Development mode with watch
|
|
186
|
+
pnpm dev
|
|
187
|
+
|
|
188
|
+
# Build the package
|
|
189
|
+
pnpm build
|
|
190
|
+
|
|
191
|
+
# Run linting
|
|
192
|
+
pnpm lint
|
|
193
|
+
|
|
194
|
+
# Type checking
|
|
195
|
+
pnpm typecheck
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
4
|
+
import { RestApiClient, OAuth2Tokens } from '@docyrus/api-client';
|
|
5
|
+
|
|
6
|
+
/** Authentication mode detected at runtime */
|
|
7
|
+
type AuthMode = 'standalone' | 'iframe';
|
|
8
|
+
/** Authentication state exposed to consumers */
|
|
9
|
+
type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated';
|
|
10
|
+
/** Configuration for the DocyrusAuthProvider */
|
|
11
|
+
interface DocyrusAuthConfig {
|
|
12
|
+
/** OAuth2 client ID. Defaults to the Docyrus public client ID */
|
|
13
|
+
clientId?: string;
|
|
14
|
+
/** API base URL. Defaults to https://alpha-api.docyrus.com */
|
|
15
|
+
apiUrl?: string;
|
|
16
|
+
/** OAuth2 scopes. Defaults to offline_access Read.All Users.Read Users.Read.All DS.Read.All */
|
|
17
|
+
scopes?: string[];
|
|
18
|
+
/** The redirect URI for OAuth2 callback. Defaults to `${window.location.origin}/auth/callback` */
|
|
19
|
+
redirectUri?: string;
|
|
20
|
+
/** The path where the OAuth2 callback is handled. Defaults to '/auth/callback' */
|
|
21
|
+
callbackPath?: string;
|
|
22
|
+
/** Allowed host origins for iframe mode. Used alongside the default *.docyrus.app pattern */
|
|
23
|
+
allowedHostOrigins?: string[];
|
|
24
|
+
/** localStorage key prefix for token storage. Defaults to 'docyrus_oauth2' */
|
|
25
|
+
storageKeyPrefix?: string;
|
|
26
|
+
/** Override auto-detection: force a specific auth mode */
|
|
27
|
+
forceMode?: AuthMode;
|
|
28
|
+
}
|
|
29
|
+
/** The shape of the React context value */
|
|
30
|
+
interface DocyrusAuthContextValue {
|
|
31
|
+
/** Current auth state */
|
|
32
|
+
status: AuthStatus;
|
|
33
|
+
/** The detected authentication mode */
|
|
34
|
+
mode: AuthMode | null;
|
|
35
|
+
/** Pre-configured RestApiClient with valid tokens */
|
|
36
|
+
client: RestApiClient | null;
|
|
37
|
+
/** Current tokens (null when unauthenticated) */
|
|
38
|
+
tokens: OAuth2Tokens | null;
|
|
39
|
+
/** Initiate sign-in (only relevant in standalone mode) */
|
|
40
|
+
signIn: () => void;
|
|
41
|
+
/** Sign out and clear tokens */
|
|
42
|
+
signOut: () => Promise<void>;
|
|
43
|
+
/** Any error that occurred during auth */
|
|
44
|
+
error: Error | null;
|
|
45
|
+
}
|
|
46
|
+
/** PostMessage payload: host sends tokens to the embedded app */
|
|
47
|
+
interface HostSignInMessage {
|
|
48
|
+
type: 'signin';
|
|
49
|
+
accessToken: string;
|
|
50
|
+
refreshToken: string;
|
|
51
|
+
}
|
|
52
|
+
/** PostMessage payload: app requests fresh tokens from the host */
|
|
53
|
+
interface TokenRefreshRequestMessage {
|
|
54
|
+
type: 'token-refresh-request';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
declare const DocyrusAuthContext: react.Context<DocyrusAuthContextValue | null>;
|
|
58
|
+
interface DocyrusAuthProviderProps extends DocyrusAuthConfig {
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
}
|
|
61
|
+
declare function DocyrusAuthProvider({ children, ...config }: DocyrusAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Hook to access Docyrus auth state.
|
|
65
|
+
* Must be used within a <DocyrusAuthProvider>.
|
|
66
|
+
*
|
|
67
|
+
* Returns: { status, mode, tokens, signIn, signOut, client, error }
|
|
68
|
+
*/
|
|
69
|
+
declare function useDocyrusAuth(): DocyrusAuthContextValue;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Hook to get the pre-configured RestApiClient.
|
|
73
|
+
* Returns null when not authenticated.
|
|
74
|
+
*
|
|
75
|
+
* Throws if used outside DocyrusAuthProvider.
|
|
76
|
+
*/
|
|
77
|
+
declare function useDocyrusClient(): RestApiClient | null;
|
|
78
|
+
|
|
79
|
+
interface SignInButtonProps {
|
|
80
|
+
/** Custom label. Defaults to "Sign in with Docyrus" */
|
|
81
|
+
label?: string;
|
|
82
|
+
/** CSS class name for the button */
|
|
83
|
+
className?: string;
|
|
84
|
+
/** Inline styles */
|
|
85
|
+
style?: CSSProperties;
|
|
86
|
+
/** Custom render function. Receives signIn and status. */
|
|
87
|
+
children?: (props: {
|
|
88
|
+
signIn: () => void;
|
|
89
|
+
status: AuthStatus;
|
|
90
|
+
}) => ReactNode;
|
|
91
|
+
/** Disable the button */
|
|
92
|
+
disabled?: boolean;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* "Sign in with Docyrus" button.
|
|
96
|
+
*
|
|
97
|
+
* In iframe mode: renders nothing (auth is handled by the host).
|
|
98
|
+
* When authenticated: renders nothing.
|
|
99
|
+
*
|
|
100
|
+
* Intentionally unstyled — use className, style, or the render-prop
|
|
101
|
+
* children pattern for full customization.
|
|
102
|
+
*/
|
|
103
|
+
declare function SignInButton({ label, className, style, children, disabled }: SignInButtonProps): react_jsx_runtime.JSX.Element | null;
|
|
104
|
+
|
|
105
|
+
type AuthStateListener = (state: {
|
|
106
|
+
status: AuthStatus;
|
|
107
|
+
tokens: OAuth2Tokens | null;
|
|
108
|
+
error: Error | null;
|
|
109
|
+
}) => void;
|
|
110
|
+
/**
|
|
111
|
+
* Unified authentication manager.
|
|
112
|
+
* Orchestrates standalone OAuth2 and iframe postMessage modes,
|
|
113
|
+
* exposes a pre-configured RestApiClient, and manages token lifecycle.
|
|
114
|
+
*/
|
|
115
|
+
declare class AuthManager {
|
|
116
|
+
private mode;
|
|
117
|
+
private status;
|
|
118
|
+
private tokens;
|
|
119
|
+
private error;
|
|
120
|
+
private client;
|
|
121
|
+
private standaloneAuth;
|
|
122
|
+
private iframeAuth;
|
|
123
|
+
private tokenRefreshTimer;
|
|
124
|
+
private listeners;
|
|
125
|
+
private config;
|
|
126
|
+
constructor(config?: DocyrusAuthConfig);
|
|
127
|
+
getMode(): AuthMode;
|
|
128
|
+
getStatus(): AuthStatus;
|
|
129
|
+
getTokens(): OAuth2Tokens | null;
|
|
130
|
+
getClient(): RestApiClient | null;
|
|
131
|
+
getError(): Error | null;
|
|
132
|
+
subscribe(listener: AuthStateListener): () => void;
|
|
133
|
+
private notify;
|
|
134
|
+
/** Initialize the auth manager. Must be called once on mount. */
|
|
135
|
+
initialize(): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Standalone mode initialization.
|
|
138
|
+
* 1. Check if we're returning from an OAuth callback.
|
|
139
|
+
* 2. If not, check for existing tokens in localStorage.
|
|
140
|
+
* 3. If tokens are expired, try to refresh.
|
|
141
|
+
*/
|
|
142
|
+
private initializeStandaloneMode;
|
|
143
|
+
/**
|
|
144
|
+
* Iframe mode initialization.
|
|
145
|
+
* Listen for postMessage tokens from the host.
|
|
146
|
+
* Status remains 'loading' until the host sends the first signin message.
|
|
147
|
+
*/
|
|
148
|
+
private initializeIframeMode;
|
|
149
|
+
/** Initiate sign-in. Only meaningful in standalone mode. */
|
|
150
|
+
signIn(): Promise<void>;
|
|
151
|
+
/**
|
|
152
|
+
* Sign out.
|
|
153
|
+
* Standalone: revoke token, clear localStorage, reset state.
|
|
154
|
+
* Iframe: clear local state (host manages the actual session).
|
|
155
|
+
*/
|
|
156
|
+
signOut(): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* Called when valid tokens are received (either mode).
|
|
159
|
+
* Creates/updates the RestApiClient and schedules token refresh.
|
|
160
|
+
*/
|
|
161
|
+
private setAuthenticated;
|
|
162
|
+
/**
|
|
163
|
+
* Create a RestApiClient with a custom TokenManager that proactively
|
|
164
|
+
* refreshes the token in getToken(). This is necessary because
|
|
165
|
+
* BaseApiClient.getAccessToken() only calls tokenManager.getToken()
|
|
166
|
+
* and does NOT auto-call refreshToken() when the token is expired.
|
|
167
|
+
*/
|
|
168
|
+
private createClient;
|
|
169
|
+
/**
|
|
170
|
+
* Get a valid access token, proactively refreshing if expired.
|
|
171
|
+
* Called by the RestApiClient on every request via tokenManager.getToken().
|
|
172
|
+
*/
|
|
173
|
+
private getValidToken;
|
|
174
|
+
/**
|
|
175
|
+
* Handle token refresh depending on mode.
|
|
176
|
+
* Standalone: use OAuth2Client.getValidAccessToken() which auto-refreshes.
|
|
177
|
+
* Iframe: send postMessage to host requesting new tokens.
|
|
178
|
+
*/
|
|
179
|
+
private handleTokenRefresh;
|
|
180
|
+
/** Schedule proactive token refresh before expiry. */
|
|
181
|
+
private scheduleTokenRefresh;
|
|
182
|
+
private clearTokenRefreshTimer;
|
|
183
|
+
/** Cleanup: remove listeners, timers, stop iframe auth. */
|
|
184
|
+
destroy(): void;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Standalone OAuth2 authorization code flow with PKCE via page redirect.
|
|
189
|
+
* Wraps api-client's OAuth2Client and BrowserOAuth2TokenStorage.
|
|
190
|
+
*/
|
|
191
|
+
declare class StandaloneOAuth2Auth {
|
|
192
|
+
private oauth2Client;
|
|
193
|
+
private storage;
|
|
194
|
+
private callbackPath;
|
|
195
|
+
constructor(config?: DocyrusAuthConfig);
|
|
196
|
+
/**
|
|
197
|
+
* Check if the current page URL is the OAuth2 callback.
|
|
198
|
+
* Called on app initialization to detect returning from the auth server.
|
|
199
|
+
*/
|
|
200
|
+
isCallbackUrl(): boolean;
|
|
201
|
+
/**
|
|
202
|
+
* Initiate the OAuth2 authorization code flow.
|
|
203
|
+
* Stores the current URL for post-auth redirect, then navigates
|
|
204
|
+
* the page to the authorization endpoint.
|
|
205
|
+
*
|
|
206
|
+
* PKCE state (codeVerifier, state) is stored in localStorage
|
|
207
|
+
* by the OAuth2Client and survives the page redirect.
|
|
208
|
+
*/
|
|
209
|
+
initiateLogin(): Promise<void>;
|
|
210
|
+
/**
|
|
211
|
+
* Handle the OAuth2 callback URL.
|
|
212
|
+
* Reads PKCE state from localStorage, validates the state param,
|
|
213
|
+
* exchanges the authorization code for tokens, and stores them.
|
|
214
|
+
*/
|
|
215
|
+
handleCallback(): Promise<OAuth2Tokens>;
|
|
216
|
+
/**
|
|
217
|
+
* Get the URL the user was on before the OAuth redirect.
|
|
218
|
+
* Clears the stored value after retrieval.
|
|
219
|
+
*/
|
|
220
|
+
getReturnUrl(): string | null;
|
|
221
|
+
/** Get currently stored tokens (e.g., on page reload). */
|
|
222
|
+
getStoredTokens(): Promise<OAuth2Tokens | null>;
|
|
223
|
+
/** Check if the stored token is expired (with 60s buffer). */
|
|
224
|
+
isTokenExpired(): Promise<boolean>;
|
|
225
|
+
/** Refresh the access token using the stored refresh token. */
|
|
226
|
+
refreshToken(): Promise<OAuth2Tokens>;
|
|
227
|
+
/** Get a valid access token, refreshing if needed. */
|
|
228
|
+
getValidAccessToken(): Promise<string>;
|
|
229
|
+
/** Logout: revoke token and clear storage. */
|
|
230
|
+
logout(): Promise<void>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
type IframeAuthCallback = (tokens: OAuth2Tokens) => void;
|
|
234
|
+
/**
|
|
235
|
+
* Iframe authentication via postMessage.
|
|
236
|
+
*
|
|
237
|
+
* Protocol:
|
|
238
|
+
* - Host → App: { type: "signin", accessToken, refreshToken }
|
|
239
|
+
* - App → Host: { type: "token-refresh-request" }
|
|
240
|
+
*
|
|
241
|
+
* Every incoming message's event.origin is validated against
|
|
242
|
+
* the allowed host pattern before processing.
|
|
243
|
+
*/
|
|
244
|
+
declare class IframeAuth {
|
|
245
|
+
private allowedOrigins;
|
|
246
|
+
private allowedPattern;
|
|
247
|
+
private onTokensReceived;
|
|
248
|
+
private refreshPromise;
|
|
249
|
+
private messageHandler;
|
|
250
|
+
constructor(allowedOrigins?: string[], allowedPattern?: RegExp);
|
|
251
|
+
/**
|
|
252
|
+
* Start listening for postMessage events from the host.
|
|
253
|
+
* The callback is invoked every time valid tokens are received.
|
|
254
|
+
*/
|
|
255
|
+
start(onTokensReceived: IframeAuthCallback): void;
|
|
256
|
+
/** Stop listening for postMessage events. */
|
|
257
|
+
stop(): void;
|
|
258
|
+
/**
|
|
259
|
+
* Request fresh tokens from the host.
|
|
260
|
+
* Posts a "token-refresh-request" to the host, then waits for
|
|
261
|
+
* a "signin" response.
|
|
262
|
+
*
|
|
263
|
+
* Only one refresh request can be in-flight at a time.
|
|
264
|
+
* Additional callers share the same promise.
|
|
265
|
+
*/
|
|
266
|
+
requestTokenRefresh(): Promise<OAuth2Tokens>;
|
|
267
|
+
private isOriginAllowed;
|
|
268
|
+
private handleMessage;
|
|
269
|
+
private rejectPendingRefresh;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Detect whether the app is inside an iframe from a trusted *.docyrus.app host
|
|
274
|
+
* or running as a standalone page.
|
|
275
|
+
*
|
|
276
|
+
* If we are in an iframe but NOT from a trusted origin, we fall back
|
|
277
|
+
* to standalone mode (graceful degradation).
|
|
278
|
+
*/
|
|
279
|
+
declare function detectAuthMode(allowedOrigins?: string[], allowedPattern?: RegExp): AuthMode;
|
|
280
|
+
|
|
281
|
+
declare const DEFAULT_API_URL = "https://alpha-api.docyrus.com";
|
|
282
|
+
declare const DEFAULT_OAUTH_CLIENT_ID = "90565525-8283-4881-82a9-8613eb82ae27";
|
|
283
|
+
declare const DEFAULT_OAUTH_SCOPES: string[];
|
|
284
|
+
declare const DEFAULT_CALLBACK_PATH = "/auth/callback";
|
|
285
|
+
|
|
286
|
+
export { AuthManager, type AuthMode, type AuthStatus, DEFAULT_API_URL, DEFAULT_CALLBACK_PATH, DEFAULT_OAUTH_CLIENT_ID, DEFAULT_OAUTH_SCOPES, type DocyrusAuthConfig, DocyrusAuthContext, type DocyrusAuthContextValue, DocyrusAuthProvider, type DocyrusAuthProviderProps, type HostSignInMessage, IframeAuth, SignInButton, type SignInButtonProps, StandaloneOAuth2Auth, type TokenRefreshRequestMessage, detectAuthMode, useDocyrusAuth, useDocyrusClient };
|