Skip to content

Commit 2e0eebf

Browse files
committed
docs: Adds Google OAuth registration
1 parent 7ee1893 commit 2e0eebf

File tree

2 files changed

+225
-19
lines changed

2 files changed

+225
-19
lines changed

docs/api/types.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ interface User {
3333
password: string // ⚠️ Contains sensitive data
3434
role: string
3535
active: boolean
36+
google_id?: string // Google OAuth ID (optional)
37+
profile_picture?: string // Profile picture URL (optional, from Google)
3638
created_at: string // ISO datetime string
3739
updated_at: string // ISO datetime string
3840
last_login_at?: string // ISO datetime string (optional)
@@ -43,6 +45,10 @@ interface User {
4345
The `User` type includes the password field. Use `UserWithoutPassword` for client-side operations.
4446
:::
4547

48+
::: info
49+
The `google_id` and `profile_picture` fields are populated when users authenticate via Google OAuth.
50+
:::
51+
4652
### UserWithoutPassword
4753

4854
Safe version of User without the password field, suitable for client-side use:
@@ -130,7 +136,9 @@ interface RuntimeModuleOptions {
130136
auth?: {
131137
whitelist?: string[]
132138
tokenExpiration?: number
139+
rememberMeExpiration?: number
133140
permissions?: Record<string, (string | Permission)[]>
141+
google?: GoogleOAuthOptions
134142
}
135143
passwordValidation?: {
136144
minLength?: number
@@ -143,6 +151,83 @@ interface RuntimeModuleOptions {
143151
}
144152
```
145153

154+
### GoogleOAuthOptions
155+
156+
Configuration options for Google OAuth authentication:
157+
158+
```typescript
159+
interface GoogleOAuthOptions {
160+
/**
161+
* Google OAuth client ID from Google Cloud Console
162+
*/
163+
clientId: string
164+
165+
/**
166+
* Google OAuth client secret from Google Cloud Console
167+
*/
168+
clientSecret: string
169+
170+
/**
171+
* Callback URL for Google OAuth (must match what's configured in Google Cloud Console)
172+
* @default '/api/nuxt-users/auth/google/callback'
173+
*/
174+
callbackUrl?: string
175+
176+
/**
177+
* Redirect URL after successful authentication
178+
* @default '/'
179+
*/
180+
successRedirect?: string
181+
182+
/**
183+
* Redirect URL after failed authentication
184+
* @default '/login?error=oauth_failed'
185+
*/
186+
errorRedirect?: string
187+
188+
/**
189+
* Google OAuth scopes to request
190+
* @default ['openid', 'profile', 'email']
191+
*/
192+
scopes?: string[]
193+
194+
/**
195+
* Allow automatic user registration when logging in with Google for the first time
196+
* If false, only existing users with matching email can log in with Google
197+
* @default false
198+
*/
199+
allowAutoRegistration?: boolean
200+
}
201+
```
202+
203+
**Example usage:**
204+
205+
```typescript
206+
// nuxt.config.ts
207+
export default defineNuxtConfig({
208+
modules: ['nuxt-users'],
209+
nuxtUsers: {
210+
auth: {
211+
google: {
212+
clientId: process.env.GOOGLE_CLIENT_ID!,
213+
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
214+
allowAutoRegistration: false, // Only existing users can log in
215+
successRedirect: '/dashboard',
216+
errorRedirect: '/login?error=oauth_failed'
217+
}
218+
}
219+
}
220+
})
221+
```
222+
223+
::: tip
224+
By default, `allowAutoRegistration` is `false` for security. This means only users with existing accounts (by email) can log in with Google. Set it to `true` to allow public registration via Google OAuth.
225+
:::
226+
227+
::: warning
228+
When `allowAutoRegistration: false`, new Google users will be redirected to `errorRedirect` with the error code `user_not_registered`.
229+
:::
230+
146231
### ModuleOptions
147232

148233
Fully resolved module options (after merging with defaults):

docs/user-guide/authentication.md

Lines changed: 140 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -702,11 +702,15 @@ export default defineNuxtConfig({
702702
google: {
703703
clientId: process.env.GOOGLE_CLIENT_ID!,
704704
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
705+
705706
// Optional: customize URLs and scopes
706707
callbackUrl: '/api/nuxt-users/auth/google/callback',
707708
successRedirect: '/dashboard',
708709
errorRedirect: '/login?error=oauth_failed',
709-
scopes: ['openid', 'profile', 'email']
710+
scopes: ['openid', 'profile', 'email'],
711+
712+
// Control automatic user registration (default: false)
713+
allowAutoRegistration: false
710714
}
711715
}
712716
}
@@ -788,18 +792,85 @@ The Google OAuth authentication flow works as follows:
788792
1. **User clicks Google login button** → Redirects to `/api/nuxt-users/auth/google/redirect`
789793
2. **Redirect to Google** → User is sent to Google's OAuth consent screen
790794
3. **User grants permission** → Google redirects back to `/api/nuxt-users/auth/google/callback`
791-
4. **Process OAuth response** → Module exchanges code for user info
792-
5. **Create or link account** → User is created or existing account is linked
793-
6. **Set authentication cookie** → User is logged in with persistent session
794-
7. **Redirect to success page** → User is redirected to configured success URL
795+
4. **Process OAuth response** → Module exchanges code for user info and verifies email
796+
5. **Find or create user** → Module checks if user exists:
797+
- Existing Google user → Update profile picture if changed
798+
- Existing user by email → Link Google account automatically
799+
- New user + `allowAutoRegistration: true` → Create new account
800+
- New user + `allowAutoRegistration: false` → Reject with error
801+
6. **Set authentication cookie** → User is logged in with persistent session (30 days by default)
802+
7. **Redirect** → User is redirected to `successRedirect` or `errorRedirect` based on outcome
803+
804+
### User Account Linking & Auto-Registration
805+
806+
The module intelligently handles different user scenarios based on the `allowAutoRegistration` configuration:
807+
808+
#### Scenario 1: Existing User with Google Account
809+
When a user who has previously linked their Google account logs in:
810+
- ✅ User is authenticated immediately
811+
- ✅ Profile picture is automatically updated if changed
812+
- ✅ User is redirected to `successRedirect`
813+
814+
#### Scenario 2: Existing User by Email (Auto-Linking)
815+
When a user with an existing account (created via traditional registration) logs in with Google for the first time:
816+
- ✅ Google account is automatically linked to the existing user account
817+
- ✅ User's `google_id` is saved for future logins
818+
- ✅ Profile picture is added/updated
819+
- ✅ User can now log in with either password or Google
820+
821+
#### Scenario 3: New User (Controlled by `allowAutoRegistration`)
822+
823+
**When `allowAutoRegistration: false` (default - recommended for production)**:
824+
- ❌ New users cannot self-register via Google
825+
- ❌ User is redirected to `errorRedirect` with `error=user_not_registered`
826+
- ✅ More secure for invite-only or controlled access systems
827+
- ✅ Prevents unauthorized account creation
828+
829+
```ts
830+
// Secure configuration - only existing users can log in with Google
831+
auth: {
832+
google: {
833+
clientId: process.env.GOOGLE_CLIENT_ID!,
834+
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
835+
allowAutoRegistration: false // Default
836+
}
837+
}
838+
```
839+
840+
**When `allowAutoRegistration: true` (for public registration)**:
841+
- ✅ New users are automatically registered when they log in with Google
842+
- ✅ Account is created with:
843+
- Email and name from Google profile
844+
- Cryptographically secure random password (user won't need it)
845+
- Profile picture from Google
846+
- Default role: `'user'`
847+
- Account status: `active`
848+
- ✅ User is immediately logged in and redirected to `successRedirect`
795849

796-
### User Account Linking
850+
```ts
851+
// Open registration - anyone with a Google account can register
852+
auth: {
853+
google: {
854+
clientId: process.env.GOOGLE_CLIENT_ID!,
855+
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
856+
allowAutoRegistration: true // Allow public registration
857+
}
858+
}
859+
```
797860

798-
The module intelligently handles user account linking:
861+
#### Security Considerations
799862

800-
- **New Google user**: Creates a new account with secure random password
801-
- **Existing email**: Links Google account to existing user account
802-
- **Returning Google user**: Logs in existing user and updates profile picture
863+
**Use `allowAutoRegistration: false` when:**
864+
- You want to control who can access your application
865+
- You have an invite-only system
866+
- You want admins to manually approve users
867+
- You're building an internal/private application
868+
869+
**Use `allowAutoRegistration: true` when:**
870+
- You want public registration
871+
- You're building a consumer-facing application
872+
- You trust Google's email verification
873+
- You have additional security measures in place (role-based access, etc.)
803874

804875
### Security Features
805876

@@ -811,41 +882,91 @@ The module intelligently handles user account linking:
811882

812883
### Error Handling
813884

814-
The OAuth flow handles various error scenarios:
885+
The OAuth flow handles various error scenarios and redirects to `errorRedirect` with specific error codes:
886+
887+
- **`oauth_failed`**: User cancels Google consent or OAuth process fails
888+
- **`oauth_not_configured`**: Missing or invalid Google OAuth configuration (client ID/secret)
889+
- **`user_not_registered`**: New user attempted login when `allowAutoRegistration: false` (default)
890+
- **`account_inactive`**: User account exists but is marked as inactive
891+
- **`oauth_failed`**: Google API failures or token exchange errors
815892

816-
- **OAuth denied**: User cancels Google consent → redirects to error page
817-
- **Invalid configuration**: Missing client ID/secret → shows configuration error
818-
- **Account inactive**: Inactive user attempts login → redirects with error message
819-
- **API errors**: Google API failures → logs error and redirects safely
893+
Example error handling in your login page:
894+
895+
```vue
896+
<script setup>
897+
import { ref, onMounted } from 'vue'
898+
import { useRoute } from 'vue-router'
899+
900+
const route = useRoute()
901+
const errorMessage = ref('')
902+
903+
const errorMessages = {
904+
oauth_failed: 'Google authentication failed. Please try again.',
905+
user_not_registered: 'You are not registered. Please sign up first or contact an administrator.',
906+
account_inactive: 'Your account is inactive. Please contact support.',
907+
oauth_not_configured: 'OAuth is not properly configured. Please contact support.'
908+
}
909+
910+
onMounted(() => {
911+
const error = route.query.error
912+
if (error && errorMessages[error]) {
913+
errorMessage.value = errorMessages[error]
914+
}
915+
})
916+
</script>
917+
918+
<template>
919+
<div v-if="errorMessage" class="error-banner">
920+
{{ errorMessage }}
921+
</div>
922+
<NUsersGoogleLoginButton />
923+
</template>
924+
```
820925

821926
### Customization
822927

823-
You can customize the OAuth behavior:
928+
You can customize the OAuth behavior with all available options:
824929

825930
```ts
826931
// nuxt.config.ts
827932
export default defineNuxtConfig({
828933
nuxtUsers: {
829934
auth: {
830935
google: {
936+
// Required: OAuth credentials from Google Cloud Console
831937
clientId: process.env.GOOGLE_CLIENT_ID!,
832938
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
833939

940+
// Control user registration (default: false)
941+
allowAutoRegistration: false,
942+
834943
// Customize redirect URLs
835-
successRedirect: '/welcome', // After successful login
944+
successRedirect: '/welcome', // After successful login (default: '/')
836945
errorRedirect: '/login?error=google_failed', // After failed login
837946

838-
// Request additional permissions
947+
// Request additional permissions (default: ['openid', 'profile', 'email'])
839948
scopes: ['openid', 'profile', 'email', 'https://www.googleapis.com/auth/user.birthday.read'],
840949

841-
// Custom callback URL (must match Google Cloud Console)
950+
// Custom callback URL - must match Google Cloud Console configuration
842951
callbackUrl: '/api/nuxt-users/auth/google/callback'
843952
}
844953
}
845954
}
846955
})
847956
```
848957

958+
#### Configuration Options Reference
959+
960+
| Option | Type | Default | Description |
961+
|--------|------|---------|-------------|
962+
| `clientId` | `string` | **required** | Google OAuth client ID from Google Cloud Console |
963+
| `clientSecret` | `string` | **required** | Google OAuth client secret from Google Cloud Console |
964+
| `allowAutoRegistration` | `boolean` | `false` | Allow new users to auto-register via Google |
965+
| `successRedirect` | `string` | `'/'` | Redirect URL after successful authentication |
966+
| `errorRedirect` | `string` | `'/login?error=oauth_failed'` | Redirect URL after failed authentication |
967+
| `scopes` | `string[]` | `['openid', 'profile', 'email']` | Google OAuth scopes to request |
968+
| `callbackUrl` | `string` | `'/api/nuxt-users/auth/google/callback'` | OAuth callback URL (must match Google Console) |
969+
849970
## Security Best Practices
850971

851972
1. **Use HTTPS**: Always use HTTPS in production to protect credentials in transit

0 commit comments

Comments
 (0)