swift-aws-lambda-runtime
swift-aws-lambda-runtime copied to clipboard
Lambda Authorizer - APIGateway.Request
Expected behavior
Obtain information passed from a Lambda Authorizer into Lambda.
Note: This is the REST API (V1)
Actual behavior
Inability to access information due to parameter not existing on APIGateway.Request
If possible, minimal yet complete reproducer code (or URL to code)
{
...
"requestContext": {
"authorizer": {
"principalId": "user-id",
"integrationLatency": 557
}
}
...
}
Maybe it makes sense to add this to APIGateway.Request.
public let authorizer: Authorizer?
public struct Authorizer: Codable {
public let principalId: String
public let context: [String: String]?
}
// OR
public let authorizer: [String: String]?
thanks for reporting @rmickeyd ~is this issue while using lambda vi api gateway?~ is this the feature you are referring to?
wdyt @fabianfett
@tomerd yes, this is the feature. Decoding might not be straight forward though. It seems when you generate an IAM policy you set a principalId which seems to always be present and then user defined attributes. The issue is AWS sends this all lumped together in one container like so:
"requestContext": {
"authorizer": {
"principalId": "user-id",
"integrationLatency": 557,
"userDefinedString": "stringval",
"userDefinedNumber": 123,
"userDefinedBool": true
}
}
I see. any ideas on how to do this generically or should it be left as exercise for the Lambda author?
imo the critical piece of information is the principalId. This is what should identify the user that made the authenticated call. I think it would make sense to ensure that is clearly exposed and then leave it up to the author to convert any other values from strings to whatever type they are attempting to pass through. Otherwise, we would need an extension to decode [String: Any] but with this method casting would be needed for every type including strings so the value in doing this is limited.
I think something like this would make the most sense:
public let authorizer: Authorizer?
public struct Authorizer: Codable {
public let principalId: String
public let context: [String: String]
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.principalId = try container.decode(String.self, forKey: .principalId)
self.context = try decoder.singleValueContainer().decode(Dictionary<String, String>.self)
}
}
If this sounds good I can throw up a PR with this implemented.
sounds fine to me if it works correctly. @fabianfett opinion?
sounds fine to me if it works correctly. @fabianfett opinion?
+1 from my side. We'll definitely need unit tests for this.
@bmoffatt Is there any document that describes all Authorizer
payloads? Can we assume that will always be a dictionary with just String values and at least the principalId
key?
Go uses interface{}
for the values... https://github.com/aws/aws-lambda-go/blob/eebb9958b0b4c19edcfdff58326d0bf40e8ddf6b/events/apigw.go#L43
The closest thing that we have is AnyCodable, but I guess we don't want to add another dependency?
C# uses a [String: String]
dictionary: https://github.com/aws/aws-lambda-dotnet/blob/e2bb81a4b48a402570b0de828772067938ca5671/Libraries/src/Amazon.Lambda.APIGatewayEvents/APIGatewayCustomAuthorizerContext.cs#L114
And thanks for reporting @rmickeyd. Because of the problems outlined above, I refrained from this feature so far. But we should definitely do something about it!
Hi,
I have the same issue but I can't see the modified code or a PR with it.
Any news on this? Was this implemented?
I've added a PR with a [String:String] dictionary.
In my use case (Cognito -> API Gateway -> Lambda), I don't receive a 'principalID' key.