Skip to content

Commit 2cf63ff

Browse files
authored
add support for IAM authorizers (#41)
* add support for IAM authorizers * add support for cognito identities inside IAM authentication block
1 parent 3ac078f commit 2cf63ff

8 files changed

+200
-1
lines changed

Sources/AWSLambdaEvents/APIGateway+V2.swift

+22-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,26 @@ public struct APIGatewayV2Request: Codable {
3232
public let scopes: [String]?
3333
}
3434

35-
public let jwt: JWT
35+
public let jwt: JWT?
36+
37+
// `IAM` contains AWS IAM authorizer information for the request context.
38+
public struct IAM: Codable {
39+
public struct CognitoIdentity: Codable {
40+
public let amr: [String]?
41+
public let identityId: String?
42+
public let identityPoolId: String?
43+
}
44+
45+
public let accessKey: String?
46+
public let accountId: String?
47+
public let callerId: String?
48+
public let cognitoIdentity: CognitoIdentity?
49+
public let principalOrgId: String?
50+
public let userArn: String?
51+
public let userId: String?
52+
}
53+
54+
public let iam: IAM?
3655
}
3756

3857
public let accountId: String
@@ -113,5 +132,7 @@ extension APIGatewayV2Request.Context: Sendable {}
113132
extension APIGatewayV2Request.Context.HTTP: Sendable {}
114133
extension APIGatewayV2Request.Context.Authorizer: Sendable {}
115134
extension APIGatewayV2Request.Context.Authorizer.JWT: Sendable {}
135+
extension APIGatewayV2Request.Context.Authorizer.IAM: Sendable {}
136+
extension APIGatewayV2Request.Context.Authorizer.IAM.CognitoIdentity: Sendable {}
116137
extension APIGatewayV2Response: Sendable {}
117138
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2017-2020 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
@testable import AWSLambdaEvents
16+
import XCTest
17+
18+
class APIGatewayV2IAMTests: XCTestCase {
19+
static let getEventWithIAM = """
20+
{
21+
"version": "2.0",
22+
"routeKey": "$default",
23+
"rawPath": "/hello",
24+
"rawQueryString": "",
25+
"headers": {
26+
"accept": "*/*",
27+
"authorization": "AWS4-HMAC-SHA256 Credential=ASIA-redacted/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=289b5fcef3d1156f019cc1140cb5565cc052880a5a0d5586c753e3e3c75556f9",
28+
"content-length": "0",
29+
"host": "74bxj8iqjc.execute-api.us-east-1.amazonaws.com",
30+
"user-agent": "curl/8.4.0",
31+
"x-amz-date": "20231214T203121Z",
32+
"x-amz-security-token": "IQoJb3JpZ2luX2VjEO3//////////-redacted",
33+
"x-amzn-trace-id": "Root=1-657b6619-3222de40051925dd66e1fd72",
34+
"x-forwarded-for": "191.95.150.52",
35+
"x-forwarded-port": "443",
36+
"x-forwarded-proto": "https"
37+
},
38+
"requestContext": {
39+
"accountId": "012345678912",
40+
"apiId": "74bxj8iqjc",
41+
"authorizer": {
42+
"iam": {
43+
"accessKey": "ASIA-redacted",
44+
"accountId": "012345678912",
45+
"callerId": "AIDA-redacted",
46+
"cognitoIdentity": null,
47+
"principalOrgId": "aws:PrincipalOrgID",
48+
"userArn": "arn:aws:iam::012345678912:user/sst",
49+
"userId": "AIDA-redacted"
50+
}
51+
},
52+
"domainName": "74bxj8iqjc.execute-api.us-east-1.amazonaws.com",
53+
"domainPrefix": "74bxj8iqjc",
54+
"http": {
55+
"method": "GET",
56+
"path": "/liveness",
57+
"protocol": "HTTP/1.1",
58+
"sourceIp": "191.95.150.52",
59+
"userAgent": "curl/8.4.0"
60+
},
61+
"requestId": "P8zkDiQ8oAMEJsQ=",
62+
"routeKey": "$default",
63+
"stage": "$default",
64+
"time": "14/Dec/2023:20:31:21 +0000",
65+
"timeEpoch": 1702585881671
66+
},
67+
"isBase64Encoded": false
68+
}
69+
"""
70+
71+
static let getEventWithIAMAndCognito = """
72+
{
73+
"version": "2.0",
74+
"routeKey": "$default",
75+
"rawPath": "/hello",
76+
"rawQueryString": "",
77+
"headers": {
78+
"accept": "*/*",
79+
"authorization": "AWS4-HMAC-SHA256 Credential=ASIA-redacted/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=289b5fcef3d1156f019cc1140cb5565cc052880a5a0d5586c753e3e3c75556f9",
80+
"content-length": "0",
81+
"host": "74bxj8iqjc.execute-api.us-east-1.amazonaws.com",
82+
"user-agent": "curl/8.4.0",
83+
"x-amz-date": "20231214T203121Z",
84+
"x-amz-security-token": "IQoJb3JpZ2luX2VjEO3//////////-redacted",
85+
"x-amzn-trace-id": "Root=1-657b6619-3222de40051925dd66e1fd72",
86+
"x-forwarded-for": "191.95.150.52",
87+
"x-forwarded-port": "443",
88+
"x-forwarded-proto": "https"
89+
},
90+
"requestContext": {
91+
"accountId": "012345678912",
92+
"apiId": "74bxj8iqjc",
93+
"authorizer": {
94+
"iam": {
95+
"accessKey": "ASIA-redacted",
96+
"accountId": "012345678912",
97+
"callerId": "AROA-redacted:CognitoIdentityCredentials",
98+
"cognitoIdentity": {
99+
"amr": [
100+
"authenticated",
101+
"cognito-idp.us-east-1.amazonaws.com/us-east-1_ABCD",
102+
"cognito-idp.us-east-1.amazonaws.com/us-east-1_ABCD:CognitoSignIn:04611e3d--redacted"
103+
],
104+
"identityId": "us-east-1:68bc0ecd-9d5e--redacted",
105+
"identityPoolId": "us-east-1:e8b526df--redacted"
106+
},
107+
"principalOrgId": "aws:PrincipalOrgID",
108+
"userArn": "arn:aws:sts::012345678912:assumed-role/authRole/CognitoIdentityCredentials",
109+
"userId": "AROA-redacted:CognitoIdentityCredentials"
110+
}
111+
},
112+
"domainName": "74bxj8iqjc.execute-api.us-east-1.amazonaws.com",
113+
"domainPrefix": "74bxj8iqjc",
114+
"http": {
115+
"method": "GET",
116+
"path": "/liveness",
117+
"protocol": "HTTP/1.1",
118+
"sourceIp": "191.95.150.52",
119+
"userAgent": "curl/8.4.0"
120+
},
121+
"requestId": "P8zkDiQ8oAMEJsQ=",
122+
"routeKey": "$default",
123+
"stage": "$default",
124+
"time": "14/Dec/2023:20:31:21 +0000",
125+
"timeEpoch": 1702585881671
126+
},
127+
"isBase64Encoded": false
128+
}
129+
"""
130+
131+
// MARK: - Request -
132+
133+
// MARK: Decoding
134+
135+
func testRequestDecodingGetRequestWithIAM() {
136+
let data = APIGatewayV2IAMTests.getEventWithIAM.data(using: .utf8)!
137+
var req: APIGatewayV2Request?
138+
XCTAssertNoThrow(req = try JSONDecoder().decode(APIGatewayV2Request.self, from: data))
139+
140+
XCTAssertEqual(req?.rawPath, "/hello")
141+
XCTAssertEqual(req?.context.authorizer?.iam?.accessKey, "ASIA-redacted")
142+
XCTAssertEqual(req?.context.authorizer?.iam?.accountId, "012345678912")
143+
XCTAssertNil(req?.body)
144+
}
145+
146+
func testRequestDecodingGetRequestWithIAMWithCognito() {
147+
let data = APIGatewayV2IAMTests.getEventWithIAMAndCognito.data(using: .utf8)!
148+
var req: APIGatewayV2Request?
149+
XCTAssertNoThrow(req = try JSONDecoder().decode(APIGatewayV2Request.self, from: data))
150+
151+
XCTAssertEqual(req?.rawPath, "/hello")
152+
XCTAssertEqual(req?.context.authorizer?.iam?.accessKey, "ASIA-redacted")
153+
XCTAssertEqual(req?.context.authorizer?.iam?.accountId, "012345678912")
154+
155+
// test the cognito identity part
156+
XCTAssertEqual(req?.context.authorizer?.iam?.cognitoIdentity?.identityId, "us-east-1:68bc0ecd-9d5e--redacted")
157+
XCTAssertEqual(req?.context.authorizer?.iam?.cognitoIdentity?.amr?.count, 3)
158+
159+
XCTAssertNil(req?.body)
160+
}
161+
}

