Skip to content

Commit

Permalink
feat: AWS Lambda authorizer support (#478)
Browse files Browse the repository at this point in the history
* feat: AWS Lambda authorizer support

* feat: update error messages/comments

* create subscription pool

* subscription connection factory tests

* integration tests

* update integration tests instructions

* update integration tests instructions

* clean up http transport logic

* fix lint error

* LambdaAuth interceptor

* add more unit tests

* add connection pool unit test
  • Loading branch information
diegocstn authored Jul 29, 2021
1 parent 9c7385d commit 8428fff
Show file tree
Hide file tree
Showing 19 changed files with 558 additions and 15 deletions.
16 changes: 16 additions & 0 deletions AWSAppSyncClient.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@
21D5286A2416A2B3005186BA /* IAMAuthInterceptorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21D528692416A2B3005186BA /* IAMAuthInterceptorTests.swift */; };
3D9BF115227836800079F52F /* NetworkReachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9BF114227836800079F52F /* NetworkReachability.swift */; };
70C68E4D132FE62623DB8C07 /* Pods_AWSAppSyncTestHostApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C707001F57B091A8A001CAB /* Pods_AWSAppSyncTestHostApp.framework */; };
7638897026A9E4D70061AF0B /* LambdaBasedConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7638896F26A9E4D70061AF0B /* LambdaBasedConnectionPool.swift */; };
763C857726B08D74005164B2 /* AWSAppSyncLambdaAuthTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763C857626B08D74005164B2 /* AWSAppSyncLambdaAuthTests.swift */; };
763C857926B1C262005164B2 /* LambdaAuthInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763C857826B1C262005164B2 /* LambdaAuthInterceptor.swift */; };
763C857B26B1CB18005164B2 /* LambdaBasedConnectionPoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763C857A26B1CB18005164B2 /* LambdaBasedConnectionPoolTests.swift */; };
8032C5415EF414C038394D69 /* Pods_AWSAppSyncTestCommon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 74071C397A83DEA980BB2F4C /* Pods_AWSAppSyncTestCommon.framework */; };
90DE0C49240A304D000E875B /* AWSAppSyncAuthTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90DE0C48240A304D000E875B /* AWSAppSyncAuthTypeTests.swift */; };
A70604C0C722923A70C937A1 /* Pods_AWSAppSyncTestApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57F5A94352E1ABE35159489D /* Pods_AWSAppSyncTestApp.framework */; };
Expand Down Expand Up @@ -510,6 +514,10 @@
6878E4A0F7372438C7043A88 /* Pods_AWSAppSync_AWSAppSyncTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AWSAppSync_AWSAppSyncTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74071C397A83DEA980BB2F4C /* Pods_AWSAppSyncTestCommon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AWSAppSyncTestCommon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
741880AF213878B400523CA8 /* AuthProviderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthProviderTests.swift; sourceTree = "<group>"; };
7638896F26A9E4D70061AF0B /* LambdaBasedConnectionPool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LambdaBasedConnectionPool.swift; sourceTree = "<group>"; };
763C857626B08D74005164B2 /* AWSAppSyncLambdaAuthTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AWSAppSyncLambdaAuthTests.swift; sourceTree = "<group>"; };
763C857826B1C262005164B2 /* LambdaAuthInterceptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LambdaAuthInterceptor.swift; sourceTree = "<group>"; };
763C857A26B1CB18005164B2 /* LambdaBasedConnectionPoolTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LambdaBasedConnectionPoolTests.swift; sourceTree = "<group>"; };
82E714A3E9BFB80BD9E5EF90 /* Pods-ApolloTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ApolloTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ApolloTests/Pods-ApolloTests.debug.xcconfig"; sourceTree = "<group>"; };
8623D545D4837963CF2FFF02 /* Pods-AWSAppSyncUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AWSAppSyncUnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AWSAppSyncUnitTests/Pods-AWSAppSyncUnitTests.debug.xcconfig"; sourceTree = "<group>"; };
8C707001F57B091A8A001CAB /* Pods_AWSAppSyncTestHostApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AWSAppSyncTestHostApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -958,6 +966,7 @@
2171807B23FDB22B00E520C9 /* SubscriptionConnectionFactory.swift */,
2171808123FDB22B00E520C9 /* UserPoolsBasedConnectionPool.swift */,
21D38B91240C099900EC2A8D /* AppSyncRealTimeClientOIDCAuthProvider.swift */,
7638896F26A9E4D70061AF0B /* LambdaBasedConnectionPool.swift */,
);
path = SubscriptionFactory;
sourceTree = "<group>";
Expand All @@ -970,6 +979,7 @@
2171808C23FDB28100E520C9 /* UserPoolsBasedConnectionPoolTests.swift */,
2171808D23FDB28100E520C9 /* OIDCBasedConnectionPoolTests.swift */,
2171808E23FDB28100E520C9 /* IAMBasedConnectionPoolTests.swift */,
763C857A26B1CB18005164B2 /* LambdaBasedConnectionPoolTests.swift */,
);
path = ConnectionPool;
sourceTree = "<group>";
Expand All @@ -978,6 +988,7 @@
isa = PBXGroup;
children = (
21D5286224169CEE005186BA /* IAMAuthInterceptor.swift */,
763C857826B1C262005164B2 /* LambdaAuthInterceptor.swift */,
);
path = AuthInterceptor;
sourceTree = "<group>";
Expand Down Expand Up @@ -1106,6 +1117,7 @@
FAFD409121D702EA0063D894 /* Helpers */,
FADC6B8822679B00008588FC /* Resources */,
741880AF213878B400523CA8 /* AuthProviderTests.swift */,
763C857626B08D74005164B2 /* AWSAppSyncLambdaAuthTests.swift */,
17664128214F6732003AE269 /* AWSAppSyncAPIKeyAuthTests.swift */,
174F80AE2109229C00775D0D /* AWSAppSyncCognitoAuthTests.swift */,
E48168AD226E8325005A1A41 /* AWSAppSyncMultiAuthClientsTests.swift */,
Expand Down Expand Up @@ -1967,6 +1979,7 @@
17E009BB1FCAB234005031DB /* GraphQLDependencyTracker.swift in Sources */,
17E009C71FCAB234005031DB /* JSONSerializationFormat.swift in Sources */,
17E009CD1FCAB234005031DB /* Collections.swift in Sources */,
763C857926B1C262005164B2 /* LambdaAuthInterceptor.swift in Sources */,
17E009C51FCAB234005031DB /* GraphQLResultAccumulator.swift in Sources */,
178B31071FCDB34100EA4619 /* AWSAppSyncClientS3ObjectsExtensions.swift in Sources */,
17E009CF1FCAB234005031DB /* ResultOrPromise.swift in Sources */,
Expand Down Expand Up @@ -2003,6 +2016,7 @@
CCEF79DD21DE7EED004AD64D /* AWSAppSyncClientError.swift in Sources */,
FA0C12BB21CD308A00B438CB /* AWSAppSyncClientConfiguration.swift in Sources */,
178B31081FCDB34100EA4619 /* AWSAppSyncClientConflictResolutionExtensions.swift in Sources */,
7638897026A9E4D70061AF0B /* LambdaBasedConnectionPool.swift in Sources */,
1729A0D01FA1365900F88594 /* AWSAppSyncSubscriptionWatcher.swift in Sources */,
FA0D82582230D0AF00E0EA82 /* AWSAppSyncSubscriptionError.swift in Sources */,
FAAACC2421DD7AC600D24B37 /* InternalS3ObjectDetails.swift in Sources */,
Expand Down Expand Up @@ -2064,6 +2078,7 @@
21933B3E24DA629B00F4D741 /* JSONValueSerializationTests.swift in Sources */,
E47789592284B3DC008E7D6E /* MockAWSAppSyncServiceConfig.swift in Sources */,
FA4F0D9521D6ED9E0099D165 /* AppSyncClientComplexObjectMutationUnitTests.swift in Sources */,
763C857B26B1CB18005164B2 /* LambdaBasedConnectionPoolTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -2073,6 +2088,7 @@
files = (
FADC6B8922679B38008588FC /* MutationQueuePerformanceTests.swift in Sources */,
FA902D0E21D97E9600C4052F /* AuthProviderTests.swift in Sources */,
763C857726B08D74005164B2 /* AWSAppSyncLambdaAuthTests.swift in Sources */,
FA902D1021D97EB100C4052F /* AWSAppSyncCognitoAuthTests.swift in Sources */,
E414DDB52289BD8A004C37CE /* AWSAppSyncMultiAuthClientsTests.swift in Sources */,
FA902D1321D97EC500C4052F /* SubscriptionStressTestHelper.swift in Sources */,
Expand Down
33 changes: 27 additions & 6 deletions AWSAppSyncClient/AWSAppSyncAuthProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// AWSAppSync
//

