From bc9d2f39f4a5cb2a87b623ac22cc3c7ba87abd54 Mon Sep 17 00:00:00 2001 From: Zeeshan Sheikh Date: Tue, 17 Sep 2024 15:39:35 +0500 Subject: [PATCH 1/2] ALS-1861: By passing any default authentication in case of API key and only use api key for authentication --- Package.resolved | 16 +++--- Package.swift | 2 +- .../Auth/AuthHelper.swift | 31 +++++++--- .../Client/AmazonLocationClient.swift | 31 +++++++--- .../Client/ApiKeyAuthScheme.swift | 52 +++++++++++++++++ .../AuthHelperTests.swift | 56 ++++++++++++++++--- 6 files changed, 153 insertions(+), 35 deletions(-) create mode 100644 Sources/AmazonLocationiOSAuthSDK/Client/ApiKeyAuthScheme.swift diff --git a/Package.resolved b/Package.resolved index 86e8c78..a4329cd 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/awslabs/aws-crt-swift", "state" : { - "revision" : "b6380f683b31072d77b601c88674461c11bcad5a", - "version" : "0.30.0" + "revision" : "26be7379c9d74ccf0a32d4429181ef06d72683f6", + "version" : "0.33.0" } }, { @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/awslabs/aws-sdk-swift", "state" : { - "branch" : "0.46.0", - "revision" : "3c20e0be8c8246de8b8e04372404ef1f90be71b6" + "revision" : "473ead298e380f632336daedc6d5b6a2dd574ee1", + "version" : "0.76.1" } }, { @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/smithy-lang/smithy-swift", "state" : { - "revision" : "b2322a067f85c230f17c80be8a67dd543454b081", - "version" : "0.51.0" + "revision" : "03e9d7279fff38042f9aed986a7fbd31ad37b30d", + "version" : "0.67.0" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-log.git", "state" : { - "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", - "version" : "1.6.1" + "revision" : "e97a6fcb1ab07462881ac165fdbb37f067e205d5", + "version" : "1.5.4" } } ], diff --git a/Package.swift b/Package.swift index 509225f..ab1c90e 100644 --- a/Package.swift +++ b/Package.swift @@ -15,7 +15,7 @@ let package = Package( dependencies: [ // Dependencies declare other packages that this package depends on. .package(url: "https://github.com/evgenyneu/keychain-swift.git", from: "20.0.0"), - .package(url: "https://github.com/awslabs/aws-sdk-swift", branch: "0.46.0") + .package(url: "https://github.com/awslabs/aws-sdk-swift", from: "0.76.1") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Sources/AmazonLocationiOSAuthSDK/Auth/AuthHelper.swift b/Sources/AmazonLocationiOSAuthSDK/Auth/AuthHelper.swift index 0ca2ffa..3764baf 100644 --- a/Sources/AmazonLocationiOSAuthSDK/Auth/AuthHelper.swift +++ b/Sources/AmazonLocationiOSAuthSDK/Auth/AuthHelper.swift @@ -1,10 +1,12 @@ import Foundation +import AWSLocation import AwsCommonRuntimeKit @objc public class AuthHelper: NSObject { private var locationCredentialsProvider: LocationCredentialsProvider? - + private var amazonLocationClient: AmazonLocationClient? + @objc public override init() { } @@ -22,29 +24,40 @@ import AwsCommonRuntimeKit private func authenticateWithCognitoIdentityPoolAndRegion(identityPoolId: String, region: String) async throws -> LocationCredentialsProvider? { let credentialProvider = LocationCredentialsProvider(region: region, identityPoolId: identityPoolId) credentialProvider.setRegion(region: region) - try await credentialProvider.getCognitoProvider()?.refreshCognitoCredentialsIfExpired() + amazonLocationClient = AmazonLocationClient(locationCredentialsProvider: credentialProvider) + try await amazonLocationClient?.initialiseLocationClient() return credentialProvider } - @objc public func authenticateWithApiKey(apiKey: String, region: String) -> LocationCredentialsProvider { + @objc public func authenticateWithApiKey(apiKey: String, region: String) async throws -> LocationCredentialsProvider? { let credentialProvider = LocationCredentialsProvider(region: region, apiKey: apiKey) credentialProvider.setAPIKey(apiKey: apiKey) credentialProvider.setRegion(region: region) - locationCredentialsProvider = credentialProvider + locationCredentialsProvider = credentialProvider + if let credentialsProvider = locationCredentialsProvider { + amazonLocationClient = AmazonLocationClient(locationCredentialsProvider: credentialsProvider) + try await amazonLocationClient?.initialiseLocationClient() + } return credentialProvider } public func authenticateWithCredentialsProvider(credentialsProvider: CredentialsProvider, region: String) async throws -> LocationCredentialsProvider? { let credentialProvider = LocationCredentialsProvider(credentialsProvider: credentialsProvider) credentialProvider.setRegion(region: region) + locationCredentialsProvider = credentialProvider + if let credentialsProvider = locationCredentialsProvider { + amazonLocationClient = AmazonLocationClient(locationCredentialsProvider: credentialsProvider) + } return credentialProvider } - @objc public func getLocationClient() -> AmazonLocationClient? + @objc public func getAmazonLocationClient() -> AmazonLocationClient? { - guard let locationCredentialsProvider = self.locationCredentialsProvider else { - return nil - } - return AmazonLocationClient(locationCredentialsProvider: locationCredentialsProvider) + return amazonLocationClient + } + + public func getLocationClient() -> LocationClient? + { + return amazonLocationClient?.locationClient } } diff --git a/Sources/AmazonLocationiOSAuthSDK/Client/AmazonLocationClient.swift b/Sources/AmazonLocationiOSAuthSDK/Client/AmazonLocationClient.swift index 1a43397..9d25217 100644 --- a/Sources/AmazonLocationiOSAuthSDK/Client/AmazonLocationClient.swift +++ b/Sources/AmazonLocationiOSAuthSDK/Client/AmazonLocationClient.swift @@ -1,7 +1,7 @@ import Foundation import AWSLocation import SmithyIdentity -import SmithyIdentityAPI +import SmithyHTTPAuthAPI public enum HTTPMethod: String { case GET @@ -43,9 +43,11 @@ public struct HTTPHeaders { } @objc public func initialiseLocationClient() async throws { - if let credentials = locationProvider.getCognitoProvider()?.getCognitoCredentials() { - - try await setLocationClient(accessKey: credentials.accessKeyId, secret: credentials.secretKey, expiration: credentials.expiration, sessionToken: credentials.sessionToken) + if let cognitoProvider = locationProvider.getCognitoProvider() { + try await cognitoProvider.refreshCognitoCredentialsIfExpired() + if let credentials = cognitoProvider.getCognitoCredentials() { + try await setLocationClient(accessKey: credentials.accessKeyId, secret: credentials.secretKey, expiration: credentials.expiration, sessionToken: credentials.sessionToken) + } } else if let credentialsProvider = locationProvider.getCustomCredentialsProvider() { @@ -55,13 +57,26 @@ public struct HTTPHeaders { try await setLocationClient(accessKey: accessKey, secret: secret, expiration: credentials.getExpiration(), sessionToken: credentials.getSessionToken()) } } + else if let apiProvider = locationProvider.getApiProvider(), + let apiKey = apiProvider.apiKey { + try await setLocationClient(apiKey: apiKey) + } } - private func setLocationClient(accessKey: String, secret: String, expiration: Date?, sessionToken: String?) async throws { - - let resolver: StaticAWSCredentialIdentityResolver? = try StaticAWSCredentialIdentityResolver(AWSCredentialIdentity(accessKey: accessKey, secret: secret, expiration: expiration, sessionToken: sessionToken)) - + private func setLocationClient(accessKey: String, secret: String, expiration: Date? = nil, sessionToken: String? = nil) async throws { + let credentialsIdentity = AWSCredentialIdentity(accessKey: accessKey, secret: secret, expiration: expiration, sessionToken: sessionToken) + let resolver: StaticAWSCredentialIdentityResolver? = try StaticAWSCredentialIdentityResolver(credentialsIdentity) let clientConfig = try await LocationClient.LocationClientConfiguration(awsCredentialIdentityResolver: resolver, region: locationProvider.getRegion(), signingRegion: locationProvider.getRegion()) + self.locationClient = LocationClient(config: clientConfig) + } + + private func setLocationClient(apiKey: String) async throws { + let resolver: AuthSchemeResolver = ApiKeyAuthSchemeResolver() + let signer = ApiKeySigner() + let authScheme: AuthScheme = ApiKeyAuthScheme(signer: signer) + let authSchemes: [AuthScheme] = [authScheme] + let region = locationProvider.getRegion() + let clientConfig = try await LocationClient.LocationClientConfiguration(region: region, authSchemes: authSchemes, authSchemeResolver: resolver) self.locationClient = LocationClient(config: clientConfig) } diff --git a/Sources/AmazonLocationiOSAuthSDK/Client/ApiKeyAuthScheme.swift b/Sources/AmazonLocationiOSAuthSDK/Client/ApiKeyAuthScheme.swift new file mode 100644 index 0000000..5f493d8 --- /dev/null +++ b/Sources/AmazonLocationiOSAuthSDK/Client/ApiKeyAuthScheme.swift @@ -0,0 +1,52 @@ +import SmithyHTTPAuthAPI +import Smithy +import SmithyHTTPAPI + +public let apiKeyAuthSchemeID: String = "smithy.api#noAuth" + +public struct ApiKeyAuthScheme: AuthScheme { + public var schemeID: String = apiKeyAuthSchemeID + public var signer: any SmithyHTTPAuthAPI.Signer + + public func customizeSigningProperties( + signingProperties: Smithy.Attributes, + context: Smithy.Context + ) throws -> Smithy.Attributes { + return signingProperties + } +} + +public class ApiKeySigner: Signer { + public init() {} + + public func signRequest( + requestBuilder: SmithyHTTPAPI.HTTPRequestBuilder, + identity: IdentityT, + signingProperties: Smithy.Attributes + ) async throws -> SmithyHTTPAPI.HTTPRequestBuilder { + return requestBuilder + } +} + +public class ApiKeyAuthSchemeResolverParameters: AuthSchemeResolverParameters { + public var operation: String + public init(operation: String) { + self.operation = operation + } +} + +public class ApiKeyAuthSchemeResolver: AuthSchemeResolver { + public func resolveAuthScheme(params: AuthSchemeResolverParameters) throws -> [AuthOption] { + var validAuthOptions = Array() + validAuthOptions.append(AuthOption(schemeID: apiKeyAuthSchemeID)) + return validAuthOptions + } + + public func constructParameters(context: Context) throws -> AuthSchemeResolverParameters { + guard let opName = context.getOperation() else { + throw ClientError.dataNotFound( + "Operation name not configured in middleware context for auth scheme resolver params construction.") + } + return ApiKeyAuthSchemeResolverParameters(operation: opName) + } +} diff --git a/Tests/AmazonLocationiOSAuthSDKTests/AuthHelperTests.swift b/Tests/AmazonLocationiOSAuthSDKTests/AuthHelperTests.swift index e3d92e9..9b06a2c 100644 --- a/Tests/AmazonLocationiOSAuthSDKTests/AuthHelperTests.swift +++ b/Tests/AmazonLocationiOSAuthSDKTests/AuthHelperTests.swift @@ -2,6 +2,8 @@ import XCTest import Foundation @testable import AmazonLocationiOSAuthSDK import AwsCommonRuntimeKit +import CoreLocation +import AWSLocation final class AuthHelperTests: XCTestCase { @@ -25,9 +27,25 @@ final class AuthHelperTests: XCTestCase { let config = readTestConfig() let identityPoolID = config["identityPoolID"]! + let searchPlaceIndex = config["placeIndex"]! + let authHelper = AuthHelper() let authProvider = try? await authHelper.authenticateWithCognitoIdentityPool(identityPoolId: identityPoolID) XCTAssertEqual(authProvider!.getIdentityPoolId(), identityPoolID) + XCTAssertNotNil(authProvider?.getCognitoProvider()) + + let biasPosition = CLLocationCoordinate2D(latitude: 47.654502614244194, longitude: -122.35862564621954) + let locationClient = authHelper.getLocationClient() + let searchPlaceIndexForSuggestionsInput = SearchPlaceIndexForSuggestionsInput(biasPosition: [biasPosition.longitude, biasPosition.latitude], indexName: searchPlaceIndex, maxResults: 15, text: "Schools") + let response = try await locationClient?.searchPlaceIndexForSuggestions(input: searchPlaceIndexForSuggestionsInput) + + var searchResults: [String] = [] + if let results = response?.results { + for item in results { + searchResults.append((item.text)!) + } + } + XCTAssertNotEqual(searchResults.count, 0, "Search has results") } func testAuthWithIdentityPoolIDAndRegion() async throws { @@ -40,15 +58,35 @@ final class AuthHelperTests: XCTestCase { XCTAssertEqual(authProvider!.getIdentityPoolId(), identityPoolID) } - func testAuthWithAPIKey() throws { - let config = readTestConfig() - - let apiKey = config["apiKey"]! - let region = config["region"]! - - let authHelper = AuthHelper() - let authProvider = authHelper.authenticateWithApiKey(apiKey: apiKey, region: region) - XCTAssertNotNil(authProvider.getApiProvider()) + func testAuthWithAPIKey() async throws { + do { + let config = readTestConfig() + let apiKey = config["apiKey"]! + let region = config["region"]! + let searchPlaceIndex = config["placeIndex"]! + + let authHelper = AuthHelper() + let authProvider = try await authHelper.authenticateWithApiKey(apiKey: apiKey, region: region) + + XCTAssertNotNil(authProvider?.getApiProvider()) + + let biasPosition = CLLocationCoordinate2D(latitude: 47.654502614244194, longitude: -122.35862564621954) + let locationClient = authHelper.getLocationClient() + let searchPlaceIndexForSuggestionsInput = SearchPlaceIndexForSuggestionsInput(biasPosition: [biasPosition.longitude, biasPosition.latitude], indexName: searchPlaceIndex, key: apiKey, maxResults: 15, text: "Schools") + let response = try await locationClient?.searchPlaceIndexForSuggestions(input: searchPlaceIndexForSuggestionsInput) + + var searchResults: [String] = [] + if let results = response?.results { + for item in results { + searchResults.append((item.text)!) + } + } + XCTAssertNotEqual(searchResults.count, 0, "Search has results") + } + catch { + XCTFail(error.localizedDescription) + throw error + } } func testAuthWithCustomeCredentials() async throws { From 379c599adcb060b592af4f904b7583c556c71926 Mon Sep 17 00:00:00 2001 From: Zeeshan Sheikh Date: Thu, 19 Sep 2024 17:47:56 +0500 Subject: [PATCH 2/2] Fixed Custom credentials provider initialize location client --- Package.resolved | 16 +++++++------- .../Auth/AuthHelper.swift | 10 +++------ .../AuthHelperTests.swift | 21 ++++++++++++++++--- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Package.resolved b/Package.resolved index a4329cd..d097f8e 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/awslabs/aws-crt-swift", "state" : { - "revision" : "26be7379c9d74ccf0a32d4429181ef06d72683f6", - "version" : "0.33.0" + "revision" : "7b42e0343f28b3451aab20840dc670abd12790bd", + "version" : "0.36.0" } }, { @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/awslabs/aws-sdk-swift", "state" : { - "revision" : "473ead298e380f632336daedc6d5b6a2dd574ee1", - "version" : "0.76.1" + "revision" : "a41d3b3e01b9803a4a2e0c2273c2de4b3fd787a4", + "version" : "0.77.1" } }, { @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/smithy-lang/smithy-swift", "state" : { - "revision" : "03e9d7279fff38042f9aed986a7fbd31ad37b30d", - "version" : "0.67.0" + "revision" : "0ed3440f8c41e27a0937364d5035d2d4fefb8aa3", + "version" : "0.71.0" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-log.git", "state" : { - "revision" : "e97a6fcb1ab07462881ac165fdbb37f067e205d5", - "version" : "1.5.4" + "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", + "version" : "1.6.1" } } ], diff --git a/Sources/AmazonLocationiOSAuthSDK/Auth/AuthHelper.swift b/Sources/AmazonLocationiOSAuthSDK/Auth/AuthHelper.swift index 3764baf..57cbdd1 100644 --- a/Sources/AmazonLocationiOSAuthSDK/Auth/AuthHelper.swift +++ b/Sources/AmazonLocationiOSAuthSDK/Auth/AuthHelper.swift @@ -47,17 +47,13 @@ import AwsCommonRuntimeKit locationCredentialsProvider = credentialProvider if let credentialsProvider = locationCredentialsProvider { amazonLocationClient = AmazonLocationClient(locationCredentialsProvider: credentialsProvider) + try await amazonLocationClient?.initialiseLocationClient() } return credentialProvider } - - @objc public func getAmazonLocationClient() -> AmazonLocationClient? + + @objc public func getLocationClient() -> AmazonLocationClient? { return amazonLocationClient } - - public func getLocationClient() -> LocationClient? - { - return amazonLocationClient?.locationClient - } } diff --git a/Tests/AmazonLocationiOSAuthSDKTests/AuthHelperTests.swift b/Tests/AmazonLocationiOSAuthSDKTests/AuthHelperTests.swift index 9b06a2c..57d5e5a 100644 --- a/Tests/AmazonLocationiOSAuthSDKTests/AuthHelperTests.swift +++ b/Tests/AmazonLocationiOSAuthSDKTests/AuthHelperTests.swift @@ -35,7 +35,7 @@ final class AuthHelperTests: XCTestCase { XCTAssertNotNil(authProvider?.getCognitoProvider()) let biasPosition = CLLocationCoordinate2D(latitude: 47.654502614244194, longitude: -122.35862564621954) - let locationClient = authHelper.getLocationClient() + let locationClient = authHelper.getLocationClient()?.locationClient let searchPlaceIndexForSuggestionsInput = SearchPlaceIndexForSuggestionsInput(biasPosition: [biasPosition.longitude, biasPosition.latitude], indexName: searchPlaceIndex, maxResults: 15, text: "Schools") let response = try await locationClient?.searchPlaceIndexForSuggestions(input: searchPlaceIndexForSuggestionsInput) @@ -71,7 +71,7 @@ final class AuthHelperTests: XCTestCase { XCTAssertNotNil(authProvider?.getApiProvider()) let biasPosition = CLLocationCoordinate2D(latitude: 47.654502614244194, longitude: -122.35862564621954) - let locationClient = authHelper.getLocationClient() + let locationClient = authHelper.getLocationClient()?.locationClient let searchPlaceIndexForSuggestionsInput = SearchPlaceIndexForSuggestionsInput(biasPosition: [biasPosition.longitude, biasPosition.latitude], indexName: searchPlaceIndex, key: apiKey, maxResults: 15, text: "Schools") let response = try await locationClient?.searchPlaceIndexForSuggestions(input: searchPlaceIndexForSuggestionsInput) @@ -94,8 +94,10 @@ final class AuthHelperTests: XCTestCase { let identityPoolID = config["identityPoolID"]! let region = config["region"]! + let searchPlaceIndex = config["placeIndex"]! + let authHelper = AuthHelper() - let authCognitoProvider = try? await authHelper.authenticateWithCognitoIdentityPool(identityPoolId: identityPoolID, region: region) + let authCognitoProvider = try? await authHelper.authenticateWithCognitoIdentityPool(identityPoolId: identityPoolID) let credentials = authCognitoProvider?.getCognitoProvider()?.getCognitoCredentials() if let accessKey = credentials?.accessKeyId, let secret = credentials?.secretKey, let sessionToken = credentials?.sessionToken { @@ -103,6 +105,19 @@ final class AuthHelperTests: XCTestCase { let authProvider = try? await authHelper.authenticateWithCredentialsProvider(credentialsProvider: credentialProvider, region: region) let customAccessKey = try await authProvider!.getCustomCredentialsProvider()?.getCredentials().getAccessKey() XCTAssertEqual(customAccessKey, accessKey) + + let biasPosition = CLLocationCoordinate2D(latitude: 47.654502614244194, longitude: -122.35862564621954) + let locationClient = authHelper.getLocationClient()?.locationClient + let searchPlaceIndexForSuggestionsInput = SearchPlaceIndexForSuggestionsInput(biasPosition: [biasPosition.longitude, biasPosition.latitude], indexName: searchPlaceIndex, maxResults: 15, text: "Schools") + let response = try await locationClient?.searchPlaceIndexForSuggestions(input: searchPlaceIndexForSuggestionsInput) + + var searchResults: [String] = [] + if let results = response?.results { + for item in results { + searchResults.append((item.text)!) + } + } + XCTAssertNotEqual(searchResults.count, 0, "Search has results") } }