Google Cloud API Error 400: redirect_uri_mismatch及Gmail API调用问题
问题分析与解决方案
核心问题
- redirect_uri不匹配:Web应用的OAuth2流程与桌面应用不同,redirect_uri必须与Google控制台配置严格一致,本地调试需使用正确的
localhost地址格式。 - 代码流程错误:更新后的代码直接创建空的
TokenResponse,未走Web应用的授权码获取→兑换token的完整流程,无法生成有效凭证。
步骤1:正确配置Google控制台的Redirect URI
- 确认凭证类型为Web应用,而非桌面应用。
- 本地调试时,redirect_uri必须使用
http://localhost:端口号/回调页面路径(注意用正斜杠),例如本地运行端口为1234、回调页为authorize.aspx,则配置http://localhost:1234/authorize.aspx。 - 配置要求:
- 必须与代码中指定的redirect_uri完全一致,包括末尾是否带斜杠、路径大小写(Google不区分大小写,但严格匹配更稳妥)。
- 本地调试优先使用
localhost,避免IP地址导致的权限验证问题。
步骤2:Web应用正确的OAuth2授权流程(VB.NET)
Web应用需先引导用户到Google授权页面获取授权码,再用授权码兑换token,之后才能调用Gmail API。以下是修正后的完整逻辑:
1. 授权跳转逻辑(示例页面:member/create.aspx)
Protected Async Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load ' 无授权码时,跳转到Google授权页面 If Request.QueryString("code") Is Nothing Then Dim flow As IAuthorizationCodeFlow = New GoogleAuthorizationCodeFlow(New GoogleAuthorizationCodeFlow.Initializer With { .ClientSecrets = New ClientSecrets With { .ClientId = "你的ClientId", .ClientSecret = "你的ClientSecret" }, .Scopes = {GmailService.Scope.GmailSend}, .DataStore = New FileDataStore("GmailAuthStore") ' 持久化存储token,避免重复授权 }) ' 生成授权跳转URL,redirect_uri需与控制台配置完全一致 Dim authorizationUrl As String = flow.CreateAuthorizationCodeRequest("http://localhost:1234/authorize.aspx").Build() Response.Redirect(authorizationUrl) Else ' 有授权码时,兑换token并发送邮件 Await DoOauthAndSendEmail("测试主题", "测试内容", "收件人邮箱") End If End Sub
2. 修正后的邮件发送方法
Public Async Function DoOauthAndSendEmail(subject As String, body As String, recipients As String) As Task Dim fromEmail As String = ConfigurationSettings.AppSettings("ContactEmail") ' 构建并转换邮件格式 Dim mailMessage As New MailMessage(fromEmail, recipients, subject, body) mailMessage.IsBodyHtml = True Dim mimeMessage As MimeMessage = MimeMessage.CreateFromMailMessage(mailMessage) Dim rawMessage As String = mimeMessage.ToString() ' 初始化授权流程 Dim flow As IAuthorizationCodeFlow = New GoogleAuthorizationCodeFlow(New GoogleAuthorizationCodeFlow.Initializer With { .ClientSecrets = New ClientSecrets With { .ClientId = "你的ClientId", .ClientSecret = "你的ClientSecret" }, .Scopes = {GmailService.Scope.GmailSend}, .DataStore = New FileDataStore("GmailAuthStore") }) ' 用授权码兑换token Dim code As String = Request.QueryString("code") Dim token As TokenResponse = Await flow.ExchangeCodeForTokenAsync("user", code, "http://localhost:1234/authorize.aspx", CancellationToken.None) ' 创建凭证并刷新过期token Dim credential As New UserCredential(flow, "user", token) If credential.Token.IsExpired(flow.Clock) Then Await credential.RefreshTokenAsync(CancellationToken.None) End If ' 初始化Gmail服务并发送邮件 Dim gmail As New GmailService(New BaseClientService.Initializer() With { .ApplicationName = "你的应用名称", .HttpClientInitializer = credential }) Dim request As UsersResource.MessagesResource.SendRequest = gmail.Users.Messages.Send( New Message With {.Raw = Base64UrlEncode(rawMessage)}, "me") Await request.ExecuteAsync() End Function ' Base64Url编码辅助方法 Private Function Base64UrlEncode(input As String) As String Dim inputBytes As Byte() = System.Text.Encoding.UTF8.GetBytes(input) Return Convert.ToBase64String(inputBytes).Replace("+", "-").Replace("/", "_").TrimEnd("="c) End Function
关键注意事项
- Token持久化:
FileDataStore会将token存储在本地文件中,后续请求可直接复用,无需重复引导用户授权。 - 端口一致性:本地调试服务器(IIS/Visual Studio开发服务器)的端口号必须与redirect_uri中的端口一致。
- OAuth同意屏幕配置:Google控制台中需完成OAuth同意屏幕配置,测试阶段可添加特定测试用户,避免授权限制。
内容的提问来源于stack exchange,提问作者Samra
相关产品推荐
相关产品推荐

