Skip to content

Commit 58f37d5

Browse files
authored
fix(Auth): Fixing deviceSRP auth flow during MigrateAuth (#2584)
* fix(Auth): Fixing deviceSRP auth flow during MigrateAuth * fix(Auth): Adding integration tests * Update SignInState+Resolver.swift
1 parent d068657 commit 58f37d5

File tree

11 files changed

+110
-27
lines changed

11 files changed

+110
-27
lines changed

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Actions/SignIn/DeviceSRPAuth/InitiateAuthDeviceSRP.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ struct InitiateAuthDeviceSRP: Action {
1414
let identifier = "InitiateAuthDeviceSRP"
1515

1616
let username: String
17-
let deviceMetadata: DeviceMetadata
1817
let authResponse: SignInResponseBehavior
1918

2019
func execute(withDispatcher dispatcher: EventDispatcher,
@@ -29,6 +28,11 @@ struct InitiateAuthDeviceSRP: Action {
2928
let gHexValue = srpEnv.srpConfiguration.gHexValue
3029
let srpKeyPair = srpClient.generateClientKeyPair()
3130

31+
// Get device metadata
32+
let deviceMetadata = await DeviceMetadataHelper.getDeviceMetadata(
33+
for: environment,
34+
with: username)
35+
3236
let srpStateData = SRPStateData(
3337
username: username,
3438
password: "",

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Actions/SignIn/DeviceSRPAuth/StartDeviceSRPFlow.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ struct StartDeviceSRPFlow: Action {
1111

1212
var identifier: String = "StartDeviceSRPFlow"
1313

14-
let srpStateData: SRPStateData
14+
let username: Username
1515
let authResponse: SignInResponseBehavior
1616

1717
func execute(withDispatcher dispatcher: EventDispatcher, environment: Environment) async {
1818
logVerbose("\(#fileID) Start execution", environment: environment)
19-
let event = SignInEvent(id: UUID().uuidString, eventType: .respondDeviceSRPChallenge(srpStateData, authResponse))
19+
let event = SignInEvent(id: UUID().uuidString, eventType: .respondDeviceSRPChallenge(
20+
username, authResponse))
2021
logVerbose("\(#fileID) Sending event \(event.type)", environment: environment)
2122
await dispatcher.send(event)
2223
}
@@ -26,7 +27,7 @@ extension StartDeviceSRPFlow: CustomDebugDictionaryConvertible {
2627
var debugDictionary: [String: Any] {
2728
[
2829
"identifier": identifier,
29-
"signInEventData": srpStateData.debugDictionary,
30+
"username": username.masked(),
3031
"signInResponse": authResponse
3132
]
3233
}

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/CodeGen/Events/SignInEvent.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ struct SignInEvent: StateMachineEvent {
2929

3030
case respondPasswordVerifier(SRPStateData, InitiateAuthOutputResponse)
3131

32-
case initiateDeviceSRP(SignInResponseBehavior)
32+
case initiateDeviceSRP(Username, SignInResponseBehavior)
3333

34-
case respondDeviceSRPChallenge(SRPStateData, SignInResponseBehavior)
34+
case respondDeviceSRPChallenge(Username, SignInResponseBehavior)
3535

3636
case respondDevicePasswordVerifier(SRPStateData, SignInResponseBehavior)
3737

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/CodeGen/States/DebugInfo/DeviceSRPState+Debug.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ extension DeviceSRPState {
1515
switch self {
1616
case .notStarted:
1717
additionalMetadataDictionary = [:]
18-
case .initiatingDeviceSRP(let signInEventData):
19-
additionalMetadataDictionary = signInEventData.debugDictionary
18+
case .initiatingDeviceSRP:
19+
additionalMetadataDictionary = [:]
2020
case .cancelling:
2121
additionalMetadataDictionary = [:]
2222
case .respondingDevicePasswordVerifier(let srpStateData):

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/CodeGen/States/DeviceSRPState.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import AWSCognitoIdentityProvider
1010
enum DeviceSRPState: State {
1111

1212
case notStarted
13-
case initiatingDeviceSRP(SRPStateData)
13+
case initiatingDeviceSRP
1414
case respondingDevicePasswordVerifier(SRPStateData)
1515
case signedIn(SignedInData)
1616
case error(SignInError)
@@ -34,8 +34,8 @@ extension DeviceSRPState {
3434
switch (lhs, rhs) {
3535
case (.notStarted, .notStarted):
3636
return true
37-
case (.initiatingDeviceSRP(let lhsData), .initiatingDeviceSRP(let rhsData)):
38-
return lhsData == rhsData
37+
case (.initiatingDeviceSRP, .initiatingDeviceSRP):
38+
return true
3939
case (.cancelling, .cancelling):
4040
return true
4141
case (.respondingDevicePasswordVerifier(let lhsData), .respondingDevicePasswordVerifier(let rhsData)):

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/Resolvers/SRP/DeviceSRPState+Resolver.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,12 @@ extension DeviceSRPState {
5050
private func resolveNotStarted(
5151
byApplying signInEvent: SignInEvent) -> StateResolution<DeviceSRPState> {
5252
switch signInEvent.eventType {
53-
case .respondDeviceSRPChallenge(let srpStateData, let authResponse):
53+
case .respondDeviceSRPChallenge(let username, let authResponse):
5454
let action = InitiateAuthDeviceSRP(
55-
username: srpStateData.username,
56-
deviceMetadata: srpStateData.deviceMetadata,
55+
username: username,
5756
authResponse: authResponse)
5857
return StateResolution(
59-
newState: DeviceSRPState.initiatingDeviceSRP(srpStateData),
58+
newState: DeviceSRPState.initiatingDeviceSRP,
6059
actions: [action]
6160
)
6261
default:

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/Resolvers/SignIn/SignInState+Resolver.swift

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ extension SignInState {
8989
}
9090

9191
if let signInEvent = event as? SignInEvent,
92-
case .initiateDeviceSRP(let challengeResponse) = signInEvent.eventType,
93-
case .respondingPasswordVerifier(let srpStateData) = srpSignInState {
92+
case .initiateDeviceSRP(let username, let challengeResponse) = signInEvent.eventType,
93+
case .respondingPasswordVerifier = srpSignInState {
9494
let action = StartDeviceSRPFlow(
95-
srpStateData: srpStateData,
95+
username: username,
9696
authResponse: challengeResponse)
9797
return .init(newState: .resolvingDeviceSrpa(.notStarted),
9898
actions: [action])
@@ -125,6 +125,15 @@ extension SignInState {
125125
actions: [action])
126126
}
127127

128+
if let signInEvent = event as? SignInEvent,
129+
case .initiateDeviceSRP(let username, let challengeResponse) = signInEvent.eventType {
130+
let action = StartDeviceSRPFlow(
131+
username: username,
132+
authResponse: challengeResponse)
133+
return .init(newState: .resolvingDeviceSrpa(.notStarted),
134+
actions: [action])
135+
}
136+
128137
let resolution = CustomSignInState.Resolver().resolve(
129138
oldState: customSignInState, byApplying: event)
130139
let signingInWithCustom = SignInState.signingInWithCustom(
@@ -151,6 +160,16 @@ extension SignInState {
151160
actions: [action])
152161
}
153162

163+
if let signInEvent = event as? SignInEvent,
164+
case .initiateDeviceSRP(let username, let challengeResponse) = signInEvent.eventType,
165+
case .signingIn = migrateSignInState {
166+
let action = StartDeviceSRPFlow(
167+
username: username,
168+
authResponse: challengeResponse)
169+
return .init(newState: .resolvingDeviceSrpa(.notStarted),
170+
actions: [action])
171+
}
172+
154173
let resolution = MigrateSignInState.Resolver().resolve(
155174
oldState: migrateSignInState, byApplying: event)
156175
let signingInWithMigration = SignInState.signingInViaMigrateAuth(
@@ -166,6 +185,15 @@ extension SignInState {
166185
actions: [action])
167186
}
168187

188+
if let signInEvent = event as? SignInEvent,
189+
case .initiateDeviceSRP(let username, let challengeResponse) = signInEvent.eventType {
190+
let action = StartDeviceSRPFlow(
191+
username: username,
192+
authResponse: challengeResponse)
193+
return .init(newState: .resolvingDeviceSrpa(.notStarted),
194+
actions: [action])
195+
}
196+
169197
// This could when we have nested challenges
170198
// Example newPasswordRequired -> sms_mfa
171199
if let signInEvent = event as? SignInEvent,
@@ -201,6 +229,15 @@ extension SignInState {
201229
), actions: [action])
202230
}
203231

232+
if let signInEvent = event as? SignInEvent,
233+
case .initiateDeviceSRP(let username, let challengeResponse) = signInEvent.eventType {
234+
let action = StartDeviceSRPFlow(
235+
username: username,
236+
authResponse: challengeResponse)
237+
return .init(newState: .resolvingDeviceSrpa(.notStarted),
238+
actions: [action])
239+
}
240+
204241
if let signInEvent = event as? SignInEvent,
205242
case .confirmDevice(let signedInData) = signInEvent.eventType {
206243
let action = ConfirmDevice(signedInData: signedInData)

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Helpers/UserPoolSignInHelper.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ struct UserPoolSignInHelper {
119119
case .smsMfa, .customChallenge, .newPasswordRequired:
120120
return SignInEvent(eventType: .receivedChallenge(respondToAuthChallenge))
121121
case .deviceSrpAuth:
122-
return SignInEvent(eventType: .initiateDeviceSRP(response))
122+
return SignInEvent(eventType: .initiateDeviceSRP(username, response))
123123
default:
124124
let message = "UnSupported challenge response \(challengeName)"
125125
let error = SignInError.unknown(message: message)

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/AWSAuthSignInTask.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ class AWSAuthSignInTask: AuthSignInTask {
8080
throw error
8181
}
8282
case .error(let error):
83-
let error = AuthError.unknown("Sign in reached an error state", error)
84-
throw error
83+
throw error.authError
8584

8685
case .signingIn(let signInState):
8786
guard let result = try UserPoolSignInHelper.checkNextStep(signInState) else {

AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/AWSAuthSignInPluginTests.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,49 @@ class AWSAuthSignInPluginTests: BasePluginTest {
542542
}
543543
}
544544

545+
/// Test a signIn with deviceSRP response
546+
///
547+
/// - Given: Given an auth plugin with mocked service. Mock unknown response for signIn result
548+
///
549+
/// - When:
550+
/// - I invoke signIn
551+
/// - Then:
552+
/// - I should get a .service error, because the response doesn't return valid data
553+
///
554+
func testSignInWithNextDeviceSRP() async {
555+
556+
self.mockIdentityProvider = MockIdentityProvider(mockInitiateAuthResponse: { _ in
557+
InitiateAuthOutputResponse(
558+
authenticationResult: .none,
559+
challengeName: .deviceSrpAuth,
560+
challengeParameters: InitiateAuthOutputResponse.validChalengeParams,
561+
session: "someSession")
562+
}, mockRespondToAuthChallengeResponse: { _ in
563+
RespondToAuthChallengeOutputResponse(
564+
authenticationResult: .none,
565+
challengeName: .devicePasswordVerifier,
566+
challengeParameters: ["paramKey": "value"],
567+
session: "session")
568+
})
569+
570+
let pluginOptions = AWSAuthSignInOptions(validationData: ["somekey": "somevalue"],
571+
metadata: ["somekey": "somevalue"],
572+
authFlowType: .userPassword)
573+
let options = AuthSignInRequest.Options(pluginOptions: pluginOptions)
574+
do {
575+
let result = try await plugin.signIn(
576+
username: "username",
577+
password: "password",
578+
options: options)
579+
XCTFail("Should not produce result - \(result)")
580+
} catch {
581+
guard case AuthError.service = error else {
582+
XCTFail("Should produce as service error")
583+
return
584+
}
585+
}
586+
}
587+
545588
// MARK: - Service error for initiateAuth
546589

547590
/// Test a signIn with `InternalErrorException` from service

0 commit comments

Comments
 (0)