// MARK: AWSOIDCAuthProvider
// For using OIDC based authorization, this protocol needs to be implemented and passed to configuration object.
// Use this for cases where the OIDC token needs to be fetched asynchronously and requires a callback
public protocol AWSOIDCAuthProviderAsync: AWSOIDCAuthProvider {
Expand All @@ -14,6 +15,13 @@ extension AWSOIDCAuthProviderAsync {
public func getLatestAuthToken() -> String { fatalError("Callback method required") }
}

// For using OIDC based authorization, this protocol needs to be implemented and passed to configuration object.
public protocol AWSOIDCAuthProvider {
/// The method should fetch the token and return it to the client for using in header request.
func getLatestAuthToken() -> String
}

// MARK: - AWSCognitoUserPoolsProvider
// For using User Pool based authorization, this protocol needs to be implemented and passed to configuration object.
// Use this for cases where the UserPool auth token needs to be fetched asynchronously and requires a callback
public protocol AWSCognitoUserPoolsAuthProviderAsync: AWSCognitoUserPoolsAuthProvider {
Expand All @@ -25,17 +33,30 @@ extension AWSCognitoUserPoolsAuthProviderAsync {
public func getLatestAuthToken() -> String { fatalError("Callback method required") }
}

// For using OIDC based authorization, this protocol needs to be implemented and passed to configuration object.
public protocol AWSOIDCAuthProvider {
/// The method should fetch the token and return it to the client for using in header request.
func getLatestAuthToken() -> String
}

// For using Cognito User Pools based authorization, this protocol needs to be implemented and passed to configuration object.
public protocol AWSCognitoUserPoolsAuthProvider: AWSOIDCAuthProvider {

}

// MARK: - AWSLambdaAuthProvider
// For using Lambda based authorization, this protocol needs to be implemented and passed to configuration object.
// Use this for cases where the authorization token needs to be fetched asynchronously and requires a callback
public protocol AWSLambdaAuthProviderAsync: AWSLambdaAuthProvider {
func getLatestAuthToken(_ callback: @escaping (String?, Error?) -> Void)
}

// For AWSLambdaAuthProvider that use a callback, the getLatestAuthToken is defaulted to return an empty string
extension AWSLambdaAuthProviderAsync {
public func getLatestAuthToken() -> String { fatalError("Callback method required") }
}

// For using AWS Lambda based authorization, this protocol needs to be implemented and passed to configuration object.
public protocol AWSLambdaAuthProvider {
/// The method should fetch the token and return it to the client for using in header request.
func getLatestAuthToken() -> String
}

// MARK: - AWSAPIKeyAuthProvider
// For using API Key based authorization, this protocol needs to be implemented and passed to configuration object.
public protocol AWSAPIKeyAuthProvider {
func getAPIKey() -> String
Expand Down
2 changes: 2 additions & 0 deletions AWSAppSyncClient/AWSAppSyncAuthType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public enum AWSAppSyncAuthType: String, Codable, Hashable {

/// User directory based authentication
case amazonCognitoUserPools = "AMAZON_COGNITO_USER_POOLS"

case awsLambda = "AWS_LAMBDA"

/// Convenience method to use instead of `AuthType(rawValue:)`
public static func getAuthType(rawValue: String) throws -> AWSAppSyncAuthType {
Expand Down
Loading

0 comments on commit 8428fff

Please sign in to comment.