Skip to content

Commit c5ed343

Browse files
committed
fix(auth): Pass deviceMetadata in RespondToAuthChallenge for signIn challenges
1 parent e52614f commit c5ed343

File tree

6 files changed

+488
-4
lines changed

6 files changed

+488
-4
lines changed

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Actions/SignIn/SRPAuth/VerifyPasswordSRP.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,24 @@ struct VerifyPasswordSRP: Action {
2626

2727
logVerbose("\(#fileID) Starting execution", environment: environment)
2828

29+
let inputUsername = stateData.username
30+
var username = inputUsername
31+
var deviceMetadata = DeviceMetadata.noData
2932
do {
3033
let srpEnv = try environment.srpEnvironment()
3134
let userPoolEnv = try environment.userPoolEnvironment()
3235
let srpClient = try SRPSignInHelper.srpClient(srpEnv)
3336
let parameters = try challengeParameters()
3437

35-
let inputUsername = stateData.username
36-
let username = parameters["USERNAME"] ?? inputUsername
38+
username = parameters["USERNAME"] ?? inputUsername
3739
let userIdForSRP = parameters["USER_ID_FOR_SRP"] ?? inputUsername
3840

3941
let saltHex = try saltHex(parameters)
4042
let secretBlockString = try secretBlockString(parameters)
4143
let secretBlock = try secretBlock(secretBlockString)
4244
let serverPublicB = try serverPublic(parameters)
4345

44-
let deviceMetadata = await DeviceMetadataHelper.getDeviceMetadata(
46+
deviceMetadata = await DeviceMetadataHelper.getDeviceMetadata(
4547
for: username,
4648
with: environment)
4749
let signature = try signature(userIdForSRP: userIdForSRP,

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Actions/SignIn/VerifySignInChallenge.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ struct VerifySignInChallenge: Action {
2121

2222
func execute(withDispatcher dispatcher: EventDispatcher, environment: Environment) async {
2323
logVerbose("\(#fileID) Starting execution", environment: environment)
24+
let username = challenge.username
25+
var deviceMetadata = DeviceMetadata.noData
2426

2527
do {
2628
let userpoolEnv = try environment.userPoolEnvironment()
@@ -29,6 +31,10 @@ struct VerifySignInChallenge: Action {
2931
let challengeType = challenge.challenge
3032
let responseKey = try challenge.getChallengeKey()
3133

34+
deviceMetadata = await DeviceMetadataHelper.getDeviceMetadata(
35+
for: username,
36+
with: environment)
37+
3238
let input = RespondToAuthChallengeInput.verifyChallenge(
3339
username: username,
3440
challengeType: challengeType,
@@ -37,6 +43,7 @@ struct VerifySignInChallenge: Action {
3743
answer: confirmSignEventData.answer,
3844
clientMetadata: confirmSignEventData.metadata,
3945
attributes: confirmSignEventData.attributes,
46+
deviceMetadata: deviceMetadata,
4047
environment: userpoolEnv)
4148

4249
let responseEvent = try await UserPoolSignInHelper.sendRespondToAuth(

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Utils/RespondToAuthChallengeInput+Amplify.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ extension RespondToAuthChallengeInput {
8484
answer: String,
8585
clientMetadata: [String: String]?,
8686
attributes: [String: String],
87+
deviceMetadata: DeviceMetadata,
8788
environment: UserPoolEnvironment) -> RespondToAuthChallengeInput {
8889

8990
var challengeResponses = [
@@ -101,7 +102,7 @@ extension RespondToAuthChallengeInput {
101102
challengeResponses: challengeResponses,
102103
session: session,
103104
clientMetadata: clientMetadata ?? [:],
104-
deviceMetadata: .noData,
105+
deviceMetadata: deviceMetadata,
105106
environment: environment)
106107
}
107108

AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ActionTests/InitiateAuthSRP/VerifyPasswordSRPTests.swift

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,4 +419,135 @@ class VerifyPasswordSRPTests: XCTestCase {
419419
await waitForExpectations(timeout: 0.1)
420420
}
421421

422+
// /// Test verify password retry on device not found
423+
// ///
424+
// /// - Given: VerifyPasswordSRP action with mocked cognito client and configuration
425+
// /// - When:
426+
// /// - I invoke the action with valid input and mock empty device not found error from Cognito
427+
// /// - Then:
428+
// /// - Should send an event with retryRespondPasswordVerifier
429+
// ///
430+
// func testPasswordVerifierWithDeviceNotFound() async {
431+
//
432+
// let identityProviderFactory: CognitoFactory = {
433+
// MockIdentityProvider(
434+
// mockRespondToAuthChallengeResponse: { _ in
435+
// throw RespondToAuthChallengeOutputError.resourceNotFoundException(
436+
// ResourceNotFoundException()
437+
// )
438+
// })
439+
// }
440+
//
441+
// let environment = Defaults.makeDefaultAuthEnvironment(
442+
// userPoolFactory: identityProviderFactory)
443+
//
444+
// let data = InitiateAuthOutputResponse.validTestData
445+
// let action = VerifyPasswordSRP(stateData: SRPStateData.testData,
446+
// authResponse: data)
447+
//
448+
// let passwordVerifierError = expectation(description: "passwordVerifierError")
449+
//
450+
// let dispatcher = MockDispatcher { event in
451+
// defer { passwordVerifierError.fulfill() }
452+
//
453+
// guard let event = event as? SignInEvent else {
454+
// XCTFail("Expected event to be SignInEvent but got \(event)")
455+
// return
456+
// }
457+
//
458+
// guard case .retryRespondPasswordVerifier = event.eventType
459+
// else {
460+
// XCTFail("Should receive retryRespondPasswordVerifier")
461+
// return
462+
// }
463+
// }
464+
//
465+
// await action.execute(withDispatcher: dispatcher, environment: environment)
466+
// await waitForExpectations(timeout: 0.1)
467+
// }
468+
469+
/// Test successful response from the VerifyPasswordSRP for confirmDevice
470+
///
471+
/// - Given: VerifyPasswordSRP action with mocked cognito client and configuration
472+
/// - When:
473+
/// - I invoke the action with valid input and mock new device
474+
/// - Then:
475+
/// - Should send an event confirmDevice
476+
///
477+
func testRespondToAuthChallengeWithConfirmDevice() async {
478+
let identityProviderFactory: CognitoFactory = {
479+
MockIdentityProvider(
480+
mockRespondToAuthChallengeResponse: { _ in
481+
return RespondToAuthChallengeOutputResponse.testDataWithNewDevice()
482+
})
483+
}
484+
485+
let environment = Defaults.makeDefaultAuthEnvironment(
486+
userPoolFactory: identityProviderFactory)
487+
488+
let data = InitiateAuthOutputResponse.validTestData
489+
let action = VerifyPasswordSRP(stateData: SRPStateData.testData,
490+
authResponse: data)
491+
492+
let passwordVerifierCompletion = expectation(
493+
description: "passwordVerifierCompletion")
494+
495+
let dispatcher = MockDispatcher { event in
496+
guard let event = event as? SignInEvent else {
497+
XCTFail("Expected event to be SignInEvent but got \(event)")
498+
return
499+
}
500+
501+
if case .confirmDevice(let signedInData) = event.eventType {
502+
XCTAssertNotNil(signedInData)
503+
passwordVerifierCompletion.fulfill()
504+
}
505+
}
506+
507+
await action.execute(withDispatcher: dispatcher, environment: environment)
508+
await waitForExpectations(timeout: 0.1)
509+
}
510+
511+
/// Test successful response from the VerifyPasswordSRP for verifyDevice
512+
///
513+
/// - Given: VerifyPasswordSRP action with mocked cognito client and configuration
514+
/// - When:
515+
/// - I invoke the action with valid input and mock verify device as response
516+
/// - Then:
517+
/// - Should send an event initiateDeviceSRP
518+
///
519+
func testRespondToAuthChallengeWithVerifyDevice() async {
520+
let identityProviderFactory: CognitoFactory = {
521+
MockIdentityProvider(
522+
mockRespondToAuthChallengeResponse: { _ in
523+
return RespondToAuthChallengeOutputResponse.testDataWithVerifyDevice()
524+
})
525+
}
526+
527+
let environment = Defaults.makeDefaultAuthEnvironment(
528+
userPoolFactory: identityProviderFactory)
529+
530+
let data = InitiateAuthOutputResponse.validTestData
531+
let action = VerifyPasswordSRP(stateData: SRPStateData.testData,
532+
authResponse: data)
533+
534+
let passwordVerifierCompletion = expectation(
535+
description: "passwordVerifierCompletion")
536+
537+
let dispatcher = MockDispatcher { event in
538+
guard let event = event as? SignInEvent else {
539+
XCTFail("Expected event to be SignInEvent but got \(event)")
540+
return
541+
}
542+
543+
if case .initiateDeviceSRP(_, let response) = event.eventType {
544+
XCTAssertNotNil(response)
545+
passwordVerifierCompletion.fulfill()
546+
}
547+
}
548+
549+
await action.execute(withDispatcher: dispatcher, environment: environment)
550+
await waitForExpectations(timeout: 0.1)
551+
}
552+
422553
}

0 commit comments

Comments
 (0)