Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(auth): add passwordless support #3920

Merged
merged 36 commits into from
Nov 25, 2024
Merged
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9b219e4
feat(auth): adding support for email mfa (#3892)
harsh62 Oct 4, 2024
c1c08a1
chore: initial commit to add sdk with passwordless models
harsh62 Sep 30, 2024
2e704e5
chore: model update
harsh62 Oct 10, 2024
9a0ce7d
feat(Auth): Adding WebAuthn APIs (#153)
sebaland Oct 17, 2024
970c93a
feat(auth): add passwordless sign with otp (#151)
harsh62 Oct 24, 2024
9e8f2f6
feat(Auth): Adding WebAuthn support to signIn and confirmSignIn APIs …
sebaland Oct 24, 2024
ac9dde4
fix: Fixing build issue when iOS 18/macOS 15 are not installed
sebaland Oct 24, 2024
a6e760b
feat(WebAuthn): Adding support for retrying a confirmSignIn with WebA…
sebaland Oct 28, 2024
364b966
feat(auth): add support for passwordless sign up and auto sign in (#160)
thisisabhash Nov 1, 2024
c773ced
chore: fix building of unit tests after sign up rebase
harsh62 Nov 3, 2024
56b31e0
feat(auth): adding passwordless sign in preferred flows (#162)
harsh62 Nov 4, 2024
3df1ef0
chore(auth): add more auto sign in and sign up state machine/e2e unit…
thisisabhash Nov 5, 2024
119a8b1
chore: updated SDK and models
harsh62 Nov 5, 2024
ab2edae
Merge branch 'passwordless' of github.com:aws-amplify/amplify-ios-sta…
harsh62 Nov 5, 2024
745cc8e
chore: update integration test host app
harsh62 Nov 5, 2024
7336281
fix: Fixing build errors in watchOS/tvOS due to missing prechecks.
sebaland Nov 5, 2024
495a487
feat(auth): adding an initial passwordless integration test with reso…
harsh62 Nov 6, 2024
aaaf694
chore: update no-auth API's in the resolver
harsh62 Nov 6, 2024
717fa31
chore: Updating to the renamed WebAuthn APIs (#164)
sebaland Nov 6, 2024
208ca17
chore: Adding unit tests for the WebAuthn APIs Tasks (#165)
sebaland Nov 12, 2024
0ffc77b
chore(auth): add integration tests for passwordless signup and auto s…
thisisabhash Nov 12, 2024
f4e5701
chore: add integration tests for sign in flows (#168)
harsh62 Nov 13, 2024
4820997
chore: update sdk to use the latest models
harsh62 Nov 13, 2024
f55d2bb
test: Adding integration tests for WebAuthn APIs (#169)
sebaland Nov 13, 2024
ed7fbf9
fix: Fixing service errors being reported as .unknown when sign in fa…
sebaland Nov 13, 2024
19eeb30
fix(auth): fix resolvers and tasks for auto sign in when state machin…
thisisabhash Nov 15, 2024
d1263a0
feat: Adding visionOS support to the WebAuthn APIs (#171)
sebaland Nov 15, 2024
12575b7
chore: using the latest version aws sdk
harsh62 Nov 22, 2024
152882e
chore: update changes needed for the sdk updated
harsh62 Nov 22, 2024
959e596
chore: fix swiftlint errors (#3921)
thisisabhash Nov 22, 2024
96cdb46
chore: running passwordless integration tests on GEN2 backend
harsh62 Nov 23, 2024
78cd5f6
chore: update test target for watchOS
harsh62 Nov 24, 2024
d0c0fce
chore: fix OTP integration tests
harsh62 Nov 24, 2024
607df25
chore: update more integration tests
harsh62 Nov 24, 2024
e4cf95c
chore: update integration test readme's
harsh62 Nov 25, 2024
c97f118
chore: disable webauthn integration tests
harsh62 Nov 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Prev Previous commit
Next Next commit
chore: update sdk to use the latest models
harsh62 committed Nov 13, 2024
commit 4820997fe1dc838bea226d797a93169d23959106
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/7.2/executionHistory/executionHistory.bin
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/7.2/executionHistory/executionHistory.lock
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/7.2/fileHashes/fileHashes.bin
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/7.2/fileHashes/fileHashes.lock
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/7.2/fileHashes/resourceHashesCache.bin
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary file not shown.
2 changes: 1 addition & 1 deletion aws-sdk-swift/.gradle/buildOutputCleanup/cache.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#Tue Nov 05 04:19:28 UTC 2024
#Wed Nov 13 16:54:30 UTC 2024
gradle.version=7.2
Binary file modified aws-sdk-swift/.gradle/buildOutputCleanup/outputFiles.bin
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/checksums/checksums.lock
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/checksums/md5-checksums.bin
Binary file not shown.
Binary file modified aws-sdk-swift/.gradle/checksums/sha1-checksums.bin
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -189,8 +189,7 @@ private func target(_ service: String) -> Target {
.awsSDKEventStreamsAuth,
.awsSDKChecksums,
],
path: "Sources/Services/\(service)/Sources/\(service)",
resources: [.process("Resources")]
path: "Sources/Services/\(service)/Sources/\(service)"
)
}

Original file line number Diff line number Diff line change
@@ -41,4 +41,16 @@ class SQSTests: XCTestCase {
XCTAssertNotNil(response.queueUrl, "Queue URL should not be nil")
XCTAssertTrue(response.queueUrl?.contains(queueName) ?? false, "Queue URL should contain the queue name.")
}

func test_QueryCompatible() async throws {
do {
_ = try await client.getQueueUrl(input: .init(queueName: "non-existent-queue-123"))
XCTFail("Expected an error to be thrown!")
} catch let error as QueueDoesNotExist {
let errorCode = error.errorCode
XCTAssertTrue(errorCode == "AWS.SimpleQueueService.NonExistentQueue")
} catch let unknownError {
XCTFail("An unexpected error occurred: \(unknownError.localizedDescription)")
}
}
}
Original file line number Diff line number Diff line change
@@ -99,7 +99,7 @@ class STSWebIdentityAWSCredentialIdentityResolverTests: XCTestCase {
// MARK: - TEST CASE

// Confirm STS web identity credentials provider works by validating response.
func testGetCallerIdentity() async throws {
func xtestGetCallerIdentity() async throws {
let response = try await webIdentityStsClient.getCallerIdentity(
input: GetCallerIdentityInput()
)
5 changes: 2 additions & 3 deletions aws-sdk-swift/Package.swift
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ import PackageDescription

// MARK: - Dynamic Content

let clientRuntimeVersion: Version = "0.87.0"
let clientRuntimeVersion: Version = "0.90.0"
let crtVersion: Version = "0.37.0"

let excludeRuntimeUnitTests = false
@@ -603,8 +603,7 @@ private func target(_ service: String) -> Target {
.awsSDKEventStreamsAuth,
.awsSDKChecksums,
],
path: "Sources/Services/\(service)/Sources/\(service)",
resources: [.process("Resources")]
path: "Sources/Services/\(service)/Sources/\(service)"
)
}

2 changes: 1 addition & 1 deletion aws-sdk-swift/Package.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.34
1.0.39
2 changes: 1 addition & 1 deletion aws-sdk-swift/Package.version.next
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.35
1.0.40
3 changes: 0 additions & 3 deletions aws-sdk-swift/ServiceClientVersions.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -20,17 +20,36 @@ public struct AWSJSONError: BaseError {
private let responseReader: Reader

@_spi(SmithyReadWrite)
public init(httpResponse: HTTPResponse, responseReader: Reader, noErrorWrapping: Bool) throws {
let code: String? = try httpResponse.headers.value(for: "X-Amzn-Errortype")
public init(httpResponse: HTTPResponse, responseReader: Reader, noErrorWrapping: Bool, code: String? = nil) throws {
let errorCode: String? = try httpResponse.headers.value(for: "X-Amzn-Errortype")
?? responseReader["code"].readIfPresent()
?? responseReader["__type"].readIfPresent()
let resolvedCode = code ?? errorCode
let message: String? = try responseReader["Message"].readIfPresent()
let requestID: String? = try responseReader["RequestId"].readIfPresent()
guard let code else { throw BaseErrorDecodeError.missingRequiredData }
self.code = sanitizeErrorType(code)
guard let resolvedCode else { throw BaseErrorDecodeError.missingRequiredData }
self.code = sanitizeErrorType(resolvedCode)
self.message = message
self.requestID = requestID
self.httpResponse = httpResponse
self.responseReader = responseReader
}
}

extension AWSJSONError {
@_spi(SmithyReadWrite)
public static func makeQueryCompatibleAWSJsonError(
httpResponse: HTTPResponse,
responseReader: Reader,
noErrorWrapping: Bool,
errorDetails: String?
) throws -> AWSJSONError {
let errorCode = try AwsQueryCompatibleErrorDetails.parse(errorDetails).code
return try AWSJSONError(
httpResponse: httpResponse,
responseReader: responseReader,
noErrorWrapping: noErrorWrapping,
code: errorCode
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import protocol ClientRuntime.BaseError
@_spi(SmithyReadWrite) import class SmithyJSON.Reader

/**
* Error details presented for backwards-compatibility by services that have migrated from awsQuery.
*/
public class AwsQueryCompatibleErrorDetails {
public let code: String
public let type: String

public init(
code: String,
type: String
) {
self.code = code
self.type = type
}

public static func parse(_ value: String?) throws -> AwsQueryCompatibleErrorDetails {
guard let value else {
throw ParseError.missingQueryErrorData
}
return try parseImpl(value)
}
}

/**
* Set awsQuery error details on a [BaseError]
*/
public enum ParseError: Error, CustomDebugStringConvertible {
case malformedErrorString
case emptyCode
case emptyType
case missingQueryErrorData

public var debugDescription: String {
switch self {
case .malformedErrorString:
return "value is malformed"
case .emptyCode:
return "code is empty"
case .emptyType:
return "type is empty"
case .missingQueryErrorData:
return "x-amzn-query-error header not found"
}
}
}

// parse an awsQuery error from its string representation
// the value is formatted as `code;type` e.g. `AWS.SimpleQueueService.NonExistentQueue;Sender`.
private func parseImpl(_ error: String) throws -> AwsQueryCompatibleErrorDetails {
let segments = error.split(separator: ";", maxSplits: 1, omittingEmptySubsequences: false)

// Check for malformed string structure
guard segments.count == 2 else {
throw ParseError.malformedErrorString
}

let code = String(segments[0])
let type = String(segments[1])

// Check for empty code or type
guard !code.isEmpty else {
throw ParseError.emptyCode
}
guard !type.isEmpty else {
throw ParseError.emptyType
}

return AwsQueryCompatibleErrorDetails(code: code, type: type)
}
Original file line number Diff line number Diff line change
@@ -55,14 +55,6 @@ public enum AWSRetryErrorInfoProvider: RetryErrorInfoProvider {

public static func errorInfo(for error: Error) -> RetryErrorInfo? {

// Look for a header with a retry after value; use it as retry after hint
var retryAfterHint: TimeInterval?
if let headers = (error as? HTTPError)?.httpResponse.headers,
let delayString = headers.value(for: "Retry-After") ?? headers.value(for: "X-Amz-Retry-After"),
let delay = TimeInterval(delayString) {
retryAfterHint = delay
}

// Determine based on properties if this error is a timeout error.
var isTimeout = false

@@ -75,32 +67,32 @@ public enum AWSRetryErrorInfoProvider: RetryErrorInfoProvider {
// Handle certain CRT errors as transient errors
if case CommonRunTimeError.crtError(let crtError) = error {
if transientCRTErrorCodes.contains(crtError.code) {
return RetryErrorInfo(errorType: .transient, retryAfterHint: retryAfterHint, isTimeout: isTimeout)
return RetryErrorInfo(errorType: .transient, retryAfterHint: nil, isTimeout: isTimeout)
}
}

if let serviceError = error as? ServiceError, let code = serviceError.typeName {
// Handle the throttling error codes as errors of retry type "throttling".
if throttlingErrorCodes.contains(code) {
return RetryErrorInfo(errorType: .throttling, retryAfterHint: retryAfterHint, isTimeout: false)
return RetryErrorInfo(errorType: .throttling, retryAfterHint: nil, isTimeout: false)
}
// Handle the transient error codes as errors of retry type "transient".
if transientErrorCodes.contains(code) {
return RetryErrorInfo(errorType: .transient, retryAfterHint: retryAfterHint, isTimeout: isTimeout)
return RetryErrorInfo(errorType: .transient, retryAfterHint: nil, isTimeout: isTimeout)
}
}

if let httpError = error as? HTTPError {
// Handle the transient and timeout HTTP status codes as errors of retry type "transient".
if (transientStatusCodes + timeoutStatusCodes).contains(httpError.httpResponse.statusCode.rawValue) {
return RetryErrorInfo(errorType: .transient, retryAfterHint: retryAfterHint, isTimeout: isTimeout)
return RetryErrorInfo(errorType: .transient, retryAfterHint: nil, isTimeout: isTimeout)
}
}

if let modeledError = error as? ModeledError, type(of: modeledError).typeName == "IDPCommunicationError" {

// Handle a modeled IDPCommunicationError (comes from STS) as an error of retry type "transient".
return RetryErrorInfo(errorType: .transient, retryAfterHint: retryAfterHint, isTimeout: isTimeout)
return RetryErrorInfo(errorType: .transient, retryAfterHint: nil, isTimeout: isTimeout)
}

// If custom AWS error matching fails, use the default error info provider to finish matching.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import XCTest
import AWSClientRuntime

class AwsQueryCompatibleErrorDetailsTests: XCTestCase {

func testParseMalformed() {
XCTAssertThrowsError(try AwsQueryCompatibleErrorDetails.parse("malformed")) { error in
XCTAssertEqual((error as! ParseError).debugDescription, "value is malformed")
}
}

func testParseEmptyCode() {
XCTAssertThrowsError(try AwsQueryCompatibleErrorDetails.parse(";type")) { error in
XCTAssertEqual((error as! ParseError).debugDescription, "code is empty")
}
}

func testParseEmptyType() {
XCTAssertThrowsError(try AwsQueryCompatibleErrorDetails.parse("code;")) { error in
XCTAssertEqual((error as! ParseError).debugDescription, "type is empty")
}
}

func testParseErrorClient() throws {
let expected = AwsQueryCompatibleErrorDetails(
code: "com.test.ErrorCode",
type: "Sender"
)
let actual = try AwsQueryCompatibleErrorDetails.parse("com.test.ErrorCode;Sender")
XCTAssertEqual(expected.code, actual.code)
XCTAssertEqual(expected.type, actual.type)
}

func testParseErrorServer() throws {
let expected = AwsQueryCompatibleErrorDetails(
code: "com.test.ErrorCode",
type: "Receiver"
)
let actual = try AwsQueryCompatibleErrorDetails.parse("com.test.ErrorCode;Receiver")
XCTAssertEqual(expected.code, actual.code)
XCTAssertEqual(expected.type, actual.type)
}
}
Original file line number Diff line number Diff line change
@@ -80,20 +80,6 @@ class AWSRetryErrorInfoProviderTests: XCTestCase {
}
}

// MARK: - Retry after hint

func test_retryAfterHint_setsRetryAfterHintWhenRetryAfterHeaderIsSetWithSeconds() throws {
let error = try TestHTTPError(statusCode: 500, headers: ["retry-after": "2.8"])
let errorInfo = AWSRetryErrorInfoProvider.errorInfo(for: error)
XCTAssertEqual(errorInfo?.retryAfterHint, 2.8)
}

func test_retryAfterHint_setsRetryAfterHintWhenXAmzRetryAfterHeaderIsSetWithSeconds() throws {
let error = try TestHTTPError(statusCode: 500, headers: ["x-amz-retry-after": "2.7"])
let errorInfo = AWSRetryErrorInfoProvider.errorInfo(for: error)
XCTAssertEqual(errorInfo?.retryAfterHint, 2.7)
}

// MARK: - isTimeout

func test_isTimeout_setsIsTimeoutWhenHTTPStatusCodeIndicatesTimeout() throws {
31 changes: 14 additions & 17 deletions aws-sdk-swift/Sources/Services/AWSACM/Package.swift.txt
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ let package = Package(
exact: "0.0.1"
),
.package(
id: "aws-sdk-swift.smithy-swift",
url: "https://github.com/smithy-lang/smithy-swift",
exact: "0.0.1"
),
],
@@ -38,55 +38,52 @@ let package = Package(
),
.product(
name: "ClientRuntime",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyIdentity",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyRetriesAPI",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyHTTPAPI",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyHTTPAuthAPI",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "Smithy",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyRetries",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyJSON",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyReadWrite",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyTimestamps",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyWaitersAPI",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
.product(
name: "SmithyTestUtil",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
],
resources: [
.process("Resources")
]
),
.testTarget(
@@ -95,7 +92,7 @@ let package = Package(
"AWSACM",
.product(
name: "SmithyTestUtil",
package: "aws-sdk-swift.smithy-swift"
package: "smithy-swift"
),
]
)
Loading