@arow-software/auth-client 1.1.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.
@@ -0,0 +1,251 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { AxiosInstance } from 'axios';
3
+
4
+ /**
5
+ * User object returned from ArowAuth
6
+ */
7
+ interface User {
8
+ id: string;
9
+ email: string;
10
+ firstName?: string;
11
+ lastName?: string;
12
+ displayName?: string;
13
+ avatarUrl?: string;
14
+ emailVerified: boolean;
15
+ roles?: string[];
16
+ permissions?: string[];
17
+ createdAt?: string;
18
+ updatedAt?: string;
19
+ }
20
+ /**
21
+ * JWT token payload structure
22
+ */
23
+ interface JwtPayload {
24
+ sub: string;
25
+ email: string;
26
+ given_name?: string;
27
+ family_name?: string;
28
+ name?: string;
29
+ picture?: string;
30
+ email_verified?: boolean;
31
+ roles?: string[];
32
+ permissions?: string[];
33
+ iat: number;
34
+ exp: number;
35
+ iss: string;
36
+ aud: string | string[];
37
+ }
38
+ /**
39
+ * Token pair returned from auth endpoints
40
+ */
41
+ interface TokenPair {
42
+ accessToken: string;
43
+ refreshToken: string;
44
+ expiresIn?: number;
45
+ tokenType?: string;
46
+ }
47
+ /**
48
+ * Auth context state
49
+ */
50
+ interface AuthState {
51
+ user: User | null;
52
+ isAuthenticated: boolean;
53
+ isLoading: boolean;
54
+ error: string | null;
55
+ }
56
+ /**
57
+ * Auth context value including actions
58
+ */
59
+ interface AuthContextValue extends AuthState {
60
+ login: (redirectPath?: string) => void;
61
+ logout: () => Promise<void>;
62
+ refreshUser: () => Promise<void>;
63
+ }
64
+ /**
65
+ * Configuration for the auth client
66
+ */
67
+ interface AuthConfig {
68
+ /**
69
+ * Base URL of the ArowAuth SSO server
70
+ * @example "https://sso.arowsoftware.co.uk"
71
+ */
72
+ ssoBaseUrl: string;
73
+ /**
74
+ * Client ID registered with ArowAuth
75
+ * @example "arowtrades"
76
+ */
77
+ clientId: string;
78
+ /**
79
+ * Base URL of your API that will validate tokens
80
+ * @example "http://localhost:5001"
81
+ */
82
+ apiBaseUrl?: string;
83
+ /**
84
+ * Custom redirect URI after SSO login (defaults to current origin + /callback)
85
+ */
86
+ redirectUri?: string;
87
+ /**
88
+ * Scopes to request from SSO (defaults to ['openid', 'email', 'profile'])
89
+ */
90
+ scopes?: string[];
91
+ /**
92
+ * Storage key prefix (defaults to 'arowauth')
93
+ */
94
+ storagePrefix?: string;
95
+ /**
96
+ * Use sessionStorage instead of localStorage (defaults to false)
97
+ */
98
+ useSessionStorage?: boolean;
99
+ /**
100
+ * Callback when tokens are refreshed
101
+ */
102
+ onTokenRefresh?: (tokens: TokenPair) => void;
103
+ /**
104
+ * Callback when auth error occurs
105
+ */
106
+ onAuthError?: (error: Error) => void;
107
+ /**
108
+ * Callback when user is logged out
109
+ */
110
+ onLogout?: () => void;
111
+ }
112
+ /**
113
+ * Props for AuthProvider component
114
+ */
115
+ interface AuthProviderProps extends AuthConfig {
116
+ children: ReactNode;
117
+ }
118
+
119
+ /**
120
+ * Initialize token manager with configuration
121
+ */
122
+ declare function initTokenManager(authConfig: AuthConfig): void;
123
+ /**
124
+ * Decode a JWT token without verification
125
+ */
126
+ declare function decodeJwt(token: string): JwtPayload | null;
127
+ /**
128
+ * Get the access token from storage
129
+ */
130
+ declare function getAccessToken(): string | null;
131
+ /**
132
+ * Get the refresh token from storage
133
+ */
134
+ declare function getRefreshToken(): string | null;
135
+ /**
136
+ * Store tokens in storage
137
+ */
138
+ declare function setTokens(accessToken: string, refreshToken: string): void;
139
+ /**
140
+ * Clear all tokens from storage
141
+ */
142
+ declare function clearTokens(): void;
143
+ /**
144
+ * Check if the access token is expired or about to expire
145
+ */
146
+ declare function isTokenExpired(token?: string | null): boolean;
147
+ /**
148
+ * Check if we have a valid (non-expired) access token
149
+ */
150
+ declare function hasValidToken(): boolean;
151
+ /**
152
+ * Get user info from the current access token
153
+ */
154
+ declare function getUserFromToken(): JwtPayload | null;
155
+ /**
156
+ * Refresh tokens using the refresh token
157
+ * Handles concurrent refresh requests by returning the same promise
158
+ */
159
+ declare function refreshTokens(): Promise<TokenPair | null>;
160
+ /**
161
+ * Get a valid access token, refreshing if necessary
162
+ */
163
+ declare function getValidAccessToken(): Promise<string | null>;
164
+
165
+ /**
166
+ * Create and configure axios instance with auth interceptors
167
+ */
168
+ declare function createAuthClient(axiosInstance: AxiosInstance, config: AuthConfig): AxiosInstance;
169
+ /**
170
+ * Create a new axios instance with auth interceptors
171
+ */
172
+ declare function createApiClient(config: AuthConfig): AxiosInstance;
173
+
174
+ declare const AuthContext: React.Context<AuthContextValue | undefined>;
175
+ /**
176
+ * AuthProvider component - wraps app with auth context
177
+ */
178
+ declare function AuthProvider(props: AuthProviderProps): React.ReactElement;
179
+
180
+ /**
181
+ * Hook to access auth state and actions
182
+ *
183
+ * @returns Auth context value with user, isAuthenticated, login, logout, etc.
184
+ * @throws Error if used outside of AuthProvider
185
+ *
186
+ * @example
187
+ * ```tsx
188
+ * function MyComponent() {
189
+ * const { user, isAuthenticated, login, logout, isLoading } = useAuth();
190
+ *
191
+ * if (isLoading) return <div>Loading...</div>;
192
+ *
193
+ * if (!isAuthenticated) {
194
+ * return <button onClick={() => login()}>Login</button>;
195
+ * }
196
+ *
197
+ * return (
198
+ * <div>
199
+ * <p>Welcome, {user?.displayName || user?.email}!</p>
200
+ * <button onClick={logout}>Logout</button>
201
+ * </div>
202
+ * );
203
+ * }
204
+ * ```
205
+ */
206
+ declare function useAuth(): AuthContextValue;
207
+ /**
208
+ * Hook to check if user is authenticated (convenience wrapper)
209
+ *
210
+ * @returns Boolean indicating if user is authenticated
211
+ */
212
+ declare function useIsAuthenticated(): boolean;
213
+ /**
214
+ * Hook to get current user (convenience wrapper)
215
+ *
216
+ * @returns Current user or null
217
+ */
218
+ declare function useUser(): User | null;
219
+
220
+ /**
221
+ * Hook to get a configured axios instance with auth interceptors
222
+ *
223
+ * The returned axios instance will:
224
+ * - Automatically attach Bearer token to requests
225
+ * - Handle 401 responses by refreshing tokens and retrying
226
+ * - Queue concurrent requests during token refresh
227
+ *
228
+ * @returns Configured axios instance
229
+ * @throws Error if used outside of AuthProvider
230
+ *
231
+ * @example
232
+ * ```tsx
233
+ * function MyComponent() {
234
+ * const client = useAuthClient();
235
+ *
236
+ * const fetchData = async () => {
237
+ * try {
238
+ * const response = await client.get('/api/data');
239
+ * console.log(response.data);
240
+ * } catch (error) {
241
+ * console.error('Failed to fetch data', error);
242
+ * }
243
+ * };
244
+ *
245
+ * return <button onClick={fetchData}>Fetch Data</button>;
246
+ * }
247
+ * ```
248
+ */
249
+ declare function useAuthClient(): AxiosInstance;
250
+
251
+ export { type AuthConfig, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthState, type JwtPayload, type TokenPair, type User, clearTokens, createApiClient, createAuthClient, decodeJwt, getAccessToken, getRefreshToken, getUserFromToken, getValidAccessToken, hasValidToken, initTokenManager, isTokenExpired, refreshTokens, setTokens, useAuth, useAuthClient, useIsAuthenticated, useUser };