@mavenmm/teamwork-auth 2.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/CHANGELOG.md ADDED
@@ -0,0 +1,55 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - Initial project setup
12
+ - TypeScript configuration
13
+ - React SSO Provider component
14
+ - Authentication hooks and utilities
15
+ - Netlify Functions helpers
16
+ - Comprehensive documentation
17
+
18
+ ## [1.0.0] - 2024-01-XX
19
+
20
+ ### Added
21
+ - 🎉 Initial release of Maven Marketing SSO package
22
+ - 🔐 Teamwork OAuth integration
23
+ - ⚛️ React Provider pattern for auth state management
24
+ - 🌐 Netlify Functions support for serverless backend
25
+ - 🔒 Full TypeScript support with type definitions
26
+ - 🎯 Role-based access control
27
+ - 🔄 Automatic token refresh functionality
28
+ - 📱 Ready-to-use authentication components
29
+ - 🛡️ Secure token storage with fallback mechanisms
30
+ - 📚 Comprehensive documentation and examples
31
+
32
+ ### Components
33
+ - `SSOProvider` - Main authentication provider
34
+ - `LoginButton` - Customizable login button
35
+ - `LogoutButton` - Logout functionality
36
+ - `ProtectedRoute` - Route protection with role/permission checks
37
+
38
+ ### Hooks
39
+ - `useAuth` - Main authentication hook
40
+ - `useSSOContext` - Direct context access
41
+
42
+ ### Utilities
43
+ - `createSSOClient` - SSO client factory
44
+ - `createAuthHandler` - Netlify auth handler
45
+ - `createCallbackHandler` - OAuth callback handler
46
+ - `createTokenRefreshHandler` - Token refresh handler
47
+
48
+ ### Security Features
49
+ - Secure cookie storage with localStorage fallback
50
+ - CORS handling for Netlify Functions
51
+ - Token expiration management
52
+ - Automatic token refresh
53
+
54
+ [Unreleased]: https://github.com/your-username/mavenmm-tw-netlify-react-sso/compare/v1.0.0...HEAD
55
+ [1.0.0]: https://github.com/your-username/mavenmm-tw-netlify-react-sso/releases/tag/v1.0.0
package/README.md ADDED
@@ -0,0 +1,403 @@
1
+ # Teamwork Auth 🚀 v2.0
2
+
3
+ A centralized React package for Teamwork authentication using an external auth service. **No more copying auth logic between apps!**
4
+
5
+ ## Architecture (v2.0) - Centralized SSO System
6
+
7
+ ```mermaid
8
+ graph TB
9
+ A[app1.mavenmm.com] --> D[auth.mavenmm.com]
10
+ B[admin.mavenmm.com] --> D
11
+ C[dashboard.mavenmm.com] --> D
12
+ D --> E[Teamwork API]
13
+
14
+ A -.->|Shared Cookies| B
15
+ B -.->|Shared Cookies| C
16
+ A -.->|Shared Cookies| C
17
+ ```
18
+
19
+ ### Components:
20
+ 1. **Frontend Package** (`@mavenmm/teamwork-auth`): React components and hooks for any Maven app
21
+ 2. **Centralized Auth Service** (`auth.mavenmm.com`): Handles all authentication logic and Teamwork API communication
22
+ 3. **Maven Apps** (`*.mavenmm.com`): Your applications that need authentication
23
+
24
+ ### Benefits:
25
+ - **🔒 Security**: Teamwork API tokens isolated to auth service only
26
+ - **🚀 Zero Backend**: Apps just install npm package - no server code needed
27
+ - **🌐 SSO**: Login once, authenticated across all `*.mavenmm.com` apps
28
+ - **🔧 Maintainable**: Update auth logic in one place for all apps
29
+ - **⚡ Fast Setup**: New apps get auth in minutes, not hours
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ npm install @mavenmm/teamwork-auth @teamwork/login-button react-router-dom
35
+ ```
36
+
37
+ ## Available Exports
38
+
39
+ ```tsx
40
+ // React Components & Hooks (v2.0 - Centralized Auth Service)
41
+ import {
42
+ AuthProvider,
43
+ useAuthContext,
44
+ useTeamworkAuth,
45
+ Login,
46
+ type TeamworkAuthConfig
47
+ } from '@mavenmm/teamwork-auth';
48
+ ```
49
+
50
+ **Requirements:**
51
+ - React Router DOM v6+ (peer dependency)
52
+ - External auth service running at `auth.mavenmm.com`
53
+
54
+ ## Quick Start (v2.0 - External Auth Service)
55
+
56
+ ### 1. Using the hook directly (Recommended)
57
+ ```tsx
58
+ import React from 'react';
59
+ import { useTeamworkAuth, Login, type TeamworkAuthConfig } from '@mavenmm/teamwork-auth';
60
+
61
+ const authConfig: TeamworkAuthConfig = {
62
+ authServiceUrl: 'https://auth.mavenmm.com',
63
+ cookieDomain: '.mavenmm.com'
64
+ };
65
+
66
+ function App() {
67
+ const { user, loading, isAuthenticated, logout } = useTeamworkAuth(authConfig);
68
+
69
+ if (loading) {
70
+ return <div>Loading...</div>;
71
+ }
72
+
73
+ if (!isAuthenticated) {
74
+ return <Login />;
75
+ }
76
+
77
+ return (
78
+ <div>
79
+ <h1>Welcome, {user?.firstName}!</h1>
80
+ <button onClick={logout}>Logout</button>
81
+ </div>
82
+ );
83
+ }
84
+ ```
85
+
86
+ ### 2. Using AuthProvider (Alternative)
87
+ ```tsx
88
+ import React from 'react';
89
+ import { BrowserRouter, Routes, Route } from 'react-router-dom';
90
+ import { AuthProvider, useAuthContext } from '@mavenmm/teamwork-auth';
91
+
92
+ function App() {
93
+ return (
94
+ <BrowserRouter>
95
+ <Routes>
96
+ <Route path="/*" element={<AuthenticatedApp />} />
97
+ </Routes>
98
+ </BrowserRouter>
99
+ );
100
+ }
101
+
102
+ // AuthProvider must be inside Router context (inside a Route element)
103
+ function AuthenticatedApp() {
104
+ return (
105
+ <AuthProvider authServiceUrl="https://auth.mavenmm.com">
106
+ <Routes>
107
+ <Route path="/home" element={<Dashboard />} />
108
+ <Route path="/profile" element={<Profile />} />
109
+ </Routes>
110
+ </AuthProvider>
111
+ );
112
+ }
113
+
114
+ function Dashboard() {
115
+ const { user, loading, isAuthenticated, logout } = useAuthContext();
116
+
117
+ if (loading) return <div>Loading...</div>;
118
+
119
+ return (
120
+ <div>
121
+ <h1>Welcome, {user?.firstName}!</h1>
122
+ <button onClick={logout}>Logout</button>
123
+ </div>
124
+ );
125
+ }
126
+ ```
127
+
128
+ ### 3. No Backend Code Needed! 🎉
129
+
130
+ **That's it!** No Netlify Functions, no environment variables, no backend setup required in your app.
131
+
132
+ The external auth service at `auth.mavenmm.com` handles all the backend logic:
133
+ - Teamwork OAuth flow
134
+ - JWT token management
135
+ - Cookie handling for `.mavenmm.com` subdomains
136
+ - Authentication validation
137
+
138
+ ## Cookie Domain Configuration 🍪
139
+
140
+ For subdomain sharing (e.g., sharing auth between `app.yourdomain.com` and `admin.yourdomain.com`):
141
+
142
+ ```bash
143
+ # In your .env file
144
+ VITE_COOKIE_DOMAIN=.yourdomain.com
145
+ ```
146
+
147
+ This allows the authentication cookie to work across all `*.yourdomain.com` subdomains.
148
+
149
+ **Behavior:**
150
+ - **Localhost**: No domain set (works with any localhost port)
151
+ - **Production with VITE_COOKIE_DOMAIN**: Cookie shared across subdomains
152
+ - **Production without VITE_COOKIE_DOMAIN**: Cookie only works on exact domain
153
+
154
+ ## Features
155
+
156
+ - 🔐 **Teamwork OAuth** - Uses official Teamwork login button
157
+ - 🍪 **Cookie-based Auth** - Secure authentication with HttpOnly cookies
158
+ - 🌐 **Subdomain Support** - Configurable cookie sharing across subdomains
159
+ - 🔄 **Auto-redirect** - Smart redirect handling between apps
160
+ - 📱 **TypeScript** - Full type safety
161
+ - ⚡ **Netlify Functions** - Ready-to-use serverless auth handlers
162
+ - 🎯 **Vite Optimized** - Built specifically for Vite+React+Netlify stack
163
+
164
+ ## Important Notes 📝
165
+
166
+ **Router Requirement**: The `AuthProvider` uses React Router hooks (`useNavigate`, `useLocation`) and must be placed inside a Router context. Specifically, it should be inside a Route element, not as a direct child of `<Router>`.
167
+
168
+ **Environment Variables**: You need both client-side (`VITE_*`) and server-side variables. The client-side variables are for React components, and server-side variables are for Netlify Functions.
169
+
170
+ ## API Reference
171
+
172
+ ### React Components
173
+
174
+ #### `useTeamworkAuth(config)`
175
+
176
+ ```tsx
177
+ const {
178
+ user, // User | null
179
+ setUser, // (user: User | null) => void
180
+ loading, // boolean
181
+ isAuthenticated, // boolean
182
+ login, // (code: string) => Promise<{twUser: User}>
183
+ logout // () => Promise<void>
184
+ } = useTeamworkAuth({
185
+ authServiceUrl: 'https://auth.mavenmm.com',
186
+ cookieDomain: '.mavenmm.com'
187
+ });
188
+ ```
189
+
190
+ #### `<Login>`
191
+
192
+ ```tsx
193
+ <Login /> // Uses environment variables for configuration
194
+ ```
195
+
196
+ ### Auth Service Endpoints (auth.mavenmm.com)
197
+
198
+ #### `POST /.netlify/functions/login`
199
+ - **Headers**: `code` (OAuth authorization code)
200
+ - **Response**: `{ twUser: User }`
201
+ - **Sets**: `maven_auth_token` cookie (HttpOnly, secure)
202
+
203
+ #### `GET /.netlify/functions/logout`
204
+ - **Response**: `{ success: true }`
205
+ - **Clears**: `maven_auth_token` cookie
206
+
207
+ #### `GET /.netlify/functions/checkAuth`
208
+ - **Response**: `{ authenticated: boolean, userId?: string }`
209
+ - **Validates**: `maven_auth_token` JWT cookie
210
+
211
+ ### Types
212
+
213
+ ```tsx
214
+ interface User {
215
+ id: string;
216
+ firstName: string;
217
+ lastName: string;
218
+ email: string;
219
+ avatar: string;
220
+ company: {
221
+ id: number;
222
+ name: string;
223
+ logo: string;
224
+ };
225
+ }
226
+ ```
227
+
228
+ ## Multi-Site Integration Example
229
+
230
+ Adding auth to a new Maven app (e.g., `app1.mavenmm.com`):
231
+
232
+ ```tsx
233
+ // Just install and configure - no backend code needed!
234
+ import { useTeamworkAuth, Login } from '@mavenmm/teamwork-auth';
235
+
236
+ const authConfig = {
237
+ authServiceUrl: 'https://auth.mavenmm.com',
238
+ cookieDomain: '.mavenmm.com' // Enables SSO across subdomains
239
+ };
240
+
241
+ function App() {
242
+ const { user, isAuthenticated, logout } = useTeamworkAuth(authConfig);
243
+
244
+ if (!isAuthenticated) return <Login />;
245
+
246
+ return (
247
+ <div>
248
+ <h1>Welcome to app1.mavenmm.com, {user?.firstName}!</h1>
249
+ <button onClick={logout}>Logout</button>
250
+ </div>
251
+ );
252
+ }
253
+ ```
254
+
255
+ **That's it!** The user will be automatically authenticated if they're logged in to any other Maven app.
256
+
257
+ ## Troubleshooting
258
+
259
+ ### Common Issues
260
+
261
+ #### 🚫 "User not authenticated" but should be logged in
262
+
263
+ **Symptoms**: App shows login screen even though user logged in elsewhere
264
+ **Causes**:
265
+ - Incorrect `cookieDomain` configuration
266
+ - App not on `*.mavenmm.com` subdomain
267
+ - Auth service unreachable
268
+
269
+ **Solutions**:
270
+ ```tsx
271
+ // 1. Check cookie domain configuration
272
+ const authConfig = {
273
+ cookieDomain: '.mavenmm.com' // Must include the dot!
274
+ };
275
+
276
+ // 2. Verify subdomain
277
+ // ✅ Good: app1.mavenmm.com, admin.mavenmm.com
278
+ // ❌ Bad: app1.mavenmarketing.com, localhost:3000
279
+
280
+ // 3. Test auth service
281
+ fetch('https://auth.mavenmm.com/.netlify/functions/checkAuth')
282
+ .then(res => console.log('Auth service status:', res.status));
283
+ ```
284
+
285
+ #### 🔄 Login button doesn't work
286
+
287
+ **Symptoms**: Clicking login does nothing or shows errors
288
+ **Causes**:
289
+ - CORS issues between app and auth service
290
+ - Auth service environment variables missing
291
+ - Teamwork OAuth app misconfigured
292
+
293
+ **Solutions**:
294
+ ```bash
295
+ # 1. Check browser console for CORS errors
296
+ # 2. Verify auth service is deployed and accessible
297
+ curl https://auth.mavenmm.com/.netlify/functions/checkAuth
298
+
299
+ # 3. Check Teamwork OAuth app redirect URIs include your app domain
300
+ ```
301
+
302
+ #### 🍪 Authentication doesn't persist after page refresh
303
+
304
+ **Symptoms**: User logged out after browser refresh
305
+ **Causes**:
306
+ - Cookies not being set properly
307
+ - Incorrect cookie domain
308
+ - Auth service issues
309
+
310
+ **Solutions**:
311
+ ```tsx
312
+ // Check browser dev tools > Application > Cookies
313
+ // Should see 'maven_auth_token' cookie for .mavenmm.com domain
314
+
315
+ // Debug authentication status
316
+ const { user, loading, isAuthenticated } = useTeamworkAuth(authConfig);
317
+ console.log('Auth debug:', { user, loading, isAuthenticated });
318
+ ```
319
+
320
+ #### ⚠️ CORS errors in browser console
321
+
322
+ **Symptoms**: Network errors when calling auth service
323
+ **Causes**:
324
+ - Auth service CORS not configured for your domain
325
+ - Using HTTP instead of HTTPS in production
326
+
327
+ **Solutions**:
328
+ ```bash
329
+ # 1. Ensure your app domain is added to auth service CORS allowlist
330
+ # 2. Use HTTPS in production (required for cookies)
331
+ # 3. Check Origin header matches your domain exactly
332
+ ```
333
+
334
+ #### 🔐 Environment variable issues
335
+
336
+ **Symptoms**: Login process fails with authentication errors
337
+ **Causes**:
338
+ - Missing or incorrect Teamwork OAuth credentials
339
+ - JWT secrets not configured
340
+
341
+ **Solutions**:
342
+ ```bash
343
+ # Auth service needs these environment variables:
344
+ VITE_CLIENT_ID=your_teamwork_client_id
345
+ VITE_CLIENT_SECRET=your_teamwork_client_secret
346
+ VITE_REDIRECT_URI=https://your-app-domain.com
347
+ JWT_KEY=secure_random_jwt_secret
348
+
349
+ # Apps only need auth service URL (no secrets):
350
+ const authConfig = {
351
+ authServiceUrl: 'https://auth.mavenmm.com'
352
+ };
353
+ ```
354
+
355
+ ### Debug Mode
356
+
357
+ Enable detailed logging to troubleshoot issues:
358
+
359
+ ```tsx
360
+ // Temporarily add for debugging
361
+ const authConfig = {
362
+ authServiceUrl: 'https://auth.mavenmm.com',
363
+ cookieDomain: '.mavenmm.com',
364
+ debug: true // Enables console logging
365
+ };
366
+ ```
367
+
368
+ ### Getting Help
369
+
370
+ 1. **Check browser console** for error messages
371
+ 2. **Verify network requests** in browser dev tools
372
+ 3. **Test auth service directly** with curl commands
373
+ 4. **Review documentation**:
374
+ - `INTEGRATION.md` - Step-by-step integration guide
375
+ - `SECURITY.md` - Security best practices
376
+ - `DEPLOYMENT.md` - Auth service deployment
377
+
378
+ ## Project Structure
379
+
380
+ ```
381
+ @mavenmm/teamwork-auth/
382
+ ├── src/ # Frontend package source
383
+ │ ├── hooks/
384
+ │ │ └── useTeamworkAuth.ts
385
+ │ ├── components/
386
+ │ │ └── Login.tsx
387
+ │ └── providers/
388
+ │ └── AuthProvider.tsx
389
+ ├── auth-service/ # Centralized auth service
390
+ │ ├── functions/
391
+ │ │ ├── login.ts
392
+ │ │ ├── logout.ts
393
+ │ │ └── checkAuth.ts
394
+ │ └── middleware/
395
+ ├── test-app/ # Local testing app
396
+ ├── INTEGRATION.md # Integration guide
397
+ ├── SECURITY.md # Security documentation
398
+ └── DEPLOYMENT.md # Deployment guide
399
+ ```
400
+
401
+ ---
402
+
403
+ Made with ❤️ by Maven Marketing
@@ -0,0 +1,4 @@
1
+ import "@teamwork/login-button";
2
+ import type { LoginProps } from "../types";
3
+ export declare function Login({ clientID, redirectURI, clientSecret }?: LoginProps): import("react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=Login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Login.d.ts","sourceRoot":"","sources":["../../src/components/Login.tsx"],"names":[],"mappings":"AAAA,OAAO,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,WAAW,EACX,YAAY,EACb,GAAE,UAAe,2CAwFjB"}
@@ -0,0 +1,16 @@
1
+ import { User } from "../types";
2
+ export interface TeamworkAuthConfig {
3
+ authServiceUrl: string;
4
+ cookieDomain?: string;
5
+ }
6
+ export declare function useTeamworkAuth(config: TeamworkAuthConfig): {
7
+ user: User | null;
8
+ setUser: import("react").Dispatch<import("react").SetStateAction<User | null>>;
9
+ loading: boolean;
10
+ isAuthenticated: boolean;
11
+ login: (code: string) => Promise<{
12
+ twUser: any;
13
+ }>;
14
+ logout: () => Promise<void>;
15
+ };
16
+ //# sourceMappingURL=useTeamworkAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTeamworkAuth.d.ts","sourceRoot":"","sources":["../../src/hooks/useTeamworkAuth.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,IAAI,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,kBAAkB;;;;;kBAa7B,MAAM;;;;EAyMlC"}
@@ -0,0 +1,16 @@
1
+ import { User } from "../types";
2
+ export interface ExternalAuthConfig {
3
+ authServiceUrl?: string;
4
+ cookieDomain?: string;
5
+ }
6
+ export declare function useTeamworkSSO(config?: ExternalAuthConfig): {
7
+ user: User | null;
8
+ setUser: import("react").Dispatch<import("react").SetStateAction<User | null>>;
9
+ loading: boolean;
10
+ isAuthenticated: boolean;
11
+ login: (code: string) => Promise<{
12
+ twUser: any;
13
+ }>;
14
+ logout: () => Promise<void>;
15
+ };
16
+ //# sourceMappingURL=useTeamworkSSO.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTeamworkSSO.d.ts","sourceRoot":"","sources":["../../src/hooks/useTeamworkSSO.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,IAAI,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,cAAc,CAAC,MAAM,GAAE,kBAAuB;;;;;kBA+BjC,MAAM;;;;EAmPlC"}
@@ -0,0 +1,6 @@
1
+ import "./utils/polyfills";
2
+ export { useTeamworkAuth, type TeamworkAuthConfig } from "./hooks/useTeamworkAuth";
3
+ export { Login } from "./components/Login";
4
+ export { default as AuthProvider, useAuthContext, type AuthProviderProps, } from "./providers/AuthProvider";
5
+ export type { User, AuthContextType, LoginResult, } from "./types";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,mBAAmB,CAAC;AAG3B,OAAO,EAAE,eAAe,EAAE,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C,OAAO,EACL,OAAO,IAAI,YAAY,EACvB,cAAc,EACd,KAAK,iBAAiB,GACvB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EACV,IAAI,EACJ,eAAe,EACf,WAAW,GACZ,MAAM,SAAS,CAAC"}
@@ -0,0 +1,311 @@
1
+ import { useState, useEffect, createContext, useRef, useContext } from 'react';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import '@teamwork/login-button';
4
+ import { useLocation } from 'react-router-dom';
5
+
6
+ // Polyfills for Node.js globals in browser environments
7
+ // This helps resolve buffer and process dependency issues
8
+ // Polyfill for process global
9
+ if (typeof process === "undefined") {
10
+ globalThis.process = {
11
+ env: {},
12
+ nextTick: (fn) => setTimeout(fn, 0),
13
+ version: "",
14
+ versions: {},
15
+ platform: "browser",
16
+ browser: true,
17
+ };
18
+ }
19
+ // Polyfill for Buffer global
20
+ if (typeof Buffer === "undefined") {
21
+ try {
22
+ const { Buffer } = require("buffer");
23
+ globalThis.Buffer = Buffer;
24
+ }
25
+ catch (e) {
26
+ // If buffer package is not available, provide a minimal polyfill
27
+ globalThis.Buffer = {
28
+ from: (data) => new Uint8Array(data),
29
+ isBuffer: () => false,
30
+ };
31
+ }
32
+ }
33
+
34
+ function useTeamworkAuth(config) {
35
+ if (!config.authServiceUrl) {
36
+ throw new Error('TeamworkAuth: authServiceUrl is required. Please provide the URL of your auth service (e.g., "https://auth.yourcompany.com")');
37
+ }
38
+ const authServiceUrl = config.authServiceUrl;
39
+ const [user, setUser] = useState(null);
40
+ const [loading, setLoading] = useState(true);
41
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
42
+ const login = async (code) => {
43
+ try {
44
+ const options = {
45
+ method: "POST",
46
+ headers: {
47
+ "Content-Type": "application/json",
48
+ "code": code,
49
+ },
50
+ credentials: "include",
51
+ };
52
+ // Record the code to prevent reuse
53
+ localStorage.setItem("maven_sso_code", JSON.stringify(code));
54
+ const res = await fetch(`${authServiceUrl}/.netlify/functions/login`, options);
55
+ if (!res.ok) {
56
+ let errorDetails;
57
+ try {
58
+ errorDetails = await res.json();
59
+ }
60
+ catch {
61
+ errorDetails = await res.text();
62
+ }
63
+ throw new Error(`Login failed with status: ${res.status}`);
64
+ }
65
+ const data = await res.json();
66
+ const { twUser } = data;
67
+ setUser(twUser);
68
+ setIsAuthenticated(true);
69
+ // Save user data to localStorage
70
+ localStorage.setItem("maven_sso_user", JSON.stringify(twUser));
71
+ // Clean up URL by removing OAuth code parameter
72
+ cleanUpUrl();
73
+ return { twUser };
74
+ }
75
+ catch (err) {
76
+ throw new Error("Failed to log in");
77
+ }
78
+ };
79
+ const cleanUpUrl = () => {
80
+ try {
81
+ const url = new URL(window.location.href);
82
+ // OAuth parameters that should be cleaned up after successful auth
83
+ const oauthParams = ['code', 'state', 'client_id', 'redirect_uri', 'scope', 'response_type'];
84
+ let hasOAuthParams = false;
85
+ // Check if any OAuth params exist
86
+ oauthParams.forEach(param => {
87
+ if (url.searchParams.has(param)) {
88
+ hasOAuthParams = true;
89
+ }
90
+ });
91
+ if (hasOAuthParams) {
92
+ // Remove all OAuth parameters
93
+ oauthParams.forEach(param => {
94
+ url.searchParams.delete(param);
95
+ });
96
+ // Update URL without page reload
97
+ window.history.replaceState({}, document.title, url.toString());
98
+ }
99
+ }
100
+ catch (error) {
101
+ // Silently fail - URL cleanup is not critical
102
+ }
103
+ };
104
+ const logout = async () => {
105
+ try {
106
+ // Call external auth service logout endpoint
107
+ await fetch(`${authServiceUrl}/.netlify/functions/logout`, {
108
+ method: "GET",
109
+ credentials: "include",
110
+ });
111
+ // Clear all user data
112
+ setUser(null);
113
+ setIsAuthenticated(false);
114
+ // Clear localStorage
115
+ localStorage.removeItem("maven_sso_user");
116
+ localStorage.removeItem("maven_sso_code");
117
+ // Clear cookies - the auth service handles domain cookies
118
+ document.cookie =
119
+ "maven_auth_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT";
120
+ // For non-localhost environments, also clear with configured domain
121
+ if (window.location.hostname !== "localhost" && config.cookieDomain) {
122
+ document.cookie = `maven_auth_token=; path=/; domain=${config.cookieDomain}; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
123
+ }
124
+ }
125
+ catch (error) {
126
+ console.error("Logout error:", error);
127
+ // Still clear local state even if API call fails
128
+ setUser(null);
129
+ setIsAuthenticated(false);
130
+ localStorage.removeItem("maven_sso_user");
131
+ }
132
+ };
133
+ useEffect(() => {
134
+ const checkAuth = async () => {
135
+ try {
136
+ // Make API call to validate auth state with external auth service
137
+ const response = await fetch(`${authServiceUrl}/.netlify/functions/checkAuth`, {
138
+ method: "GET",
139
+ credentials: "include",
140
+ });
141
+ if (response.ok) {
142
+ const contentType = response.headers.get("content-type");
143
+ if (!contentType || !contentType.includes("application/json")) {
144
+ setIsAuthenticated(false);
145
+ setUser(null);
146
+ localStorage.removeItem("maven_sso_user");
147
+ return;
148
+ }
149
+ const data = await response.json();
150
+ if (data.authenticated === true) {
151
+ setIsAuthenticated(true);
152
+ // Clean up URL since we're authenticated via cookie
153
+ cleanUpUrl();
154
+ // Check if we already have user data in localStorage
155
+ const prevUser = localStorage.getItem("maven_sso_user");
156
+ if (prevUser) {
157
+ try {
158
+ const userData = JSON.parse(prevUser);
159
+ setUser(userData);
160
+ }
161
+ catch (error) {
162
+ localStorage.removeItem("maven_sso_user");
163
+ // Create basic user as fallback
164
+ const basicUser = {
165
+ id: data.userId || data._id || "temp-user",
166
+ firstName: "Teamwork",
167
+ lastName: "User",
168
+ email: "user@teamwork.example",
169
+ avatar: "",
170
+ company: {
171
+ id: 1,
172
+ name: "Teamwork",
173
+ logo: "",
174
+ },
175
+ };
176
+ localStorage.setItem("maven_sso_user", JSON.stringify(basicUser));
177
+ setUser(basicUser);
178
+ }
179
+ }
180
+ else {
181
+ // Create a basic user object since we don't have one
182
+ const basicUser = {
183
+ id: data.userId || data._id || "temp-user",
184
+ firstName: "Teamwork",
185
+ lastName: "User",
186
+ email: "user@teamwork.example",
187
+ avatar: "",
188
+ company: {
189
+ id: 1,
190
+ name: "Teamwork",
191
+ logo: "",
192
+ },
193
+ };
194
+ localStorage.setItem("maven_sso_user", JSON.stringify(basicUser));
195
+ setUser(basicUser);
196
+ }
197
+ }
198
+ else {
199
+ setIsAuthenticated(false);
200
+ setUser(null);
201
+ localStorage.removeItem("maven_sso_user");
202
+ }
203
+ }
204
+ else {
205
+ setIsAuthenticated(false);
206
+ setUser(null);
207
+ localStorage.removeItem("maven_sso_user");
208
+ }
209
+ }
210
+ catch (error) {
211
+ setIsAuthenticated(false);
212
+ setUser(null);
213
+ localStorage.removeItem("maven_sso_user");
214
+ }
215
+ finally {
216
+ setLoading(false);
217
+ }
218
+ };
219
+ // Always validate with server - httpOnly cookies are handled automatically by browser
220
+ checkAuth();
221
+ }, [authServiceUrl]); // Add authServiceUrl as dependency
222
+ return { user, setUser, loading, isAuthenticated, login, logout };
223
+ }
224
+
225
+ function Login({ clientID, redirectURI, clientSecret } = {}) {
226
+ // For production npm package, we require props to be passed
227
+ // Environment variables are only for development/testing
228
+ const TEAMWORK_CLIENT_ID = clientID;
229
+ const TEAMWORK_REDIRECT_URI = redirectURI;
230
+ const TEAMWORK_CLIENT_SECRET = clientSecret;
231
+ // Check if required props are available
232
+ if (!TEAMWORK_CLIENT_ID || !TEAMWORK_REDIRECT_URI) {
233
+ const missingVars = [];
234
+ if (!TEAMWORK_CLIENT_ID)
235
+ missingVars.push('clientID');
236
+ if (!TEAMWORK_REDIRECT_URI)
237
+ missingVars.push('redirectURI');
238
+ return (jsxs("div", { style: {
239
+ padding: '20px',
240
+ border: '2px solid #f44336',
241
+ borderRadius: '8px',
242
+ backgroundColor: '#ffebee',
243
+ color: '#c62828'
244
+ }, children: [jsx("h3", { children: "\u26A0\uFE0F Login Configuration Error" }), jsx("p", { children: "Missing required Teamwork OAuth configuration:" }), jsx("ul", { children: missingVars.map(varName => (jsx("li", { children: jsx("strong", { children: varName }) }, varName))) }), jsx("p", { children: "Either pass as props or set environment variables:" }), jsx("pre", { style: { background: '#f5f5f5', padding: '10px', fontSize: '12px' }, children: `// As props:
245
+ <Login
246
+ clientID="your_teamwork_client_id"
247
+ redirectURI="https://your-app.com"
248
+ />
249
+
250
+ // Or as environment variables:
251
+ VITE_TEAMWORK_CLIENT_ID=your_teamwork_client_id
252
+ VITE_TEAMWORK_REDIRECT_URI=https://your-app.com` })] }));
253
+ }
254
+ return (jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%' }, children: [jsx("teamwork-login-button", { redirectURI: TEAMWORK_REDIRECT_URI, clientID: TEAMWORK_CLIENT_ID, icon: "false", color: "slate", size: "medium", borders: "default" }), TEAMWORK_CLIENT_SECRET && (jsxs("div", { style: {
255
+ marginTop: '20px',
256
+ padding: '15px',
257
+ backgroundColor: '#f5f5f5',
258
+ border: '1px solid #ddd',
259
+ borderRadius: '5px',
260
+ fontSize: '12px',
261
+ fontFamily: 'monospace'
262
+ }, children: [jsx("h4", { children: "\uD83D\uDD27 Debug Info:" }), jsx("table", { children: jsxs("tbody", { children: [jsxs("tr", { children: [jsx("td", { style: { paddingRight: '10px' }, children: "Redirect URI:" }), jsx("td", { children: TEAMWORK_REDIRECT_URI })] }), jsxs("tr", { children: [jsx("td", { style: { paddingRight: '10px' }, children: "Client ID:" }), jsx("td", { children: TEAMWORK_CLIENT_ID })] }), jsxs("tr", { children: [jsx("td", { style: { paddingRight: '10px' }, children: "Client Secret:" }), jsx("td", { children: "***hidden***" })] })] }) })] }))] }));
263
+ }
264
+
265
+ const AuthContext = createContext({});
266
+ // Hook to use the auth context
267
+ function useAuthContext() {
268
+ const context = useContext(AuthContext);
269
+ if (!context) {
270
+ throw new Error("useAuthContext must be used within an AuthProvider");
271
+ }
272
+ return context;
273
+ }
274
+ function AuthProvider({ children, authConfig, }) {
275
+ const { user, setUser, logout, loading, isAuthenticated, login } = useTeamworkAuth(authConfig);
276
+ // Get the code from the URL for the teamwork login flow
277
+ const location = useLocation();
278
+ const params = location.search;
279
+ const code = new URLSearchParams(params).get("code");
280
+ const value = { user, logout, loading, isAuthenticated };
281
+ // Use refs to prevent infinite loops
282
+ const lastCodeRef = useRef(null);
283
+ // Handle OAuth callback code
284
+ useEffect(() => {
285
+ // Skip if still loading
286
+ if (loading)
287
+ return;
288
+ const usedCode = localStorage.getItem("prevCode");
289
+ const handleLogin = async (code) => {
290
+ try {
291
+ const result = await login(code);
292
+ }
293
+ catch (err) {
294
+ // Handle login error silently or with user-facing error handling
295
+ }
296
+ };
297
+ // Process OAuth callback code if present
298
+ if (code && !user) {
299
+ // React.StrictMode is causing this provider to render twice on load, teamwork will return an error on the second login call
300
+ // Add a prevCode check here to make sure we don't double request /api/login with the same code
301
+ if (usedCode !== code && lastCodeRef.current !== code) {
302
+ lastCodeRef.current = code;
303
+ handleLogin(code);
304
+ }
305
+ }
306
+ }, [code, user, loading, login]);
307
+ return jsx(AuthContext.Provider, { value: value, children: children });
308
+ }
309
+
310
+ export { AuthProvider, Login, useAuthContext, useTeamworkAuth };
311
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/utils/polyfills.ts","../src/hooks/useTeamworkAuth.ts","../src/components/Login.tsx","../src/providers/AuthProvider.tsx"],"sourcesContent":[null,null,null,null],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type TeamworkAuthConfig } from "../hooks/useTeamworkAuth";
2
+ import type { AuthContextType } from "../types";
3
+ export declare const AuthContext: import("react").Context<AuthContextType>;
4
+ export declare function useAuthContext(): AuthContextType;
5
+ export interface AuthProviderProps {
6
+ children: React.ReactNode;
7
+ authConfig: TeamworkAuthConfig;
8
+ }
9
+ export default function AuthProvider({ children, authConfig, }: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=AuthProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../src/providers/AuthProvider.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,KAAK,EAAQ,eAAe,EAAE,MAAM,UAAU,CAAC;AAEtD,eAAO,MAAM,WAAW,0CAAuC,CAAC;AAGhE,wBAAgB,cAAc,oBAM7B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,EAAE,kBAAkB,CAAC;CAChC;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,QAAQ,EACR,UAAU,GACX,EAAE,iBAAiB,2CAyCnB"}
@@ -0,0 +1,7 @@
1
+ declare const localStorageMock: {
2
+ getItem: jest.Mock<any, any, any>;
3
+ setItem: jest.Mock<any, any, any>;
4
+ removeItem: jest.Mock<any, any, any>;
5
+ clear: jest.Mock<any, any, any>;
6
+ };
7
+ //# sourceMappingURL=setupTests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupTests.d.ts","sourceRoot":"","sources":["../src/setupTests.ts"],"names":[],"mappings":"AAeA,QAAA,MAAM,gBAAgB;;;;;CAKrB,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface User {
2
+ id: string;
3
+ firstName: string;
4
+ lastName: string;
5
+ email: string;
6
+ avatar: string;
7
+ company: {
8
+ id: number;
9
+ name: string;
10
+ logo: string;
11
+ };
12
+ }
13
+ export interface AuthContextType {
14
+ user: User | null;
15
+ logout: () => Promise<void>;
16
+ loading: boolean;
17
+ isAuthenticated: boolean;
18
+ }
19
+ export interface LoginResult {
20
+ success: boolean;
21
+ user?: User;
22
+ error?: string;
23
+ }
24
+ export interface LoginProps {
25
+ clientID?: string;
26
+ redirectURI?: string;
27
+ clientSecret?: string;
28
+ }
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAGD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAGD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB"}
@@ -0,0 +1,3 @@
1
+ export declare function getEnvVar(key: string): string | undefined;
2
+ export declare function isDev(): boolean;
3
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AACA,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgCzD;AAGD,wBAAgB,KAAK,IAAI,OAAO,CAgC/B"}
@@ -0,0 +1,2 @@
1
+ export declare function ensurePolyfills(): boolean;
2
+ //# sourceMappingURL=polyfills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfills.d.ts","sourceRoot":"","sources":["../../src/utils/polyfills.ts"],"names":[],"mappings":"AA8BA,wBAAgB,eAAe,YAG9B"}
package/package.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "@mavenmm/teamwork-auth",
3
+ "version": "2.0.0",
4
+ "description": "Centralized Teamwork SSO authentication system for React applications with zero backend code required",
5
+ "type": "module",
6
+ "main": "dist/index.esm.js",
7
+ "module": "dist/index.esm.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.esm.js",
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.esm.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "CHANGELOG.md"
20
+ ],
21
+ "scripts": {
22
+ "build": "rollup -c",
23
+ "build:watch": "rollup -c -w",
24
+ "dev": "npm run build:watch",
25
+ "test": "jest",
26
+ "test:watch": "jest --watch",
27
+ "type-check": "tsc --noEmit",
28
+ "prepare": "npm run build",
29
+ "prepublishOnly": "npm run type-check && npm run build",
30
+ "test:local": "npm run build && concurrently \"npm run test:auth-service\" \"npm run test:app\"",
31
+ "test:auth-service": "cd auth-service && npm install && npm run dev",
32
+ "test:app": "cd test-app && npm install && npm run dev",
33
+ "test:setup": "npm run build && cd test-app && npm install"
34
+ },
35
+ "keywords": [
36
+ "maven-marketing",
37
+ "sso",
38
+ "authentication",
39
+ "react",
40
+ "netlify",
41
+ "teamwork",
42
+ "oauth",
43
+ "typescript"
44
+ ],
45
+ "author": "Maven Marketing",
46
+ "license": "ISC",
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/mavenmm/teamwork-auth.git"
53
+ },
54
+ "bugs": {
55
+ "url": "https://github.com/mavenmm/teamwork-auth/issues"
56
+ },
57
+ "homepage": "https://github.com/mavenmm/teamwork-auth#readme",
58
+ "peerDependencies": {
59
+ "react": ">=16.8.0",
60
+ "react-dom": ">=16.8.0",
61
+ "react-router-dom": ">=6.0.0"
62
+ },
63
+ "devDependencies": {
64
+ "@rollup/plugin-commonjs": "^25.0.0",
65
+ "@rollup/plugin-node-resolve": "^15.2.0",
66
+ "@rollup/plugin-typescript": "^11.1.0",
67
+ "@testing-library/jest-dom": "^6.0.0",
68
+ "@testing-library/react": "^14.0.0",
69
+ "@types/jest": "^29.5.0",
70
+ "@types/node": "^20.0.0",
71
+ "@types/react": "^18.2.0",
72
+ "@types/react-dom": "^18.2.0",
73
+ "concurrently": "^8.2.0",
74
+ "jest": "^29.6.0",
75
+ "jest-environment-jsdom": "^29.6.0",
76
+ "rollup": "^3.28.0",
77
+ "rollup-plugin-peer-deps-external": "^2.2.4",
78
+ "ts-jest": "^29.1.0",
79
+ "tslib": "^2.6.0",
80
+ "typescript": "^5.1.0"
81
+ },
82
+ "dependencies": {
83
+ "@teamwork/login-button": "^1.0.1",
84
+ "buffer": "^6.0.0",
85
+ "process": "^0.11.10"
86
+ }
87
+ }