Skip to content

Commit 19eeb30

Browse files
authoredNov 15, 2024
fix(auth): fix resolvers and tasks for auto sign in when state machine is in signing in state (#172)
* fix(auth): fix resolvers and tasks for auto sign in when state machine is in signin in state * fix indentation
1 parent ed7fbf9 commit 19eeb30

File tree

4 files changed

+111
-7
lines changed

4 files changed

+111
-7
lines changed
 

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

+8
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,14 @@ extension SignInState {
555555
return .init(newState: .signedIn(signedInData),
556556
actions: [SignInComplete(signedInData: signedInData)])
557557
}
558+
559+
if let signInEvent = event as? SignInEvent,
560+
case .confirmDevice(let signedInData) = signInEvent.eventType {
561+
let action = ConfirmDevice(signedInData: signedInData)
562+
return .init(newState: .confirmingDevice,
563+
actions: [action])
564+
}
565+
558566
if let signInEvent = event as? SignInEvent,
559567
case .throwAuthError(let error) = signInEvent.eventType {
560568
let action = ThrowSignInError(error: error)

‎AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/AWSAuthAutoSignInTask.swift

+27-3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class AWSAuthAutoSignInTask: AuthAutoSignInTask, DefaultLogger {
4949
log.verbose("Received result")
5050
return result
5151
} catch {
52+
await waitForSignInCancel()
5253
throw error
5354
}
5455
}
@@ -76,7 +77,8 @@ class AWSAuthAutoSignInTask: AuthAutoSignInTask, DefaultLogger {
7677
AuthPluginErrorConstants.invalidStateError, nil)
7778
throw error
7879
case .signingIn:
79-
continue
80+
log.verbose("Cancelling existing signIn flow")
81+
await sendCancelSignInEvent()
8082
case .configured, .signedOut:
8183
return
8284
default: continue
@@ -85,10 +87,11 @@ class AWSAuthAutoSignInTask: AuthAutoSignInTask, DefaultLogger {
8587
}
8688

8789
private func doAutoSignIn() async throws -> AuthSignInResult {
88-
let stateSequences = await authStateMachine.listen()
8990
log.verbose("Sending autoSignIn event")
9091
try await sendAutoSignInEvent()
92+
9193
log.verbose("Waiting for autoSignIn to complete")
94+
let stateSequences = await authStateMachine.listen()
9295
for await state in stateSequences {
9396
guard case .configured(let authNState, let authZState, _) = state else { continue }
9497

@@ -113,7 +116,28 @@ class AWSAuthAutoSignInTask: AuthAutoSignInTask, DefaultLogger {
113116
}
114117
throw AuthError.unknown("Sign in reached an error state")
115118
}
116-
119+
120+
private func sendCancelSignInEvent() async {
121+
let event = AuthenticationEvent(eventType: .cancelSignIn)
122+
await authStateMachine.send(event)
123+
}
124+
125+
private func waitForSignInCancel() async {
126+
await sendCancelSignInEvent()
127+
let stateSequences = await authStateMachine.listen()
128+
log.verbose("Wait for signIn to cancel")
129+
for await state in stateSequences {
130+
guard case .configured(let authenticationState, _, _) = state else {
131+
continue
132+
}
133+
switch authenticationState {
134+
case .signedOut:
135+
return
136+
default: continue
137+
}
138+
}
139+
}
140+
117141
private func sendAutoSignInEvent() async throws {
118142
let currentState = await authStateMachine.currentState
119143
guard case .configured(_, _, let signUpState) = currentState else {

‎AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/ClientBehaviorTests/SignIn/AWSAuthAutoSignInTests.swift

+74-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import AWSCognitoIdentity
1212
import AWSCognitoIdentityProvider
1313
@_spi(UnknownAWSHTTPServiceError) import AWSClientRuntime
1414

15-
class AutoSignInTests: BasePluginTest {
15+
class AWSAuthAutoSignInTests: BasePluginTest {
1616

1717
override var initialState: AuthState {
1818
AuthState.configured(
@@ -56,6 +56,79 @@ class AutoSignInTests: BasePluginTest {
5656
}
5757
}
5858

59+
/// Test auto sign in success
60+
///
61+
/// - Given: Given an auth plugin with mocked service and in `.signingIn` authentication state and
62+
/// `.signedUp` sign up state
63+
///
64+
/// - When:
65+
/// - I invoke autoSignIn
66+
/// - Then:
67+
/// - I should get a successful result with tokens
68+
///
69+
func testAutoSignInSuccessFromSigningInAuthenticationState() async {
70+
let mockIdentityProvider = MockIdentityProvider(
71+
mockSignUpResponse: { _ in
72+
return .init(
73+
codeDeliveryDetails: .init(
74+
attributeName: "some attribute",
75+
deliveryMedium: .email,
76+
destination: "jeffb@amazon.com"
77+
),
78+
userConfirmed: false,
79+
userSub: "userSub"
80+
)
81+
},
82+
mockInitiateAuthResponse: { input in
83+
return InitiateAuthOutput(
84+
authenticationResult: .init(
85+
accessToken: Defaults.validAccessToken,
86+
expiresIn: 300,
87+
idToken: "idToken",
88+
newDeviceMetadata: nil,
89+
refreshToken: "refreshToken",
90+
tokenType: ""))
91+
},
92+
mockConfirmSignUpResponse: { request in
93+
XCTAssertNil(request.clientMetadata)
94+
XCTAssertNil(request.forceAliasCreation)
95+
return .init(session: "session")
96+
}
97+
)
98+
99+
let initialStateSigningIn = AuthState.configured(
100+
.signingIn(.resolvingChallenge(
101+
.waitingForAnswer(
102+
.init(
103+
challenge: .emailOtp,
104+
availableChallenges: [.emailOtp],
105+
username: "jeffb",
106+
session: nil,
107+
parameters: nil),
108+
.apiBased(.userAuth),
109+
.confirmSignInWithOTP(.init(destination: .email("jeffb@amazon.com")))),
110+
.emailOTP,
111+
.apiBased(.userAuth))),
112+
.configured,
113+
.signedUp(
114+
.init(username: "jeffb", session: "session"),
115+
.init(.completeAutoSignIn("session"))))
116+
117+
let authPluginSigningIn = configureCustomPluginWith(userPool: { mockIdentityProvider },
118+
initialState: initialStateSigningIn)
119+
120+
do {
121+
let result = try await authPluginSigningIn.autoSignIn()
122+
guard case .done = result.nextStep else {
123+
XCTFail("Result should be .done for next step")
124+
return
125+
}
126+
XCTAssertTrue(result.isSignedIn, "Signin result should be complete")
127+
} catch {
128+
XCTFail("Received failure with error \(error)")
129+
}
130+
}
131+
59132
/// Test auto sign in failure
60133
///
61134
/// - Given: Given an auth plugin with mocked service and in `.notStarted` sign up state
@@ -331,7 +404,6 @@ class AutoSignInTests: BasePluginTest {
331404
}
332405
}
333406

334-
335407
// MARK: - Service error for initiateAuth
336408

337409
/// Test a autoSignIn with an `InternalErrorException` from service

‎Package.resolved

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
"kind" : "remoteSourceControl",
4242
"location" : "https://github.com/smithy-lang/smithy-swift",
4343
"state" : {
44-
"revision" : "0d4d3eae8cfb04f3e0cbc4e7740e7344cc9fac55",
45-
"version" : "0.87.0"
44+
"revision" : "697ab725e92622427f536c2f2a176f0dbecb3776",
45+
"version" : "0.90.0"
4646
}
4747
},
4848
{

0 commit comments

Comments
 (0)
Please sign in to comment.