Expo安卓应用Google OAuth遇400错误及redirect_uri配置困惑
Expo安卓应用Google OAuth认证问题解决
问题描述
首次在Expo中实现安卓应用的Google OAuth认证时,出现错误:
You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy for keeping apps secure.
同时不清楚redirect_uri的配置方式,相关代码如下:
const redirectUri = AuthSession.makeRedirectUri(); const login = () => { const [userInfo, setUserinfo] = useState(); const [request, response, promptAsync] = Google.useAuthRequest({ androidClientId: process.env.EXPO_PUBLIC_ANDROID_GOOGLE_CLIENT_ID || "", redirectUri: redirectUri, usePKCE: false }); console.log(request) useEffect(() => { console.log(process.env.EXPO_PUBLIC_ANDROID_GOOGLE_CLIENT_ID) if(response?.type == "success"){ const {authentication} = response; getUserInfo(authentication?.accessToken) } }, [response]) async function getUserInfo(token: string | undefined){ try{ const response = await fetch('https://www.googleapis.com/userinfo/v2/me', { headers: {Authorization: `Bearer ${token}`} }) const user = await response.json() setUserinfo(user) } catch(exc){ console.error("Error getting user info with access token", exc) } } }
解决方案
1. 修复PKCE配置(核心错误)
Google OAuth 2.0政策强制要求移动端应用使用PKCE(Proof Key for Code Exchange)保障安全,你代码中usePKCE: false直接违反了该规则,这是报错的主要原因。
- 将
usePKCE改为true。
2. 正确配置Redirect URI
Expo中AuthSession.makeRedirectUri()会自动生成对应环境的重定向URI,但需要在Google Cloud控制台中将这些URI添加到授权列表:
- Expo Go预览环境:
运行应用后,通过console.log(redirectUri)拿到实际生成的URI(格式类似exp://192.168.xxx.xxx:8081--auth或exp://your-project-slug.exp.direct--auth),把这个值添加到Google Cloud的OAuth客户端「已授权的重定向URI」中。 - 自定义开发构建/生产构建:
重定向URI格式为com.your.app.package://expo-auth-session,替换com.your.app.package为你的安卓应用包名(在app.json的android.package字段中设置),同样添加到Google Cloud的授权列表。
3. 修正代码中的Hook位置错误
React Hooks(如useState、useEffect)不能定义在普通函数内部(你的login函数里),必须移到组件顶层。修正后的代码示例:
import { useState, useEffect } from 'react'; import { Google, AuthSession } from 'expo'; export default function LoginScreen() { const [userInfo, setUserinfo] = useState<any>(null); const redirectUri = AuthSession.makeRedirectUri(); const [request, response, promptAsync] = Google.useAuthRequest({ androidClientId: process.env.EXPO_PUBLIC_ANDROID_GOOGLE_CLIENT_ID || "", redirectUri: redirectUri, usePKCE: true // 必须开启PKCE }); useEffect(() => { console.log(process.env.EXPO_PUBLIC_ANDROID_GOOGLE_CLIENT_ID); if(response?.type === "success"){ const {authentication} = response; getUserInfo(authentication?.accessToken); } }, [response]) async function getUserInfo(token: string | undefined){ if(!token) return; try{ const response = await fetch('https://www.googleapis.com/userinfo/v2/me', { headers: {Authorization: `Bearer ${token}`} }) const user = await response.json(); setUserinfo(user); } catch(exc){ console.error("获取用户信息失败", exc); } } return ( // 你的页面JSX <button onClick={() => promptAsync()}>登录Google</button> ) }
4. 其他必要检查
- 确保
androidClientId是Google Cloud中创建的安卓类型OAuth客户端ID,不要混用网页或iOS的客户端ID。 - 检查Google Cloud安卓客户端配置中的SHA-1指纹:
- 使用Expo Go时,固定SHA-1为
BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:A1:66:6E:44:5D:75。 - 自定义构建时,需要生成你应用签名证书的SHA-1指纹并添加到配置中。
- 使用Expo Go时,固定SHA-1为
内容的提问来源于stack exchange,提问作者GaGex
相关产品推荐
相关产品推荐