Tests/AWSLambdaEventsTests/APIGateway+V2Tests.swift

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ class APIGatewayV2Tests: XCTestCase {
8686
XCTAssertEqual(req?.queryStringParameters?.count, 1)
8787
XCTAssertEqual(req?.rawQueryString, "foo=bar")
8888
XCTAssertEqual(req?.headers.count, 8)
89+
XCTAssertEqual(req?.context.authorizer?.jwt?.claims?["aud"], "customers")
90+
8991
XCTAssertNil(req?.body)
9092
}
9193
}

docker/docker-compose.al2.56.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ services:
88
args:
99
swift_version: "5.6"
1010

11+
soundness:
12+
image: swift-aws-lambda-events:al2-5.6
13+
1114
test:
1215
image: swift-aws-lambda-events:al2-5.6
1316

docker/docker-compose.al2.57.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ services:
88
args:
99
swift_version: "5.7"
1010

11+
soundness:
12+
image: swift-aws-lambda-events:al2-5.7
13+
1114
test:
1215
image: swift-aws-lambda-events:al2-5.7
1316

docker/docker-compose.al2.58.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ services:
88
args:
99
swift_version: "5.8"
1010

11+
soundness:
12+
image: swift-aws-lambda-events:al2-5.8
13+
1114
test:
1215
image: swift-aws-lambda-events:al2-5.8
1316

docker/docker-compose.al2.59.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ services:
88
args:
99
base_image: "swiftlang/swift:nightly-5.9-amazonlinux2"
1010

11+
soundness:
12+
image: swift-aws-lambda-events:al2-5.9
13+
1114
test:
1215
image: swift-aws-lambda-events:al2-5.9
1316

docker/docker-compose.al2.main.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ services:
88
args:
99
base_image: "swiftlang/swift:nightly-main-amazonlinux2"
1010

11+
soundness:
12+
image: swift-aws-lambda-events:al2-main
13+
1114
test:
1215
image: swift-aws-lambda-events:al2-main
1316

0 commit comments

Comments
 (0)