Skip to content

Commit fb1bc99

Browse files
committed
Add comprehensive README for React package
1 parent d671ec7 commit fb1bc99

File tree

1 file changed

+320
-0
lines changed

1 file changed

+320
-0
lines changed

packages/react/README.md

Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
# @vector-institute/aieng-auth-react
2+
3+
React hooks and components for CyberArk OAuth authentication with PKCE support.
4+
5+
## Features
6+
7+
- 🎣 React hooks for authentication state and token management
8+
- 🔐 Built-in `AuthProvider` for managing authentication context
9+
- 🛡️ `ProtectedRoute` component for route protection
10+
- ⚡ Automatic token refresh handling
11+
- 🎯 TypeScript support with full type definitions
12+
- 🔄 Loading and error states handled automatically
13+
14+
## Installation
15+
16+
```bash
17+
npm install @vector-institute/aieng-auth-react
18+
# or
19+
pnpm add @vector-institute/aieng-auth-react
20+
# or
21+
yarn add @vector-institute/aieng-auth-react
22+
```
23+
24+
## Quick Start
25+
26+
### 1. Wrap your app with AuthProvider
27+
28+
```tsx
29+
import { AuthProvider } from '@vector-institute/aieng-auth-react';
30+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
31+
32+
const authConfig = {
33+
clientId: 'your-google-client-id',
34+
clientSecret: 'your-google-client-secret',
35+
redirectUri: 'http://localhost:3000/callback',
36+
postLogoutRedirectUri: 'http://localhost:3000',
37+
allowedDomains: ['yourdomain.com'], // Optional: restrict by email domain
38+
};
39+
40+
function App() {
41+
return (
42+
<AuthProvider config={authConfig}>
43+
<BrowserRouter>
44+
<Routes>
45+
<Route path="/" element={<HomePage />} />
46+
<Route path="/dashboard" element={<DashboardPage />} />
47+
<Route path="/callback" element={<CallbackPage />} />
48+
</Routes>
49+
</BrowserRouter>
50+
</AuthProvider>
51+
);
52+
}
53+
```
54+
55+
### 2. Use the authentication hook
56+
57+
```tsx
58+
import { useAuth } from '@vector-institute/aieng-auth-react';
59+
60+
function HomePage() {
61+
const { isAuthenticated, isLoading, user, login, logout, error } = useAuth();
62+
63+
if (isLoading) {
64+
return <div>Loading...</div>;
65+
}
66+
67+
if (error) {
68+
return <div>Error: {error.message}</div>;
69+
}
70+
71+
return (
72+
<div>
73+
{!isAuthenticated ? (
74+
<button onClick={login}>Sign in with Google</button>
75+
) : (
76+
<div>
77+
<p>Welcome, {user?.name}!</p>
78+
<p>Email: {user?.email}</p>
79+
<button onClick={logout}>Logout</button>
80+
</div>
81+
)}
82+
</div>
83+
);
84+
}
85+
```
86+
87+
### 3. Handle the OAuth callback
88+
89+
```tsx
90+
import { useAuth } from '@vector-institute/aieng-auth-react';
91+
import { useEffect } from 'react';
92+
import { useNavigate } from 'react-router-dom';
93+
94+
function CallbackPage() {
95+
const { handleCallback, isLoading, error } = useAuth();
96+
const navigate = useNavigate();
97+
98+
useEffect(() => {
99+
handleCallback().then(() => {
100+
navigate('/dashboard');
101+
});
102+
}, [handleCallback, navigate]);
103+
104+
if (error) {
105+
return <div>Authentication failed: {error.message}</div>;
106+
}
107+
108+
return <div>Completing authentication...</div>;
109+
}
110+
```
111+
112+
## API Reference
113+
114+
### AuthProvider
115+
116+
Provides authentication context to your application.
117+
118+
```tsx
119+
<AuthProvider config={authConfig} storage={storage}>
120+
{children}
121+
</AuthProvider>
122+
```
123+
124+
**Props:**
125+
- `config` (required): Authentication configuration object
126+
- `clientId`: Google OAuth client ID
127+
- `clientSecret`: Google OAuth client secret
128+
- `redirectUri`: OAuth redirect URI
129+
- `postLogoutRedirectUri`: Where to redirect after logout
130+
- `allowedDomains`: Array of allowed email domains (optional)
131+
- `storage` (optional): Token storage implementation (defaults to `MemoryTokenStorage`)
132+
- `children`: React children
133+
134+
### useAuth Hook
135+
136+
Access authentication state and methods.
137+
138+
```tsx
139+
const {
140+
isAuthenticated,
141+
isLoading,
142+
user,
143+
error,
144+
login,
145+
logout,
146+
handleCallback,
147+
refreshToken,
148+
} = useAuth();
149+
```
150+
151+
**Returns:**
152+
- `isAuthenticated`: Boolean indicating if user is authenticated
153+
- `isLoading`: Boolean indicating if authentication is in progress
154+
- `user`: User object with profile information (name, email, picture, etc.)
155+
- `error`: Error object if authentication fails
156+
- `login()`: Function to initiate OAuth login flow
157+
- `logout()`: Function to log out the user
158+
- `handleCallback()`: Function to handle OAuth callback (call this on your callback page)
159+
- `refreshToken()`: Function to manually refresh the access token
160+
161+
### useToken Hook
162+
163+
Access token information directly.
164+
165+
```tsx
166+
const { accessToken, isValid, refresh } = useToken();
167+
```
168+
169+
**Returns:**
170+
- `accessToken`: Current access token (string or null)
171+
- `isValid`: Boolean indicating if the token is valid
172+
- `refresh()`: Function to refresh the token
173+
174+
### ProtectedRoute Component
175+
176+
Protect routes that require authentication.
177+
178+
```tsx
179+
import { ProtectedRoute } from '@vector-institute/aieng-auth-react';
180+
181+
<Route
182+
path="/dashboard"
183+
element={
184+
<ProtectedRoute redirectTo="/login">
185+
<DashboardPage />
186+
</ProtectedRoute>
187+
}
188+
/>
189+
```
190+
191+
**Props:**
192+
- `children`: React children to render if authenticated
193+
- `redirectTo`: Path to redirect to if not authenticated (default: '/')
194+
195+
## Types
196+
197+
```typescript
198+
import type {
199+
AuthState,
200+
AuthContextValue,
201+
AuthProviderProps,
202+
ProtectedRouteProps,
203+
// Re-exported from core
204+
AuthConfig,
205+
AuthTokens,
206+
User,
207+
} from '@vector-institute/aieng-auth-react';
208+
```
209+
210+
## Configuration
211+
212+
### Environment Variables
213+
214+
Example `.env` file for your React app:
215+
216+
```env
217+
VITE_GOOGLE_CLIENT_ID=your-client-id
218+
VITE_GOOGLE_CLIENT_SECRET=your-client-secret
219+
VITE_REDIRECT_URI=http://localhost:3000/callback
220+
VITE_POST_LOGOUT_REDIRECT_URI=http://localhost:3000
221+
VITE_ALLOWED_DOMAINS=yourdomain.com,anotherdomain.com
222+
```
223+
224+
### Token Storage
225+
226+
By default, `AuthProvider` uses `MemoryTokenStorage` which stores tokens in memory (most secure but lost on refresh). You can provide a custom storage:
227+
228+
```tsx
229+
import { SessionStorageAdapter } from '@vector-institute/aieng-auth-core';
230+
231+
<AuthProvider config={authConfig} storage={new SessionStorageAdapter()}>
232+
{children}
233+
</AuthProvider>
234+
```
235+
236+
## Security Best Practices
237+
238+
- Always use PKCE flow (automatically handled by this library)
239+
- Use `MemoryTokenStorage` for maximum security (tokens lost on refresh)
240+
- Use `SessionStorageAdapter` if you need persistence across page refreshes
241+
- Avoid `LocalStorageAdapter` unless absolutely necessary
242+
- Restrict access by email domain using `allowedDomains` config
243+
- Always use HTTPS in production
244+
- Never commit OAuth client secrets to version control
245+
246+
## Example: Complete Authentication Flow
247+
248+
```tsx
249+
// App.tsx
250+
import { AuthProvider } from '@vector-institute/aieng-auth-react';
251+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
252+
253+
const config = {
254+
clientId: process.env.REACT_APP_CLIENT_ID,
255+
clientSecret: process.env.REACT_APP_CLIENT_SECRET,
256+
redirectUri: `${window.location.origin}/callback`,
257+
postLogoutRedirectUri: window.location.origin,
258+
allowedDomains: ['yourdomain.com'],
259+
};
260+
261+
function App() {
262+
return (
263+
<AuthProvider config={config}>
264+
<BrowserRouter>
265+
<Routes>
266+
<Route path="/" element={<LoginPage />} />
267+
<Route path="/callback" element={<CallbackPage />} />
268+
<Route
269+
path="/dashboard"
270+
element={
271+
<ProtectedRoute>
272+
<DashboardPage />
273+
</ProtectedRoute>
274+
}
275+
/>
276+
</Routes>
277+
</BrowserRouter>
278+
</AuthProvider>
279+
);
280+
}
281+
282+
// LoginPage.tsx
283+
function LoginPage() {
284+
const { login, isAuthenticated } = useAuth();
285+
286+
if (isAuthenticated) {
287+
return <Navigate to="/dashboard" />;
288+
}
289+
290+
return <button onClick={login}>Sign in with Google</button>;
291+
}
292+
293+
// CallbackPage.tsx
294+
function CallbackPage() {
295+
const { handleCallback } = useAuth();
296+
const navigate = useNavigate();
297+
298+
useEffect(() => {
299+
handleCallback().then(() => navigate('/dashboard'));
300+
}, []);
301+
302+
return <div>Authenticating...</div>;
303+
}
304+
305+
// DashboardPage.tsx
306+
function DashboardPage() {
307+
const { user, logout } = useAuth();
308+
309+
return (
310+
<div>
311+
<h1>Welcome, {user?.name}!</h1>
312+
<button onClick={logout}>Logout</button>
313+
</div>
314+
);
315+
}
316+
```
317+
318+
## License
319+
320+
MIT

0 commit comments

Comments
 (0)