chadstart 1.0.0 → 1.0.2

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/docs/oauth.md ADDED
@@ -0,0 +1,869 @@
1
+ ---
2
+ id: oauth
3
+ title: OAuth / Social Login
4
+ description: Add "Login with Google", "Login with GitHub", and 200+ other OAuth providers to your ChadStart app in minutes.
5
+ ---
6
+
7
+ # OAuth / Social Login
8
+
9
+ ## Introduction
10
+
11
+ ChadStart supports **OAuth / Social Login** via the [grant](https://www.npmjs.com/package/grant) library, giving you access to **200+ OAuth providers** out of the box. Users can sign in with their existing accounts on platforms like Google, GitHub, Facebook, Discord, and many more — no custom OAuth flow code required.
12
+
13
+ When a user logs in via an OAuth provider, ChadStart will:
14
+
15
+ 1. Redirect the user to the provider's authorization page.
16
+ 2. Handle the callback and extract the user's profile.
17
+ 3. Find an existing user by email or create a new one in your authenticable entity.
18
+ 4. Return a **JWT token** (same format as email/password login).
19
+
20
+ !!! info
21
+ OAuth secrets (**client IDs** and **client secrets**) must always be stored in environment variables — never in your YAML config file.
22
+
23
+ ## Quick Start
24
+
25
+ ### 1. Register your app with the provider
26
+
27
+ Visit the provider's developer console and create an OAuth application. You will receive a **Client ID** (key) and **Client Secret**.
28
+
29
+ Set the **Redirect URI** (callback URL) to:
30
+
31
+ ```
32
+ https://your-domain.com/connect/<provider>/callback
33
+ ```
34
+
35
+ For local development:
36
+
37
+ ```
38
+ http://localhost:3000/connect/<provider>/callback
39
+ ```
40
+
41
+ ### 2. Set environment variables
42
+
43
+ ```bash
44
+ # .env
45
+ OAUTH_GOOGLE_KEY=your-google-client-id
46
+ OAUTH_GOOGLE_SECRET=your-google-client-secret
47
+ ```
48
+
49
+ The pattern is always `OAUTH_<PROVIDER>_KEY` and `OAUTH_<PROVIDER>_SECRET` where `<PROVIDER>` is the provider name in **UPPERCASE**.
50
+
51
+ ### 3. Add OAuth config to your YAML
52
+
53
+ ```yaml
54
+ oauth:
55
+ entity: User # Which authenticable entity to use
56
+ successRedirect: /dashboard # Where to redirect after login
57
+ providers:
58
+ google:
59
+ scope:
60
+ - openid
61
+ - email
62
+ - profile
63
+ ```
64
+
65
+ ### 4. Add a login button
66
+
67
+ ```html
68
+ <a href="/connect/google">Login with Google</a>
69
+ ```
70
+
71
+ That's it! ChadStart handles the entire OAuth dance automatically.
72
+
73
+ ## Configuration Reference
74
+
75
+ The `oauth` section in your YAML config supports the following options:
76
+
77
+ ```yaml
78
+ oauth:
79
+ # Target authenticable entity for OAuth users.
80
+ # Default: first authenticable entity in your config.
81
+ entity: User
82
+
83
+ # Redirect URL after successful login (?token=JWT is appended).
84
+ # If omitted, returns JSON: { token, user }
85
+ successRedirect: /dashboard
86
+
87
+ # Redirect URL on error (?error=message is appended).
88
+ # If omitted, returns JSON: { error }
89
+ errorRedirect: /login?error=true
90
+
91
+ # Default settings for all providers
92
+ defaults:
93
+ transport: querystring
94
+
95
+ # Provider configurations
96
+ providers:
97
+ google:
98
+ scope:
99
+ - openid
100
+ - email
101
+ - profile
102
+ ```
103
+
104
+ ### Provider Options
105
+
106
+ Each provider entry supports these options:
107
+
108
+ | Option | Type | Description |
109
+ |--------|------|-------------|
110
+ | `scope` | `string` or `string[]` | OAuth scopes to request |
111
+ | `callback` | `string` | Custom callback URL (default: `/api/auth/oauth/callback`) |
112
+ | `custom_params` | `object` | Extra query parameters for the authorization URL |
113
+ | `subdomain` | `string` | Required by some providers (e.g., Shopify) |
114
+ | `nonce` | `boolean` | Enable nonce generation (some OIDC providers) |
115
+ | `pkce` | `boolean` | Enable PKCE for enhanced security |
116
+ | `response` | `string[]` | Data to include in callback (e.g., `['tokens', 'profile']`) |
117
+
118
+ ### Environment Variables
119
+
120
+ | Variable | Description |
121
+ |----------|-------------|
122
+ | `OAUTH_<PROVIDER>_KEY` | Client/App ID for the provider |
123
+ | `OAUTH_<PROVIDER>_SECRET` | Client/App Secret for the provider |
124
+ | `BASE_URL` | Your application's public URL (used to build redirect URIs) |
125
+
126
+ ## API Endpoints
127
+
128
+ Once OAuth is configured, the following endpoints are available:
129
+
130
+ | Method | Path | Description |
131
+ |--------|------|-------------|
132
+ | `GET` | `/connect/<provider>` | Initiates the OAuth flow (redirects to provider) |
133
+ | `GET` | `/api/auth/oauth/callback` | OAuth callback (handled automatically) |
134
+ | `GET` | `/api/auth/oauth/providers` | Lists configured provider names |
135
+
136
+ ### Example: List providers
137
+
138
+ ```http
139
+ GET /api/auth/oauth/providers
140
+ ```
141
+
142
+ ```json
143
+ {
144
+ "providers": ["google", "github", "discord"]
145
+ }
146
+ ```
147
+
148
+ ## Top 20 Provider Setup Guides
149
+
150
+ Below are setup guides for the 20 most popular OAuth providers. For each one, you need to:
151
+
152
+ 1. Create an app on the provider's developer portal
153
+ 2. Set the redirect URI to `https://your-domain.com/connect/<provider>/callback`
154
+ 3. Add the client ID and secret to your `.env` file
155
+ 4. Add the provider to your YAML config
156
+
157
+ ---
158
+
159
+ ### 1. Google
160
+
161
+ **Developer Console:** [console.cloud.google.com](https://console.cloud.google.com/apis/credentials)
162
+
163
+ 1. Create a project → **APIs & Services** → **Credentials** → **Create OAuth Client ID**
164
+ 2. Set application type to **Web application**
165
+ 3. Add authorized redirect URI: `http://localhost:3000/connect/google/callback`
166
+
167
+ ```bash
168
+ OAUTH_GOOGLE_KEY=your-client-id.apps.googleusercontent.com
169
+ OAUTH_GOOGLE_SECRET=your-client-secret
170
+ ```
171
+
172
+ ```yaml
173
+ oauth:
174
+ providers:
175
+ google:
176
+ scope:
177
+ - openid
178
+ - email
179
+ - profile
180
+ custom_params:
181
+ access_type: offline # Get a refresh token
182
+ ```
183
+
184
+ ---
185
+
186
+ ### 2. GitHub
187
+
188
+ **Developer Settings:** [github.com/settings/developers](https://github.com/settings/developers)
189
+
190
+ 1. Go to **Settings** → **Developer Settings** → **OAuth Apps** → **New OAuth App**
191
+ 2. Set the callback URL: `http://localhost:3000/connect/github/callback`
192
+
193
+ ```bash
194
+ OAUTH_GITHUB_KEY=your-github-client-id
195
+ OAUTH_GITHUB_SECRET=your-github-client-secret
196
+ ```
197
+
198
+ ```yaml
199
+ oauth:
200
+ providers:
201
+ github:
202
+ scope:
203
+ - user:email
204
+ - read:user
205
+ ```
206
+
207
+ ---
208
+
209
+ ### 3. Facebook
210
+
211
+ **Developer Portal:** [developers.facebook.com](https://developers.facebook.com/apps/)
212
+
213
+ 1. Create a new app → **Facebook Login** → **Settings**
214
+ 2. Add valid redirect URI: `http://localhost:3000/connect/facebook/callback`
215
+
216
+ ```bash
217
+ OAUTH_FACEBOOK_KEY=your-facebook-app-id
218
+ OAUTH_FACEBOOK_SECRET=your-facebook-app-secret
219
+ ```
220
+
221
+ ```yaml
222
+ oauth:
223
+ providers:
224
+ facebook:
225
+ scope:
226
+ - email
227
+ - public_profile
228
+ ```
229
+
230
+ ---
231
+
232
+ ### 4. Discord
233
+
234
+ **Developer Portal:** [discord.com/developers](https://discord.com/developers/applications)
235
+
236
+ 1. Create a new application → **OAuth2** → **General**
237
+ 2. Add redirect: `http://localhost:3000/connect/discord/callback`
238
+
239
+ ```bash
240
+ OAUTH_DISCORD_KEY=your-discord-client-id
241
+ OAUTH_DISCORD_SECRET=your-discord-client-secret
242
+ ```
243
+
244
+ ```yaml
245
+ oauth:
246
+ providers:
247
+ discord:
248
+ scope:
249
+ - identify
250
+ - email
251
+ ```
252
+
253
+ ---
254
+
255
+ ### 5. Apple
256
+
257
+ **Developer Portal:** [developer.apple.com](https://developer.apple.com/account/resources/identifiers/list/serviceId)
258
+
259
+ 1. Register a **Services ID** and configure **Sign In with Apple**
260
+ 2. Set the redirect URL: `https://your-domain.com/connect/apple/callback`
261
+
262
+ !!! warning
263
+ Apple requires HTTPS even for development.
264
+
265
+ ```bash
266
+ OAUTH_APPLE_KEY=your-apple-services-id
267
+ OAUTH_APPLE_SECRET=your-apple-client-secret
268
+ ```
269
+
270
+ ```yaml
271
+ oauth:
272
+ providers:
273
+ apple:
274
+ scope:
275
+ - name
276
+ - email
277
+ nonce: true
278
+ ```
279
+
280
+ ---
281
+
282
+ ### 6. Microsoft
283
+
284
+ **Azure Portal:** [portal.azure.com](https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)
285
+
286
+ 1. Register a new application → **Authentication** → **Add a platform** → **Web**
287
+ 2. Set redirect URI: `http://localhost:3000/connect/microsoft/callback`
288
+
289
+ ```bash
290
+ OAUTH_MICROSOFT_KEY=your-application-client-id
291
+ OAUTH_MICROSOFT_SECRET=your-client-secret-value
292
+ ```
293
+
294
+ ```yaml
295
+ oauth:
296
+ providers:
297
+ microsoft:
298
+ scope:
299
+ - openid
300
+ - email
301
+ - profile
302
+ ```
303
+
304
+ ---
305
+
306
+ ### 7. Twitter (X)
307
+
308
+ **Developer Portal:** [developer.twitter.com](https://developer.twitter.com/en/portal/projects-and-apps)
309
+
310
+ 1. Create a project and app → **User authentication settings** → **Edit**
311
+ 2. Set the callback URL: `http://localhost:3000/connect/twitter/callback`
312
+
313
+ ```bash
314
+ OAUTH_TWITTER_KEY=your-twitter-api-key
315
+ OAUTH_TWITTER_SECRET=your-twitter-api-secret
316
+ ```
317
+
318
+ ```yaml
319
+ oauth:
320
+ providers:
321
+ twitter:
322
+ scope:
323
+ - users.read
324
+ - tweet.read
325
+ ```
326
+
327
+ ---
328
+
329
+ ### 8. LinkedIn
330
+
331
+ **Developer Portal:** [linkedin.com/developers](https://www.linkedin.com/developers/apps)
332
+
333
+ 1. Create an app → **Auth** → add redirect URL: `http://localhost:3000/connect/linkedin/callback`
334
+
335
+ ```bash
336
+ OAUTH_LINKEDIN_KEY=your-linkedin-client-id
337
+ OAUTH_LINKEDIN_SECRET=your-linkedin-client-secret
338
+ ```
339
+
340
+ ```yaml
341
+ oauth:
342
+ providers:
343
+ linkedin:
344
+ scope:
345
+ - openid
346
+ - email
347
+ - profile
348
+ ```
349
+
350
+ ---
351
+
352
+ ### 9. Spotify
353
+
354
+ **Developer Dashboard:** [developer.spotify.com/dashboard](https://developer.spotify.com/dashboard)
355
+
356
+ 1. Create an app → **Edit Settings** → add redirect URI: `http://localhost:3000/connect/spotify/callback`
357
+
358
+ ```bash
359
+ OAUTH_SPOTIFY_KEY=your-spotify-client-id
360
+ OAUTH_SPOTIFY_SECRET=your-spotify-client-secret
361
+ ```
362
+
363
+ ```yaml
364
+ oauth:
365
+ providers:
366
+ spotify:
367
+ scope:
368
+ - user-read-email
369
+ - user-read-private
370
+ ```
371
+
372
+ ---
373
+
374
+ ### 10. Slack
375
+
376
+ **API Portal:** [api.slack.com/apps](https://api.slack.com/apps)
377
+
378
+ 1. Create an app → **OAuth & Permissions** → add redirect URL: `http://localhost:3000/connect/slack/callback`
379
+
380
+ ```bash
381
+ OAUTH_SLACK_KEY=your-slack-client-id
382
+ OAUTH_SLACK_SECRET=your-slack-client-secret
383
+ ```
384
+
385
+ ```yaml
386
+ oauth:
387
+ providers:
388
+ slack:
389
+ scope:
390
+ - openid
391
+ - email
392
+ - profile
393
+ ```
394
+
395
+ ---
396
+
397
+ ### 11. GitLab
398
+
399
+ **Application Settings:** [gitlab.com/-/profile/applications](https://gitlab.com/-/profile/applications)
400
+
401
+ 1. Create a new application with redirect URI: `http://localhost:3000/connect/gitlab/callback`
402
+
403
+ ```bash
404
+ OAUTH_GITLAB_KEY=your-gitlab-application-id
405
+ OAUTH_GITLAB_SECRET=your-gitlab-secret
406
+ ```
407
+
408
+ ```yaml
409
+ oauth:
410
+ providers:
411
+ gitlab:
412
+ scope:
413
+ - read_user
414
+ - email
415
+ ```
416
+
417
+ ---
418
+
419
+ ### 12. Bitbucket
420
+
421
+ **App Passwords:** [bitbucket.org/account/settings/app-passwords/](https://bitbucket.org/account/settings/)
422
+
423
+ 1. Go to **Settings** → **OAuth consumers** → **Add consumer**
424
+ 2. Set callback URL: `http://localhost:3000/connect/bitbucket/callback`
425
+
426
+ ```bash
427
+ OAUTH_BITBUCKET_KEY=your-bitbucket-key
428
+ OAUTH_BITBUCKET_SECRET=your-bitbucket-secret
429
+ ```
430
+
431
+ ```yaml
432
+ oauth:
433
+ providers:
434
+ bitbucket:
435
+ scope:
436
+ - account
437
+ - email
438
+ ```
439
+
440
+ ---
441
+
442
+ ### 13. Twitch
443
+
444
+ **Developer Console:** [dev.twitch.tv/console/apps](https://dev.twitch.tv/console/apps)
445
+
446
+ 1. Register a new application with redirect URL: `http://localhost:3000/connect/twitch/callback`
447
+
448
+ ```bash
449
+ OAUTH_TWITCH_KEY=your-twitch-client-id
450
+ OAUTH_TWITCH_SECRET=your-twitch-client-secret
451
+ ```
452
+
453
+ ```yaml
454
+ oauth:
455
+ providers:
456
+ twitch:
457
+ scope:
458
+ - user:read:email
459
+ ```
460
+
461
+ ---
462
+
463
+ ### 14. Dropbox
464
+
465
+ **App Console:** [dropbox.com/developers/apps](https://www.dropbox.com/developers/apps)
466
+
467
+ 1. Create app → **Settings** → add redirect URI: `http://localhost:3000/connect/dropbox/callback`
468
+
469
+ ```bash
470
+ OAUTH_DROPBOX_KEY=your-dropbox-app-key
471
+ OAUTH_DROPBOX_SECRET=your-dropbox-app-secret
472
+ ```
473
+
474
+ ```yaml
475
+ oauth:
476
+ providers:
477
+ dropbox:
478
+ scope:
479
+ - account_info.read
480
+ ```
481
+
482
+ ---
483
+
484
+ ### 15. Shopify
485
+
486
+ **Partners Dashboard:** [partners.shopify.com](https://partners.shopify.com/)
487
+
488
+ 1. Create an app → **App setup** → add redirect URL: `http://localhost:3000/connect/shopify/callback`
489
+
490
+ ```bash
491
+ OAUTH_SHOPIFY_KEY=your-shopify-api-key
492
+ OAUTH_SHOPIFY_SECRET=your-shopify-api-secret
493
+ ```
494
+
495
+ ```yaml
496
+ oauth:
497
+ providers:
498
+ shopify:
499
+ subdomain: your-store # Your Shopify store subdomain
500
+ scope:
501
+ - read_products
502
+ - read_customers
503
+ ```
504
+
505
+ ---
506
+
507
+ ### 16. Notion
508
+
509
+ **Integrations:** [notion.so/my-integrations](https://www.notion.so/my-integrations)
510
+
511
+ 1. Create a new integration → **OAuth** → set redirect URI: `http://localhost:3000/connect/notion/callback`
512
+
513
+ ```bash
514
+ OAUTH_NOTION_KEY=your-notion-client-id
515
+ OAUTH_NOTION_SECRET=your-notion-client-secret
516
+ ```
517
+
518
+ ```yaml
519
+ oauth:
520
+ providers:
521
+ notion:
522
+ scope: []
523
+ ```
524
+
525
+ ---
526
+
527
+ ### 17. Zoom
528
+
529
+ **Marketplace:** [marketplace.zoom.us](https://marketplace.zoom.us/develop/create)
530
+
531
+ 1. Create an OAuth app → add redirect URL: `http://localhost:3000/connect/zoom/callback`
532
+
533
+ ```bash
534
+ OAUTH_ZOOM_KEY=your-zoom-client-id
535
+ OAUTH_ZOOM_SECRET=your-zoom-client-secret
536
+ ```
537
+
538
+ ```yaml
539
+ oauth:
540
+ providers:
541
+ zoom:
542
+ scope:
543
+ - user:read
544
+ ```
545
+
546
+ ---
547
+
548
+ ### 18. Stripe
549
+
550
+ **Dashboard:** [dashboard.stripe.com](https://dashboard.stripe.com/settings/connect)
551
+
552
+ 1. Go to **Settings** → **Connect** → set redirect URI: `http://localhost:3000/connect/stripe/callback`
553
+
554
+ ```bash
555
+ OAUTH_STRIPE_KEY=your-stripe-client-id
556
+ OAUTH_STRIPE_SECRET=your-stripe-api-secret-key
557
+ ```
558
+
559
+ ```yaml
560
+ oauth:
561
+ providers:
562
+ stripe:
563
+ scope:
564
+ - read_write
565
+ ```
566
+
567
+ ---
568
+
569
+ ### 19. Reddit
570
+
571
+ **App Preferences:** [reddit.com/prefs/apps](https://www.reddit.com/prefs/apps)
572
+
573
+ 1. Create a new app (select **web app**) → set redirect URI: `http://localhost:3000/connect/reddit/callback`
574
+
575
+ ```bash
576
+ OAUTH_REDDIT_KEY=your-reddit-client-id
577
+ OAUTH_REDDIT_SECRET=your-reddit-client-secret
578
+ ```
579
+
580
+ ```yaml
581
+ oauth:
582
+ providers:
583
+ reddit:
584
+ scope:
585
+ - identity
586
+ ```
587
+
588
+ ---
589
+
590
+ ### 20. Auth0
591
+
592
+ **Dashboard:** [manage.auth0.com](https://manage.auth0.com/)
593
+
594
+ 1. Create a new application → **Settings** → set callback URL: `http://localhost:3000/connect/auth0/callback`
595
+
596
+ ```bash
597
+ OAUTH_AUTH0_KEY=your-auth0-client-id
598
+ OAUTH_AUTH0_SECRET=your-auth0-client-secret
599
+ ```
600
+
601
+ ```yaml
602
+ oauth:
603
+ providers:
604
+ auth0:
605
+ subdomain: your-tenant # Your Auth0 tenant subdomain
606
+ scope:
607
+ - openid
608
+ - email
609
+ - profile
610
+ ```
611
+
612
+ ---
613
+
614
+ ## All Supported Providers (200+)
615
+
616
+ ChadStart uses the [grant](https://www.npmjs.com/package/grant) library under the hood, which supports **200+ OAuth providers**. Any provider listed at [github.com/simov/grant](https://github.com/simov/grant) can be added to your YAML config by its name.
617
+
618
+ Below is a selection of additional providers you can configure. The setup pattern is the same for all:
619
+
620
+ 1. Set `OAUTH_<PROVIDER>_KEY` and `OAUTH_<PROVIDER>_SECRET` in your `.env`
621
+ 2. Add the provider to your YAML config under `oauth.providers`
622
+ 3. Add `<a href="/connect/<provider>">Login with Provider</a>` to your frontend
623
+
624
+ ### Categories of Additional Providers
625
+
626
+ #### Developer & DevOps Platforms
627
+ `atlassian`, `azure`, `digitalocean`, `heroku`, `figma`, `vercel`
628
+
629
+ #### Social & Communication
630
+ `instagram`, `snapchat`, `tiktok`, `telegram`, `line`, `kakao`, `vk`, `weibo`, `wechat`, `yandex`
631
+
632
+ #### Enterprise & Productivity
633
+ `salesforce`, `hubspot`, `asana`, `basecamp`, `box`, `docusign`, `freshbooks`, `intuit`, `quickbooks`, `zendesk`
634
+
635
+ #### Gaming
636
+ `battlenet`, `epicgames`, `steam`, `riotgames`
637
+
638
+ #### Music & Media
639
+ `deezer`, `soundcloud`, `vimeo`, `dailymotion`
640
+
641
+ #### Finance & Payments
642
+ `paypal`, `square`, `coinbase`
643
+
644
+ #### Identity Providers
645
+ `okta`, `onelogin`, `keycloak`
646
+
647
+ #### Email & Marketing
648
+ `mailchimp`, `constantcontact`, `mailgun`
649
+
650
+ ### Example: Adding any provider
651
+
652
+ The configuration pattern is identical for all providers:
653
+
654
+ ```yaml
655
+ oauth:
656
+ providers:
657
+ <provider-name>:
658
+ scope:
659
+ - required-scope-1
660
+ - required-scope-2
661
+ ```
662
+
663
+ ```bash
664
+ OAUTH_<PROVIDER_NAME>_KEY=your-client-id
665
+ OAUTH_<PROVIDER_NAME>_SECRET=your-client-secret
666
+ ```
667
+
668
+ ```html
669
+ <a href="/connect/<provider-name>">Login with Provider</a>
670
+ ```
671
+
672
+ !!! tip
673
+ Check the provider's documentation for the list of available scopes. Grant handles the OAuth protocol differences (OAuth 1.0, 1.0a, 2.0, and OpenID Connect) automatically.
674
+
675
+ ## How It Works
676
+
677
+ ### OAuth Flow
678
+
679
+ ```
680
+ ┌──────────┐ 1. Click login ┌────────────┐
681
+ │ Browser │ ──────────────────────▶ │ ChadStart │
682
+ │ │ │ /connect/ │
683
+ │ │ 2. Redirect to │ google │
684
+ │ │ ◀────────────────────── │ │
685
+ │ │ └────────────┘
686
+ │ │ 3. Login at Google
687
+ │ │ ──────────────────────▶ ┌────────────┐
688
+ │ │ │ Google │
689
+ │ │ 4. Redirect back │ OAuth │
690
+ │ │ ◀────────────────────── │ Server │
691
+ │ │ └────────────┘
692
+ │ │ 5. Exchange code
693
+ │ │ ──────────────────────▶ ┌────────────┐
694
+ │ │ │ ChadStart │
695
+ │ │ 6. JWT token │ /callback │
696
+ │ │ ◀────────────────────── │ │
697
+ └──────────┘ └────────────┘
698
+ ```
699
+
700
+ 1. User clicks a **"Login with Google"** button that links to `/connect/google`.
701
+ 2. ChadStart (via Grant) redirects the user to Google's authorization page.
702
+ 3. User authenticates with Google and grants permissions.
703
+ 4. Google redirects back to ChadStart's callback URL with an authorization code.
704
+ 5. Grant exchanges the code for tokens and fetches the user profile.
705
+ 6. ChadStart finds or creates the user and returns a **JWT token**.
706
+
707
+ ### User Creation
708
+
709
+ When a user logs in via OAuth for the first time:
710
+
711
+ - ChadStart looks for an existing user **by email address**.
712
+ - If found, the existing user is authenticated (no duplicate accounts).
713
+ - If not found, a **new user is created** with:
714
+ - `email` from the OAuth profile
715
+ - A random secure password (user authenticates via OAuth, not password)
716
+ - `name` from the profile (if the entity has a `name` property)
717
+
718
+ ### Token Usage
719
+
720
+ The JWT token returned from OAuth login works exactly the same as tokens from email/password login:
721
+
722
+ ```http
723
+ GET /api/dynamic/posts
724
+ Authorization: Bearer <token-from-oauth>
725
+ ```
726
+
727
+ ## Frontend Integration
728
+
729
+ ### HTML Buttons
730
+
731
+ ```html
732
+ <!-- Simple login buttons -->
733
+ <a href="/connect/google" class="btn">Login with Google</a>
734
+ <a href="/connect/github" class="btn">Login with GitHub</a>
735
+ <a href="/connect/discord" class="btn">Login with Discord</a>
736
+ ```
737
+
738
+ ### React Example
739
+
740
+ ```jsx
741
+ function OAuthButtons() {
742
+ return (
743
+ <div>
744
+ <a href="/connect/google">Login with Google</a>
745
+ <a href="/connect/github">Login with GitHub</a>
746
+ </div>
747
+ );
748
+ }
749
+
750
+ // Handle the redirect (on your successRedirect page)
751
+ function Dashboard() {
752
+ useEffect(() => {
753
+ const params = new URLSearchParams(window.location.search);
754
+ const token = params.get('token');
755
+ if (token) {
756
+ localStorage.setItem('token', token);
757
+ // Clean up URL
758
+ window.history.replaceState({}, '', window.location.pathname);
759
+ }
760
+ }, []);
761
+
762
+ return <div>Welcome!</div>;
763
+ }
764
+ ```
765
+
766
+ ### Vue Example
767
+
768
+ ```vue
769
+ <template>
770
+ <div>
771
+ <a href="/connect/google">Login with Google</a>
772
+ <a href="/connect/github">Login with GitHub</a>
773
+ </div>
774
+ </template>
775
+
776
+ <script setup>
777
+ import { onMounted } from 'vue'
778
+
779
+ onMounted(() => {
780
+ const params = new URLSearchParams(window.location.search)
781
+ const token = params.get('token')
782
+ if (token) {
783
+ localStorage.setItem('token', token)
784
+ window.history.replaceState({}, '', window.location.pathname)
785
+ }
786
+ })
787
+ </script>
788
+ ```
789
+
790
+ ### Dynamic Provider Buttons
791
+
792
+ ```javascript
793
+ // Fetch available providers and render buttons dynamically
794
+ async function renderOAuthButtons(containerId) {
795
+ const res = await fetch('/api/auth/oauth/providers');
796
+ const { providers } = await res.json();
797
+
798
+ const container = document.getElementById(containerId);
799
+ providers.forEach(provider => {
800
+ const link = document.createElement('a');
801
+ link.href = `/connect/${provider}`;
802
+ link.textContent = `Login with ${provider.charAt(0).toUpperCase() + provider.slice(1)}`;
803
+ link.className = 'oauth-btn';
804
+ container.appendChild(link);
805
+ });
806
+ }
807
+ ```
808
+
809
+ ## Multiple Providers
810
+
811
+ You can configure as many providers as you need:
812
+
813
+ ```yaml
814
+ oauth:
815
+ entity: User
816
+ successRedirect: /dashboard
817
+ providers:
818
+ google:
819
+ scope: [openid, email, profile]
820
+ github:
821
+ scope: [user:email]
822
+ discord:
823
+ scope: [identify, email]
824
+ microsoft:
825
+ scope: [openid, email, profile]
826
+ spotify:
827
+ scope: [user-read-email]
828
+ ```
829
+
830
+ All providers share the same callback endpoint and user entity — a user who has signed in with Google and later tries GitHub (with the same email) will be matched to their existing account.
831
+
832
+ ## Security Considerations
833
+
834
+ !!! warning "Important"
835
+ - **Never** put OAuth client secrets in your YAML file — always use environment variables.
836
+ - **Always** use HTTPS in production. OAuth tokens transmitted over HTTP can be intercepted.
837
+ - Set `BASE_URL` in your `.env` to your production URL so redirect URIs are correct.
838
+ - Some providers (like Apple) require HTTPS even for development.
839
+
840
+ ### PKCE Support
841
+
842
+ For enhanced security, enable [PKCE](https://oauth.net/2/pkce/) on providers that support it:
843
+
844
+ ```yaml
845
+ oauth:
846
+ providers:
847
+ google:
848
+ pkce: true
849
+ scope: [openid, email, profile]
850
+ ```
851
+
852
+ ## Troubleshooting
853
+
854
+ ### Common Issues
855
+
856
+ | Issue | Solution |
857
+ |-------|----------|
858
+ | "redirect_uri_mismatch" | Make sure the redirect URI in your provider's console exactly matches `http(s)://your-domain/connect/<provider>/callback` |
859
+ | "invalid_client" | Double-check your `OAUTH_<PROVIDER>_KEY` and `OAUTH_<PROVIDER>_SECRET` environment variables |
860
+ | User not created | Ensure you have at least one entity with `authenticable: true` |
861
+ | Token not received | Check that `successRedirect` points to a valid page in your app |
862
+ | Provider not found | The provider name must be lowercase and match grant's naming (e.g., `github`, not `GitHub`) |
863
+
864
+ ### Debug Tips
865
+
866
+ 1. Check available providers: `GET /api/auth/oauth/providers`
867
+ 2. Verify environment variables are set correctly
868
+ 3. Check server logs for OAuth callback errors
869
+ 4. Make sure `BASE_URL` is set in production