在 DotNet 中创建 AWS Cognito PreSignup Lambda
Posted
技术标签:
【中文标题】在 DotNet 中创建 AWS Cognito PreSignup Lambda【英文标题】:Creating a AWS Cognito PreSignup Lambda in DotNet 【发布时间】:2017-10-24 03:08:31 【问题描述】:使用 .Net Core 1.0 Lambda 我希望能够创建一个 Lambda 函数来处理来自 AWS Cognito 用户池的 PreSignUp 触发器。
using Amazon.Lambda.Core;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
public class PreSignUp_SignUp
public string userPoolId get; set;
public const string EmailKey = "email";
public const string PhoneNumber = "phone_number";
public Dictionary<string,string> userAttributes get; set;
public Dictionary<string, string> validationData get; set;
public class PreSignup_SignUpResponse
public bool autoConfirmUser get; set;
public class Function
public PreSignup_SignUpResponse FunctionHandler(PreSignUp_SignUp input, ILambdaContext context)
return new PreSignup_SignUpResponse autoConfirmUser = true ;
虽然请求成功并在调用 Lambda 时返回响应,但示例请求如下:
"datasetName": "datasetName",
"eventType": "SyncTrigger",
"region": "us-east-1",
"identityId": "identityId",
"datasetRecords":
"SampleKey2":
"newValue": "newValue2",
"oldValue": "oldValue2",
"op": "replace"
,
"SampleKey1":
"newValue": "newValue1",
"oldValue": "oldValue1",
"op": "replace"
,
"identityPoolId": "identityPoolId",
"version": 2
通过 .Net AmazonCognitoIdentityProviderClient 执行实际注册时,我收到错误消息:
Amazon.CognitoIdentityProvider.Model.InvalidLambdaResponseException : 无法识别的 lambda 输出
我猜这意味着我没有得到正确的响应(甚至可能是请求)的形状。
是否有人提供适用于 AWS Cognito 中 PreSignUp 触发器的 .Net Lambda 函数示例?
【问题讨论】:
【参考方案1】:认知触发器请求/响应必须包含认知触发器文档中指定的整个有效负载:
http://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html
在诊断此问题时,我发现最好的起点是创建一个函数处理程序,该处理程序接受一个 JObject,然后记录并返回相同的对象,例如
public JObject FunctionHandler(JObject input, ILambdaContext context)
context.Logger.LogLine("Input was: " + input);
return input;
这会在 cloudwatch 日志中捕获有效负载,然后帮助引导您实现所需的强类型结构化。
在我的 PreSignUp 案例中,我最终创建了以下类型来创建一个简单的函数,该函数可以自动验证所有提供的凭据。
public abstract class AbstractTriggerRequest
[JsonProperty("userAttributes")]
public Dictionary<string, string> UserAttributes get; set;
public abstract class AbstractTriggerResponse
public class TriggerCallerContext
[JsonProperty("awsSdkVersion")]
public string AwsSdkVersion get; set;
[JsonProperty("clientId")]
public string ClientId get; set;
public abstract class AbstractTriggerBase<TRequest, TResponse>
where TRequest: AbstractTriggerRequest
where TResponse: AbstractTriggerResponse
[JsonProperty("version")]
public int Version get; set;
[JsonProperty("triggerSource")]
public string TriggerSource get; set;
[JsonProperty("region")]
public string Region get; set;
[JsonProperty("userPoolId")]
public string UserPoolId get; set;
[JsonProperty("callerContext")]
public TriggerCallerContext CallerContext get; set;
[JsonProperty("request")]
public TRequest Request get; set;
[JsonProperty("response")]
public TResponse Response get; set;
[JsonProperty("userName", NullValueHandling = NullValueHandling.Ignore)]
public string UserName get; set;
public class PreSignUpSignUpRequest : AbstractTriggerRequest
[JsonProperty("validationData")]
public Dictionary<string,string> ValidationData get; set;
然后,Lambda 函数以以下签名结束:
public class Function
public PreSignUp_SignUp FunctionHandler(PreSignUp_SignUp input, ILambdaContext context)
context.Logger.LogLine("Auto-confirming everything!");
input.Response = new PreSignUpSignUpResponse
AutoConfirmUser = true,
// you can only auto-verify email or phone if it's present in the user attributes
AutoVerifyEmail = input.Request.UserAttributes.ContainsKey("email"),
AutoVerifyPhone = input.Request.UserAttributes.ContainsKey("phone_number")
;
return input;
希望这可以帮助其他在为 Cognito 编写 Lambda 触发器时遇到问题的人。
【讨论】:
这是一个很好的答案,但也请查看 DaddyCoder 对 .netcore 3.1 应用程序语法更新的响应,因为您可能会使用新的 JSON 序列化程序【参考方案2】:除非您仍然使用旧的、性能较低的 Amazon.Lambda.Serialization.Json.JsonSerializer
,否则之前的两个响应现在不准确。这个旧的序列化程序使用Newtonsoft.Json
,而新的Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer
实现了最近的System.Text.Json
。
因此,JObject
参数不再适用,而应替换为 JsonElement
。如果你尝试将JObject
与这个新的序列化程序一起使用,你会得到一个错误,因为序列化程序不知道如何处理这个对象。
您应该阅读this 以更好地了解它的工作原理,但您可以使用GetProperty("[insert property name here]")
访问JsonElement
的属性。
例如:
public async Task<JsonElement> FunctionHandler(JsonElement input, ILambdaContext context)
var request = input.GetProperty("request");
var userAttributes = request.GetProperty("userAttributes");
string email = userAttributes.GetProperty("email").GetString();
return input;
这样,您无需构建整个类来容纳所需的请求和响应参数,只需获取和设置您需要的属性即可。
【讨论】:
这是正确的。 JsonElement 类也可以很好地记录日志,因此按照 Bittercoder 推荐的记录输入的起点,您仍然可以使用以下语法:context.Logger.LogLine("Input was: " + input);
查看 Cloudwatch 日志中的请求负载。【参考方案3】:
这里已经有另一个很好的答案了。不过我不是 .NET 开发专家,所以这个解决方案对我来说更有意义。
class AutoVerifyEmail
public AutoVerifyEmail()
public JObject AutoVerifyEmailPreSignup(JObject input, ILambdaContext context)
//Console.Write(input); //Print Input
input["response"]["autoVerifyEmail"] = true;
input["response"]["autoConfirmUser"] = true;
return input;
【讨论】:
以上是关于在 DotNet 中创建 AWS Cognito PreSignup Lambda的主要内容,如果未能解决你的问题,请参考以下文章
AWS Amplify AppSync 使用在 Cognito 中创建的 Google 用户登录
如何在 Keycloak 中创建客户端以与 AWS Cognito 身份联合使用
AWS Cognito - SerializationException(在不期望的地方找到结构或映射的开始)