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
Show file tree
Hide file tree
Changes from all commits
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)
ruisebas 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 …
ruisebas Oct 24, 2024
ac9dde4
fix: Fixing build issue when iOS 18/macOS 15 are not installed
ruisebas Oct 24, 2024
a6e760b
feat(WebAuthn): Adding support for retrying a confirmSignIn with WebA…
ruisebas 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.
ruisebas 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)
ruisebas Nov 6, 2024
208ca17
chore: Adding unit tests for the WebAuthn APIs Tasks (#165)
ruisebas 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)
ruisebas Nov 13, 2024
ed7fbf9
fix: Fixing service errors being reported as .unknown when sign in fa…
ruisebas 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)
ruisebas 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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/integ_test_auth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,9 @@ jobs:
resource_subfolder: auth
timeout-minutes: 30
secrets: inherit

# Disabling the integration test because the job is not able to connect to the local server
# auth-webauthn-integration-test-iOS:
# name: Auth WebAuthn Integration Tests (iOS)
# uses: ./.github/workflows/integ_test_auth_webauthn.yml
# secrets: inherit
101 changes: 101 additions & 0 deletions .github/workflows/integ_test_auth_webauthn.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: Integration Tests | Auth - WebAuthn
on:
workflow_dispatch:
workflow_call:

permissions:
id-token: write
contents: read

jobs:
auth-webauthn-integration-tests:
name: iOS Tests | AuthWebAuthnApp
runs-on: macos-15
timeout-minutes: 30
environment: IntegrationTest

steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false

- name: Get build parameters for iOS
id: platform
uses: ./.github/composite_actions/get_platform_parameters
with:
platform: iOS

- name: Create the test configuration directory
run: mkdir -p ~/.aws-amplify/amplify-ios/testconfiguration/

- name: Download the Integration Test configurations
uses: ./.github/composite_actions/download_test_configuration
with:
resource_subfolder: auth
aws_role_to_assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws_region: ${{ secrets.AWS_REGION }}
aws_s3_bucket: ${{ secrets.AWS_S3_BUCKET_INTEG_V2 }}
destination: ~/.aws-amplify/amplify-ios/testconfiguration/

- name: Set up node
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
with:
node-version: 16.x

- name: Attempt to use the dependencies cache
id: dependencies-cache
timeout-minutes: 4
continue-on-error: true
uses: actions/cache/restore@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
with:
path: ~/Library/Developer/Xcode/DerivedData/Amplify
key: amplify-packages-${{ hashFiles('Package.resolved') }}
restore-keys: |
amplify-packages-

- name: Attempt to restore the build cache
id: build-cache
timeout-minutes: 4
continue-on-error: true
uses: actions/cache/restore@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
with:
path: ${{ github.workspace }}/Build
key: Amplify-iOS-build-cache

- name: Run Local Server
run: |
cd ./AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/LocalServer
npm install
npm start &
shell: bash

- name: Run iOS Integration Tests
id: run-tests
continue-on-error: true
uses: ./.github/composite_actions/run_xcodebuild_test
with:
scheme: AuthWebAuthnApp
destination: ${{ steps.platform.outputs.destination }}
sdk: ${{ steps.platform.outputs.sdk }}
xcode_path: /Applications/Xcode_${{ steps.platform.outputs.xcode-version }}.app
project_path: ./AmplifyPlugins/Auth/Tests/AuthWebAuthnApp
generate_coverage: false
cloned_source_packages_path: ~/Library/Developer/Xcode/DerivedData/Amplify
derived_data_path: ${{ github.workspace }}/Build
disable_package_resolution: ${{ steps.dependencies-cache.outputs.cache-hit }}

- name: Retry iOS Integration Tests
if: steps.run-tests.outcome=='failure'
id: retry-tests
uses: ./.github/composite_actions/run_xcodebuild_test
with:
scheme: AuthWebAuthnApp
destination: ${{ steps.platform.outputs.destination }}
sdk: ${{ steps.platform.outputs.sdk }}
xcode_path: /Applications/Xcode_${{ steps.platform.outputs.xcode-version }}.app
project_path: ./AmplifyPlugins/Auth/Tests/AuthWebAuthnApp
generate_coverage: false
cloned_source_packages_path: ~/Library/Developer/Xcode/DerivedData/Amplify
derived_data_path: ${{ github.workspace }}/Build
disable_package_resolution: true
4 changes: 4 additions & 0 deletions Amplify/Categories/Auth/AuthCategory+ClientBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ extension AuthCategory: AuthCategoryBehavior {
return await plugin.signOut(options: options)
}

