ASP.NET Core 3.1集成Google Drive API时遭遇OAuth 2.0错误400: redirect_uri_mismatch
Let's break down why you're hitting this redirect_uri_mismatch error and how to fix it:
The Root Cause
You're using GoogleWebAuthorizationBroker.AuthorizeAsync—this method is designed for desktop applications, not web apps. It automatically spins up a temporary local server with a hardcoded redirect URI (like http://localhost:random-port/authorize), which doesn't match the http://127.0.0.1:4000 address of your ASP.NET Core web server, nor the URIs you've configured in Google Cloud Console.
Step 1: Correct Your Google Cloud Console Configuration
First, make sure your OAuth 2.0 Client ID is set up properly for web apps:
- Go to your Google Cloud Console > APIs & Services > Credentials
- Find your Client ID. If it's a "Desktop app" type, create a new Web application Client ID instead.
- Under "Authorized redirect URIs", add exactly
http://127.0.0.1:4000/signin-google(we'll use this default callback path with ASP.NET Core's auth middleware later).- Important:
127.0.0.1andlocalhostare treated as separate domains here—match the exact address your app uses.
- Important:
Step 2: Update Your ASP.NET Core Code for Web App Authorization
Instead of GoogleWebAuthorizationBroker, use ASP.NET Core's built-in authentication middleware to handle the OAuth flow correctly. Here's how to adjust your code:
1. Configure Google Auth Middleware (Startup.cs)
Add this to your ConfigureServices method to set up Google OAuth authentication:
using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Authentication.Cookies; public void ConfigureServices(IServiceCollection services) { // ... other service configurations services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; }) .AddCookie() .AddGoogle(options => { // Load credentials from appsettings.json (replace with your keys) options.ClientId = Configuration["Google:ClientId"]; options.ClientSecret = Configuration["Google:ClientSecret"]; options.CallbackPath = "/signin-google"; // Must match the URI in Google Console // Add the Drive API scopes you need options.Scope.Add(DriveService.Scope.Drive); options.Scope.Add(DriveService.Scope.DriveFile); }); // Add HttpContextAccessor to access user tokens in your service services.AddHttpContextAccessor(); }
Don't forget to enable authentication in the Configure method:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // ... other middleware (like routing, static files) app.UseAuthentication(); app.UseAuthorization(); // ... endpoints }
2. Update Your GDriveService to Use Authenticated User Tokens
Modify your service to retrieve the valid access token from the authenticated user's session and create the DriveService:
public class GDriveService : BaseService { private readonly IHttpContextAccessor _httpContextAccessor; private readonly string _appName; private DriveService _service; public GDriveService(IWebHostEnvironment env, IHttpContextAccessor httpContextAccessor) : base(env) { _httpContextAccessor = httpContextAccessor; _appName = ConfigurationManager.AppSettings["AppName"].ToString(); InitializeDriveService(); } private void InitializeDriveService() { // Get the access token from the current authenticated user var accessToken = _httpContextAccessor.HttpContext.GetTokenAsync("access_token").Result; // Create a credential from the token var credential = new UserCredential( new GoogleAuthorizationCodeFlow( new GoogleAuthorizationCodeFlow.Initializer { ClientSecrets = new ClientSecrets { ClientId = ConfigurationManager.AppSettings["GoogleClientId"], ClientSecret = ConfigurationManager.AppSettings["GoogleClientSecret"] }, Scopes = new[] { DriveService.Scope.Drive, DriveService.Scope.DriveFile } }), "user", // Use the authenticated user's ID here for multi-user apps new TokenResponse { AccessToken = accessToken }); // Initialize the Drive Service _service = new DriveService(new BaseClientService.Initializer { HttpClientInitializer = credential, ApplicationName = _appName }); } // Add your Drive API methods here using _service }
Step 3: Trigger the Authorization Flow
To prompt users to authenticate, add a login route or action that challenges the Google auth scheme:
public IActionResult Login() { return Challenge(new AuthenticationProperties { RedirectUri = "/" }, GoogleDefaults.AuthenticationScheme); }
Key Notes to Avoid Future Issues
- Never use
GoogleWebAuthorizationBrokerin a web application—it's intended for desktop/mobile apps where the app can listen on a random local port. - Always ensure the redirect URI in Google Console exactly matches the one used in your app (including
http/https, domain, port, and path). - For multi-user apps, store user tokens securely (like in a database) instead of relying on session storage alone.
内容的提问来源于stack exchange,提问作者Chanchen Pork

