From d88545fe4dee00ca5ca32b30d4e3b56e6e89ef4e Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Wed, 10 Apr 2024 17:52:45 +0100 Subject: [PATCH] Update for Soto v7 and concurrency fixes (#47) * Concurrency fixes * Update CI * 7.0.0 beta --- .github/workflows/ci.yml | 10 ++-------- Package.swift | 17 +++++++++++------ .../Authenticatable+JWT.swift | 17 ++++++++--------- .../Identifiable.swift | 2 +- .../UserPoolCredentialProvider.swift | 2 +- Sources/SotoCognitoAuthenticationSRP/SRP.swift | 4 ++-- .../CognitoTests.swift | 10 +++++----- .../CognitoSRPTests.swift | 6 +++--- 8 files changed, 33 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6dc12e..ab18da5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,12 +7,6 @@ on: paths: - '**.swift' pull_request: - branches: - - main - - 5.x.x - paths: - - '**.swift' - - '.github/workflows/ci.yml' workflow_dispatch: env: @@ -21,7 +15,7 @@ env: jobs: macOS: - runs-on: macOS-latest + runs-on: macOS-13 steps: - name: Checkout uses: actions/checkout@v3 @@ -42,9 +36,9 @@ jobs: strategy: matrix: image: - - swift:5.7 - swift:5.8 - swift:5.9 + - swift:5.10 runs-on: ubuntu-latest container: image: ${{ matrix.image }} diff --git a/Package.swift b/Package.swift index eb72da2..1d21af0 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.7 +// swift-tools-version:5.8 //===----------------------------------------------------------------------===// // // This source file is part of the Soto for AWS open source project @@ -17,6 +17,10 @@ import PackageDescription +let swiftSettings: [SwiftSetting] = [ + .enableExperimentalFeature("StrictConcurrency=complete"), +] + let package = Package( name: "soto-cognito-authentication-kit", platforms: [ @@ -30,7 +34,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/apple/swift-crypto.git", .upToNextMajor(from: "1.0.0")), - .package(url: "https://github.com/soto-project/soto.git", from: "7.0.0-alpha"), + .package(url: "https://github.com/soto-project/soto.git", from: "7.0.0-beta"), .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.10.0"), .package(url: "https://github.com/vapor/jwt-kit.git", .upToNextMajor(from: "4.2.6")), // for SRP @@ -45,17 +49,18 @@ let package = Package( .product(name: "AsyncHTTPClient", package: "async-http-client"), .product(name: "JWTKit", package: "jwt-kit"), .product(name: "Crypto", package: "swift-crypto"), - ] + ], + swiftSettings: swiftSettings ), - .testTarget(name: "SotoCognitoAuthenticationKitTests", dependencies: ["SotoCognitoAuthenticationKit"]), - .target( name: "SotoCognitoAuthenticationSRP", dependencies: [ .product(name: "BigNum", package: "big-num"), .target(name: "SotoCognitoAuthenticationKit"), - ] + ], + swiftSettings: swiftSettings ), + .testTarget(name: "SotoCognitoAuthenticationKitTests", dependencies: ["SotoCognitoAuthenticationKit"]), .testTarget(name: "SotoCognitoAuthenticationSRPTests", dependencies: ["SotoCognitoAuthenticationSRP"]), ] ) diff --git a/Sources/SotoCognitoAuthenticationKit/Authenticatable+JWT.swift b/Sources/SotoCognitoAuthenticationKit/Authenticatable+JWT.swift index 271cbbe..e3630a8 100644 --- a/Sources/SotoCognitoAuthenticationKit/Authenticatable+JWT.swift +++ b/Sources/SotoCognitoAuthenticationKit/Authenticatable+JWT.swift @@ -91,18 +91,17 @@ extension CognitoAuthenticatable { } logger.debug("Load jwks.json") - let jwtSignersURL = "https://cognito-idp.\(configuration.region.rawValue).amazonaws.com/\(configuration.userPoolId)/.well-known/jwks.json" + let jwtSignersURL = URL(string: "https://cognito-idp.\(configuration.region.rawValue).amazonaws.com/\(configuration.userPoolId)/.well-known/jwks.json")! let httpClient = configuration.cognitoIDP.client.httpClient - let response = try await httpClient.get( - url: jwtSignersURL, - deadline: .now() + .seconds(20), + let request = AWSHTTPRequest(url: jwtSignersURL, method: .GET, headers: [:], body: .init()) + let response = try await httpClient.execute( + request: request, + timeout: .seconds(20), logger: logger - ).get() + ) let signers = JWTSigners() - guard let body = response.body else { return JWTSigners() } - if let data = body.getString(at: body.readerIndex, length: body.readableBytes) { - try signers.use(jwksJSON: data) - } + let data = try await response.body.collect(upTo: 1_000_000) + try signers.use(jwksJSON: String(buffer: data)) self.jwtSigners = signers return signers } diff --git a/Sources/SotoCognitoAuthenticationKit/Identifiable.swift b/Sources/SotoCognitoAuthenticationKit/Identifiable.swift index cbd2f35..ce78b22 100644 --- a/Sources/SotoCognitoAuthenticationKit/Identifiable.swift +++ b/Sources/SotoCognitoAuthenticationKit/Identifiable.swift @@ -15,7 +15,7 @@ import NIO import SotoCognitoIdentity -public final class CognitoIdentifiable: Sendable { +public struct CognitoIdentifiable: Sendable { // MARK: Member variables /// Configuration diff --git a/Sources/SotoCognitoAuthenticationKit/UserPoolCredentialProvider.swift b/Sources/SotoCognitoAuthenticationKit/UserPoolCredentialProvider.swift index e5f6189..2924c22 100644 --- a/Sources/SotoCognitoAuthenticationKit/UserPoolCredentialProvider.swift +++ b/Sources/SotoCognitoAuthenticationKit/UserPoolCredentialProvider.swift @@ -16,7 +16,7 @@ import SotoCognitoIdentity import SotoCognitoIdentityProvider /// Cognito authentication method used by `CredentialProviderFactory.cognitoUserPool`. -public struct CognitoAuthenticationMethod { +public struct CognitoAuthenticationMethod: Sendable { public struct Context: Sendable { public let authenticatable: CognitoAuthenticatable public let userName: String diff --git a/Sources/SotoCognitoAuthenticationSRP/SRP.swift b/Sources/SotoCognitoAuthenticationSRP/SRP.swift index e11f042..f7645b3 100644 --- a/Sources/SotoCognitoAuthenticationSRP/SRP.swift +++ b/Sources/SotoCognitoAuthenticationSRP/SRP.swift @@ -16,8 +16,8 @@ import BigNum import Crypto import Foundation -/// Class to generate SRP password authentication key -class SRP { +/// Generates SRP password authentication key +struct SRP: Sendable { let N: BigNum let g: BigNum let k: BigNum diff --git a/Tests/SotoCognitoAuthenticationKitTests/CognitoTests.swift b/Tests/SotoCognitoAuthenticationKitTests/CognitoTests.swift index 011bfa7..afb4e9a 100644 --- a/Tests/SotoCognitoAuthenticationKitTests/CognitoTests.swift +++ b/Tests/SotoCognitoAuthenticationKitTests/CognitoTests.swift @@ -72,9 +72,9 @@ final class CognitoTests: XCTestCase { override class func setUp() { if ProcessInfo.processInfo.environment["CI"] == "true" { - self.awsClient = AWSClient(httpClientProvider: .createNew) + self.awsClient = AWSClient() } else { - self.awsClient = AWSClient(middleware: AWSLoggingMiddleware(), httpClientProvider: .createNew) + self.awsClient = AWSClient(middleware: AWSLoggingMiddleware()) } self.cognitoIDP = CognitoIdentityProvider(client: self.awsClient, region: self.region) @@ -334,7 +334,7 @@ final class CognitoTests: XCTestCase { func testUnauthenticatdClient() async throws { XCTAssertNil(Self.setUpFailure) try await self.test(#function) { username, password in - let awsClient = AWSClient(credentialProvider: .empty, httpClientProvider: .shared(Self.awsClient.httpClient)) + let awsClient = AWSClient(credentialProvider: .empty, httpClient: Self.awsClient.httpClient) defer { XCTAssertNoThrow(try awsClient.syncShutdown()) } let cognitoIdentityProvider = CognitoIdentityProvider(client: awsClient, region: Self.cognitoIDP.region) let configuration = CognitoConfiguration( @@ -358,7 +358,7 @@ final class CognitoTests: XCTestCase { func testRequireAuthenticatedClient() async throws { XCTAssertNil(Self.setUpFailure) try await self.test(#function) { username, password in - let awsClient = AWSClient(credentialProvider: .empty, httpClientProvider: .shared(Self.awsClient.httpClient)) + let awsClient = AWSClient(credentialProvider: .empty, httpClient: Self.awsClient.httpClient) defer { XCTAssertNoThrow(try awsClient.syncShutdown()) } let cognitoIdentityProvider = CognitoIdentityProvider(client: awsClient, region: Self.cognitoIDP.region) let configuration = CognitoConfiguration( @@ -432,7 +432,7 @@ final class CognitoTests: XCTestCase { } } ) - let client = AWSClient(credentialProvider: credentialProvider, httpClientProvider: .createNew) + let client = AWSClient(credentialProvider: credentialProvider) do { _ = try await client.credentialProvider.getCredential(logger: AWSClient.loggingDisabled) } catch let error as CognitoIdentityErrorType where error == .invalidIdentityPoolConfigurationException { diff --git a/Tests/SotoCognitoAuthenticationSRPTests/CognitoSRPTests.swift b/Tests/SotoCognitoAuthenticationSRPTests/CognitoSRPTests.swift index af3b396..818b5df 100644 --- a/Tests/SotoCognitoAuthenticationSRPTests/CognitoSRPTests.swift +++ b/Tests/SotoCognitoAuthenticationSRPTests/CognitoSRPTests.swift @@ -60,7 +60,7 @@ public class AWSCognitoContextTest: CognitoContextData { } final class CognitoSRPTests: XCTestCase { - static let awsClient = AWSClient(middleware: AWSLoggingMiddleware(), httpClientProvider: .createNew) + static let awsClient = AWSClient(middleware: AWSLoggingMiddleware()) static var region: Region = .useast1 static let cognitoIDP = CognitoIdentityProvider(client: awsClient, region: .useast1) static var cognitoIdentity: CognitoIdentity! = CognitoIdentity(client: awsClient, region: .useast1) @@ -201,7 +201,7 @@ final class CognitoSRPTests: XCTestCase { func testAuthenticateSRP() async throws { XCTAssertNil(Self.setUpFailure) - let awsClient = AWSClient(credentialProvider: .empty, middleware: AWSLoggingMiddleware(), httpClientProvider: .createNew) + let awsClient = AWSClient(credentialProvider: .empty, middleware: AWSLoggingMiddleware()) defer { XCTAssertNoThrow(try awsClient.syncShutdown()) } let cognitoIDPUnauthenticated = CognitoIdentityProvider(client: awsClient, region: .useast1) let configuration = CognitoConfiguration( @@ -309,7 +309,7 @@ final class CognitoSRPTests: XCTestCase { } } ) - let client = AWSClient(credentialProvider: credentialProvider, httpClientProvider: .createNew) + let client = AWSClient(credentialProvider: credentialProvider) do { _ = try await client.credentialProvider.getCredential(logger: AWSClient.loggingDisabled) } catch let error as CognitoIdentityErrorType where error == .invalidIdentityPoolConfigurationException {