public func autoSignIn() async throws -> AuthSignInResult {
try await plugin.autoSignIn()
}

public func deleteUser() async throws {
try await plugin.deleteUser()
}
Expand Down
51 changes: 51 additions & 0 deletions Amplify/Categories/Auth/AuthCategory+WebAuthnBehaviour.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

extension AuthCategory: AuthCategoryWebAuthnBehaviour {
#if os(iOS) || os(macOS)
@available(iOS 17.4, macOS 13.5, *)
public func associateWebAuthnCredential(
presentationAnchor: AuthUIPresentationAnchor? = nil,
options: AuthAssociateWebAuthnCredentialRequest.Options? = nil
) async throws {
try await plugin.associateWebAuthnCredential(
presentationAnchor: presentationAnchor,
options: options
)
}
#elseif os(visionOS)
public func associateWebAuthnCredential(
presentationAnchor: AuthUIPresentationAnchor,
options: AuthAssociateWebAuthnCredentialRequest.Options? = nil
) async throws {
try await plugin.associateWebAuthnCredential(
presentationAnchor: presentationAnchor,
options: options
)
}
#endif

public func listWebAuthnCredentials(
options: AuthListWebAuthnCredentialsRequest.Options? = nil
) async throws -> AuthListWebAuthnCredentialsResult {
return try await plugin.listWebAuthnCredentials(
options: options
)
}

public func deleteWebAuthnCredential(
credentialId: String,
options: AuthDeleteWebAuthnCredentialRequest.Options? = nil
) async throws {
try await plugin.deleteWebAuthnCredential(
credentialId: credentialId,
options: options
)
}
}
6 changes: 5 additions & 1 deletion Amplify/Categories/Auth/AuthCategoryBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#endif

