yikart/AiToEarn · error · Error
Invalid Google token
Error message
Invalid Google token
What it means
googleLogin verifies a Google ID token with google-auth-library's OAuth2Client.verifyIdToken. After verification, ticket.getPayload() must return the decoded claims; if it returns null/undefined the token cannot be trusted and the service throws Error('Invalid Google token'). This guards against empty or malformed tokens reaching the login flow.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/google/google.service.ts:403
/**
* Google登录
* @param clientId Google客户端ID
* @param credential Google认证凭证
* @returns Account
*/
async googleLogin(clientId: string, credential: string): Promise<any> {
try {
console.log('Verifying Google token with:');
// 验证Google token
const ticket = await this.oauth2Client.verifyIdToken({
idToken: credential,
audience: clientId,
});
console.log('ticket',ticket)
const googleUser = ticket.getPayload();
console.log('payload',googleUser)
if (!googleUser) {
throw new Error('Invalid Google token');
}
console.log('Google login success, googleUser:', googleUser);
const googleAccount = {
googleId: googleUser.sub,
email: googleUser.email,
// accessToken: result.data.access_token,
refreshToken: null,
// expiresAt: result.data.expires_in
};
let userInfo: User | null = null;
// 优先用 Google ID 查找(最准确)
if (googleUser.sub) {
userInfo = await this.userModel.findOne({
'googleAccount.googleId': googleUser.sub,
status: UserStatus.OPEN,View on GitHub (pinned to d3aa8bea5b)
Solutions
- Check the client is sending the real Google ID token (credential/id_token), not an access token or empty string
- Verify the clientId passed as audience matches the OAuth client that issued the token
- Validate the token string is non-empty before calling googleLogin
- Upgrade google-auth-library to the latest version
- Catch this in the controller and return 401 instead of a raw 500
Example fix
// before
if (!googleUser) {
throw new Error('Invalid Google token');
}
// after
if (!googleUser || !googleUser.sub || !googleUser.email) {
throw new UnauthorizedException('Invalid or incomplete Google token payload');
} Defensive patterns
Strategy: validation
Validate before calling
if (typeof idToken !== 'string' || idToken.split('.').length !== 3) {
throw new UnauthorizedException('A valid Google id_token is required');
} Type guard
function hasGooglePayload(t: unknown): t is { sub: string; email: string } {
return !!t && typeof t === 'object' && 'sub' in t && typeof (t as any).sub === 'string';
} Try / catch
try {
await authService.googleLogin(idToken, clientId);
} catch (err) {
if (err.message.includes('Invalid Google token')) {
return res.status(401).json({ error: 'Please sign in with Google again' });
}
throw err;
} Prevention
- Send the id_token (credential), never the access_token
- Confirm audience/clientId matches the OAuth client on both frontend and backend
- Reject empty tokens client-side before calling the API
- Keep google-auth-library up to date
When it happens
Trigger: Calling googleLogin with an idToken that is empty, malformed, or decodes to no payload — i.e. verifyIdToken resolves but getPayload() returns falsy.
Common situations: Frontend sends an empty string token when the user aborted Google Sign-In; wrong clientId/audience causing an unexpected payload shape; passing an access_token instead of an id_token; an outdated google-auth-library version behaving differently.
Related errors
- Google login failed: ${error.message}
- Failed to refresh access token
- Failed to get user permissions
- Failed to fetch user info
- 无法生成授权URL
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/30e8089ee815735a.
Report an issue: GitHub.