2:I[7012,["4765","static/chunks/4765-f5afdf8061f456f3.js","9856","static/chunks/9856-3b185291364d9bef.js","6687","static/chunks/app/docs/%5B...slug%5D/page-e07536548216bee4.js"],"MarkdownRenderer"] 4:I[9856,["4765","static/chunks/4765-f5afdf8061f456f3.js","9856","static/chunks/9856-3b185291364d9bef.js","6687","static/chunks/app/docs/%5B...slug%5D/page-e07536548216bee4.js"],""] 5:I[4126,[],""] 7:I[9630,[],""] 8:I[4278,["9856","static/chunks/9856-3b185291364d9bef.js","8172","static/chunks/8172-b3a2d6fe4ae10d40.js","3185","static/chunks/app/layout-2814fa5d15b84fe4.js"],"HeadingProvider"] 9:I[1476,["9856","static/chunks/9856-3b185291364d9bef.js","8172","static/chunks/8172-b3a2d6fe4ae10d40.js","3185","static/chunks/app/layout-2814fa5d15b84fe4.js"],"Header"] a:I[3167,["9856","static/chunks/9856-3b185291364d9bef.js","8172","static/chunks/8172-b3a2d6fe4ae10d40.js","3185","static/chunks/app/layout-2814fa5d15b84fe4.js"],"Sidebar"] b:I[7409,["9856","static/chunks/9856-3b185291364d9bef.js","8172","static/chunks/8172-b3a2d6fe4ae10d40.js","3185","static/chunks/app/layout-2814fa5d15b84fe4.js"],"PageFrame"] 3:T1775, # OAuth Login Configuration Guide This document explains how to configure Google and Microsoft OAuth login for VoiceAssist. ## Overview VoiceAssist supports OAuth 2.0 authentication with: - **Google** (Google Sign-In) - **Microsoft** (Microsoft Entra ID / Azure AD) When configured, users can sign in using their existing Google or Microsoft accounts instead of creating a separate password. ## Environment Variables Add these environment variables to your `.env` file or deployment configuration: ### Google OAuth ```env # Google OAuth (optional - leave empty to disable) GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-google-client-secret GOOGLE_OAUTH_REDIRECT_URI=https://your-domain.com/auth/callback/google ``` ### Microsoft OAuth ```env # Microsoft OAuth (optional - leave empty to disable) MICROSOFT_CLIENT_ID=your-microsoft-application-client-id MICROSOFT_CLIENT_SECRET=your-microsoft-client-secret MICROSOFT_OAUTH_REDIRECT_URI=https://your-domain.com/auth/callback/microsoft ``` ## Setting Up OAuth Providers ### Google OAuth Setup 1. Go to [Google Cloud Console](https://console.cloud.google.com/) 2. Create a new project or select an existing one 3. Navigate to **APIs & Services > Credentials** 4. Click **Create Credentials > OAuth client ID** 5. Select **Web application** as the application type 6. Configure authorized redirect URIs: - For development: `http://localhost:5173/auth/callback/google` - For production: `https://your-domain.com/auth/callback/google` 7. Copy the Client ID and Client Secret to your environment variables ### Microsoft OAuth Setup 1. Go to [Azure Portal](https://portal.azure.com/) 2. Navigate to **Microsoft Entra ID > App registrations** 3. Click **New registration** 4. Enter a name for your application 5. Select supported account types (typically "Accounts in any organizational directory and personal Microsoft accounts") 6. Add redirect URI: - Platform: Web - For development: `http://localhost:5173/auth/callback/microsoft` - For production: `https://your-domain.com/auth/callback/microsoft` 7. Under **Certificates & secrets**, create a new client secret 8. Copy the Application (client) ID and client secret value to your environment variables ## API Endpoints ### Get OAuth Authorization URL ``` GET /api/auth/oauth/{provider}/authorize ``` **Parameters:** - `provider`: `google` or `microsoft` **Response (200 OK):** ```json { "success": true, "data": { "url": "https://accounts.google.com/o/oauth2/v2/auth?...", "state": "random-csrf-state-token" }, "error": null, "metadata": {...}, "timestamp": "2024-01-15T10:00:00.000Z" } ``` **Response (503 Service Unavailable):** When provider is not configured: ```json { "detail": "Google OAuth is not configured. Please contact the administrator." } ``` ### OAuth Callback ``` POST /api/auth/oauth/{provider}/callback ``` **Parameters:** - `provider`: `google` or `microsoft` **Request Body:** ```json { "code": "authorization-code-from-provider" } ``` **Response (200 OK):** ```json { "access_token": "jwt-access-token", "refresh_token": "jwt-refresh-token", "token_type": "bearer", "expires_in": 900 } ``` ### Check Provider Status ``` GET /api/auth/oauth/{provider}/status ``` **Response:** ```json { "success": true, "data": { "provider": "google", "configured": true, "enabled": true }, "error": null, "metadata": {...}, "timestamp": "2024-01-15T10:00:00.000Z" } ``` ## Frontend Integration The frontend OAuth flow works as follows: 1. User clicks "Sign in with Google" or "Sign in with Microsoft" 2. Frontend calls `GET /api/auth/oauth/{provider}/authorize` 3. Frontend receives the authorization URL and redirects the browser to it 4. User authenticates with the provider 5. Provider redirects back to `/auth/callback/{provider}?code=...` 6. Frontend extracts the code and calls `POST /api/auth/oauth/{provider}/callback` 7. Backend exchanges code for tokens and creates/finds the user 8. Backend returns JWT tokens 9. Frontend stores tokens and redirects to the app ## User Account Behavior ### New Users When a user signs in via OAuth for the first time: - A new account is created using their email from the OAuth provider - The user's name is taken from the provider profile - No password is set (OAuth-only account) ### Existing Users If a user with the same email already exists: - The OAuth provider is linked to the existing account - User can now sign in with either method (password or OAuth) ### Account Security - OAuth accounts without passwords cannot use password-based login - OAuth provider ID is stored to prevent account hijacking - Users cannot change their email to another user's OAuth-linked email ## Troubleshooting ### "OAuth not configured" Error - Verify the environment variables are set correctly - Ensure both `CLIENT_ID` and `CLIENT_SECRET` are provided - Restart the API server after changing environment variables ### "Failed to exchange authorization code" - Check that the redirect URI matches exactly (including trailing slashes) - Verify the client secret is correct - Check server logs for detailed error messages ### User Not Found After OAuth - Check that the email scope is included in the OAuth request - Verify the provider returned an email address - Check server logs for user creation errors ## Running Tests Run the OAuth integration tests: ```bash cd services/api-gateway source venv/bin/activate pytest tests/integration/test_auth_oauth.py -v ``` ## Security Considerations 1. **State Parameter**: The authorize endpoint generates a random state parameter for CSRF protection 2. **HTTPS Required**: OAuth redirect URIs must use HTTPS in production 3. **Secret Storage**: Never commit OAuth secrets to version control 4. **Token Validation**: All tokens from OAuth providers are validated before use 5. **Rate Limiting**: OAuth endpoints have rate limits to prevent abuse 6:["slug","OAUTH_LOGIN_CONFIG","c"] 0:["X7oMT3VrOffzp0qvbeOas",[[["",{"children":["docs",{"children":[["slug","OAUTH_LOGIN_CONFIG","c"],{"children":["__PAGE__?{\"slug\":[\"OAUTH_LOGIN_CONFIG\"]}",{}]}]}]},"$undefined","$undefined",true],["",{"children":["docs",{"children":[["slug","OAUTH_LOGIN_CONFIG","c"],{"children":["__PAGE__",{},[["$L1",["$","div",null,{"children":[["$","div",null,{"className":"mb-6 flex items-center justify-between gap-4","children":[["$","div",null,{"children":[["$","p",null,{"className":"text-sm text-gray-500 dark:text-gray-400","children":"Docs / Raw"}],["$","h1",null,{"className":"text-3xl font-bold text-gray-900 dark:text-white","children":"Oauth Login Config"}],["$","p",null,{"className":"text-sm text-gray-600 dark:text-gray-400","children":["Sourced from"," ",["$","code",null,{"className":"font-mono text-xs","children":["docs/","OAUTH_LOGIN_CONFIG.md"]}]]}]]}],["$","a",null,{"href":"https://github.com/mohammednazmy/VoiceAssist/edit/main/docs/OAUTH_LOGIN_CONFIG.md","target":"_blank","rel":"noreferrer","className":"inline-flex items-center gap-2 rounded-md border border-gray-200 dark:border-gray-700 px-3 py-1.5 text-sm text-gray-700 dark:text-gray-200 hover:border-primary-500 dark:hover:border-primary-400 hover:text-primary-700 dark:hover:text-primary-300","children":"Edit on GitHub"}]]}],["$","div",null,{"className":"rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 p-6","children":["$","$L2",null,{"content":"$3"}]}],["$","div",null,{"className":"mt-6 flex flex-wrap gap-2 text-sm","children":[["$","$L4",null,{"href":"/reference/all-docs","className":"inline-flex items-center gap-1 rounded-md bg-gray-100 px-3 py-1 text-gray-700 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700","children":"← All documentation"}],["$","$L4",null,{"href":"/","className":"inline-flex items-center gap-1 rounded-md bg-gray-100 px-3 py-1 text-gray-700 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700","children":"Home"}]]}]]}],null],null],null]},[null,["$","$L5",null,{"parallelRouterKey":"children","segmentPath":["children","docs","children","$6","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[null,["$","$L5",null,{"parallelRouterKey":"children","segmentPath":["children","docs","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/7f586cdbbaa33ff7.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"en","className":"h-full","children":["$","body",null,{"className":"__className_f367f3 h-full bg-white dark:bg-gray-900","children":[["$","a",null,{"href":"#main-content","className":"skip-to-content","children":"Skip to main content"}],["$","$L8",null,{"children":[["$","$L9",null,{}],["$","$La",null,{}],["$","main",null,{"id":"main-content","className":"lg:pl-64","role":"main","aria-label":"Documentation content","children":["$","$Lb",null,{"children":["$","$L5",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]}]}]]}]]}]}]],null],null],["$Lc",null]]]] c:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"Oauth Login Config | Docs | VoiceAssist Docs"}],["$","meta","3",{"name":"description","content":"This document explains how to configure Google and Microsoft OAuth login for VoiceAssist."}],["$","meta","4",{"name":"keywords","content":"VoiceAssist,documentation,medical AI,voice assistant,healthcare,HIPAA,API"}],["$","meta","5",{"name":"robots","content":"index, follow"}],["$","meta","6",{"name":"googlebot","content":"index, follow"}],["$","link","7",{"rel":"canonical","href":"https://assistdocs.asimo.io"}],["$","meta","8",{"property":"og:title","content":"VoiceAssist Documentation"}],["$","meta","9",{"property":"og:description","content":"Comprehensive documentation for VoiceAssist - Enterprise Medical AI Assistant"}],["$","meta","10",{"property":"og:url","content":"https://assistdocs.asimo.io"}],["$","meta","11",{"property":"og:site_name","content":"VoiceAssist Docs"}],["$","meta","12",{"property":"og:type","content":"website"}],["$","meta","13",{"name":"twitter:card","content":"summary"}],["$","meta","14",{"name":"twitter:title","content":"VoiceAssist Documentation"}],["$","meta","15",{"name":"twitter:description","content":"Comprehensive documentation for VoiceAssist - Enterprise Medical AI Assistant"}],["$","meta","16",{"name":"next-size-adjust"}]] 1:null