如何在.NET中通过Google OAuth2令牌完成AWS Cognito用户认证?
解决方案
你需要通过Cognito联合身份认证流程实现「存在则登录,不存在则创建」的逻辑,核心是先验证Google令牌合法性,再查询关联Cognito用户,最后生成Cognito会话令牌。以下是具体步骤和.NET代码实现:
1. 验证Google ID Token合法性
这一步是必要的,防止伪造令牌。使用Google官方库Google.Apis.Auth完成验证:
using Google.Apis.Auth; var googleIdToken = "从前端接收的Google ID Token"; var googleClientId = "你的Google OAuth客户端ID"; var validationSettings = new GoogleJsonWebSignature.ValidationSettings { Audience = new List<string> { googleClientId } }; // 验证并解析令牌,失败会抛出异常 var googleUserPayload = await GoogleJsonWebSignature.ValidateAsync(googleIdToken, validationSettings);
2. 查询Cognito用户池是否存在关联用户
通过Google用户的sub(唯一标识)查询Cognito用户,避免邮箱重复的问题:
using Amazon.CognitoIdentityProvider; using Amazon.CognitoIdentityProvider.Model; var cognitoClient = new AmazonCognitoIdentityProviderClient(RegionEndpoint.YourRegion); // 替换为你的用户池区域 var userPoolId = "你的Cognito用户池ID"; var listUsersRequest = new ListUsersRequest { UserPoolId = userPoolId, Filter = $"identities[0].userId = \"{googleUserPayload.Sub}\"" }; var listUsersResponse = await cognitoClient.ListUsersAsync(listUsersRequest); var existingUser = listUsersResponse.Users.FirstOrDefault();
3. 不存在则创建Cognito用户并关联Google身份
如果用户未在Cognito中存在,先创建本地用户,再关联Google身份提供商:
if (existingUser == null) { // 1. 创建Cognito本地用户 var createUserRequest = new AdminCreateUserRequest { UserPoolId = userPoolId, Username = googleUserPayload.Email, // 用邮箱作为用户名,或用Google的sub UserAttributes = new List<AttributeType> { new AttributeType { Name = "email", Value = googleUserPayload.Email }, new AttributeType { Name = "email_verified", Value = "true" } // Google已验证邮箱,直接设为true }, TemporaryPassword = Guid.NewGuid().ToString() // 临时密码,关联第三方后无需使用 }; await cognitoClient.AdminCreateUserAsync(createUserRequest); // 2. 关联Google身份到Cognito用户 var linkProviderRequest = new AdminLinkProviderForUserRequest { UserPoolId = userPoolId, DestinationUser = new ProviderUserIdentifierType { ProviderName = "Cognito", ProviderAttributeName = "username", ProviderAttributeValue = googleUserPayload.Email }, SourceUser = new ProviderUserIdentifierType { ProviderName = "Google", ProviderAttributeName = "sub", ProviderAttributeValue = googleUserPayload.Sub } }; await cognitoClient.AdminLinkProviderForUserAsync(linkProviderRequest); // 获取刚创建的用户信息 existingUser = (await cognitoClient.AdminGetUserAsync(new AdminGetUserRequest { UserPoolId = userPoolId, Username = googleUserPayload.Email })).User; }
4. 生成Cognito会话令牌(登录)
使用Google的ID Token向Cognito发起认证,获取Cognito的ID/Access/Refresh令牌,返回给前端使用:
var clientId = "你的Cognito应用客户端ID"; var authRequest = new AdminInitiateAuthRequest { UserPoolId = userPoolId, ClientId = clientId, AuthFlow = AuthFlowType.AuthenticationProvider, AuthParameters = new Dictionary<string, string> { { "PROVIDER_NAME", "Google" }, { "ID_TOKEN", googleIdToken } } }; var authResponse = await cognitoClient.AdminInitiateAuthAsync(authRequest); // 封装Cognito令牌返回给前端 var cognitoTokens = new { IdToken = authResponse.AuthenticationResult.IdToken, AccessToken = authResponse.AuthenticationResult.AccessToken, RefreshToken = authResponse.AuthenticationResult.RefreshToken };
关键注意事项
- 确保你的Cognito用户池已在控制台配置Google作为身份提供商,并填写正确的Google OAuth客户端ID和密钥。
- 前端后续请求需携带Cognito的
IdToken或AccessToken,后端通过Cognito SDK验证令牌合法性即可。 - 若使用
email作为Cognito用户名,需确保用户池允许邮箱作为用户名,且开启邮箱唯一性验证。
内容的提问来源于stack exchange,提问作者moccasine
相关产品推荐
相关产品推荐