/// Behavior of the Auth category that clients will use
public protocol AuthCategoryBehavior: AuthCategoryUserBehavior, AuthCategoryDeviceBehavior {
public protocol AuthCategoryBehavior: AuthCategoryUserBehavior, AuthCategoryDeviceBehavior, AuthCategoryWebAuthnBehaviour {

/// SignUp a user with the authentication provider.
///
Expand Down Expand Up @@ -102,6 +102,10 @@
options: AuthConfirmSignInRequest.Options?
) async throws -> AuthSignInResult


Check warning on line 105 in Amplify/Categories/Auth/AuthCategoryBehavior.swift

View workflow job for this annotation

GitHub Actions / run-swiftlint

Lines should not have trailing whitespace (trailing_whitespace)

Check warning on line 105 in Amplify/Categories/Auth/AuthCategoryBehavior.swift

View workflow job for this annotation

GitHub Actions / run-swiftlint

Limit vertical whitespace to a single empty line; currently 2 (vertical_whitespace)
/// Auto signs in the user for passwordless sign up
func autoSignIn() async throws -> AuthSignInResult

Check warning on line 108 in Amplify/Categories/Auth/AuthCategoryBehavior.swift

View workflow job for this annotation

GitHub Actions / run-swiftlint

Lines should not have trailing whitespace (trailing_whitespace)
/// Sign out the currently logged-in user.
///
/// - Parameters:
Expand Down
35 changes: 35 additions & 0 deletions Amplify/Categories/Auth/AuthCategoryWebAuthnBehaviour.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

public protocol AuthCategoryWebAuthnBehaviour: AnyObject {
#if os(iOS) || os(macOS)
/// - Tag: AuthCategoryWebAuthnBehaviour.associate
@available(iOS 17.4, macOS 13.5, *)
func associateWebAuthnCredential(
presentationAnchor: AuthUIPresentationAnchor?,
options: AuthAssociateWebAuthnCredentialRequest.Options?
) async throws
#elseif os(visionOS)
func associateWebAuthnCredential(
presentationAnchor: AuthUIPresentationAnchor,
options: AuthAssociateWebAuthnCredentialRequest.Options?
) async throws
#endif

/// - Tag: AuthCategoryWebAuthnBehaviour.list
func listWebAuthnCredentials(
options: AuthListWebAuthnCredentialsRequest.Options?
) async throws -> AuthListWebAuthnCredentialsResult

/// - Tag: AuthCategoryWebAuthnBehaviour.delete
func deleteWebAuthnCredential(
credentialId: String,
options: AuthDeleteWebAuthnCredentialRequest.Options?
) async throws
}
27 changes: 27 additions & 0 deletions Amplify/Categories/Auth/Models/AuthFactorType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

public enum AuthFactorType: String {

/// An auth factor that uses password
case password

/// An auth factor that uses SRP protocol
case passwordSRP

/// An auth factor that uses SMS OTP
case smsOTP

/// An auth factor that uses Email OTP
case emailOTP

#if os(iOS) || os(macOS) || os(visionOS)
/// An auth factor that uses WebAuthn
@available(iOS 17.4, macOS 13.5, visionOS 1.0, *)
case webAuthn
#endif
}
11 changes: 11 additions & 0 deletions Amplify/Categories/Auth/Models/AuthSignInStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
/// Set of allowed MFA types that would be used for continuing sign in during MFA selection step
public typealias AllowedMFATypes = Set<MFAType>

/// Set of available factors that would be used for continuing/confirming sign in
public typealias AvailableAuthFactorTypes = Set<AuthFactorType>

/// Auth SignIn flow steps
///
///
Expand All @@ -26,6 +29,10 @@ public enum AuthSignInStep {
///
case confirmSignInWithNewPassword(AdditionalInfo?)

/// Auth step required the user to give a password.
///
case confirmSignInWithPassword

/// Auth step is TOTP multi factor authentication.
///
/// Confirmation code for the MFA will be retrieved from the associated Authenticator app
Expand All @@ -52,6 +59,10 @@ public enum AuthSignInStep {
/// OTP for the factor will be sent to the delivery medium.
case confirmSignInWithOTP(AuthCodeDeliveryDetails)

/// Auth step is for continuing sign in by selecting the first factor that would be used for signing in
///
case continueSignInWithFirstFactorSelection(AvailableAuthFactorTypes)

/// Auth step required the user to change their password.
///
case resetPassword(AdditionalInfo?)
Expand Down
5 changes: 5 additions & 0 deletions Amplify/Categories/Auth/Models/AuthSignUpStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

public typealias UserId = String
public typealias Session = String

/// SignUp step to be followed.
public enum AuthSignUpStep {
Expand All @@ -16,6 +17,10 @@ public enum AuthSignUpStep {
AdditionalInfo? = nil,
UserId? = nil)

/// Sign Up successfully completed
/// The customers can use this step to determine if they want to complete sign in
case completeAutoSignIn(Session)

/// Sign up is complete
case done
}
52 changes: 52 additions & 0 deletions Amplify/Categories/Auth/Models/AuthWebAuthnCredential.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

/// Represents the output of a call to
/// [`AuthCategoryWebAuthnBehaviour.listWebAuthnCredentials(options:)`](x-source-tag://AuthCategoryWebAuthnBehaviour.list)
///
/// - Tag: AuthListWebAuthnCredentialsResult
public struct AuthListWebAuthnCredentialsResult {
/// The list of WebAuthn credentials
///
/// - Tag: AuthListWebAuthnCredentialsResult.credentials
public var credentials: [AuthWebAuthnCredential]

/// String indicating the page offset at which to resume a listing.
///
/// This value is usually copied to
/// [AuthListWebAuthnCredentialsRequest.Options.nextToken](x-source-tag://AuthListWebAuthnCredentialsRequestOptions.nextToken).
///
/// - Tag: AuthListWebAuthnCredentialsResult.nextToken
public let nextToken: String?

/// - Tag: AuthListWebAuthnCredentialsResult.init
public init(
credentials: [AuthWebAuthnCredential],
nextToken: String?
) {
self.credentials = credentials
self.nextToken = nextToken
}
}

/// Defines a WebAuthn credential
/// - Tag: AuthWebAuthnCredential
public protocol AuthWebAuthnCredential {
/// The credential's ID
var credentialId: String { get }

/// The credential's creation date
var createdAt: Date { get }

/// The credential's relying party ID
var relyingPartyId: String { get }

/// The credential's friendly name
var friendlyName: String? { get }
}
Loading
Loading