I've been working on learning Amplify Framework for Android in Kotlin. Previously, with help from the SO community, I was able to set up Authentication via the Cognito Hosted UI. I could sign in and out, and query a DynamoDB user table, cool.
I was using a second Activity AuthActivity with a viewmodel to handle login/logout. However, I want to migrate to a 1 Activity n Fragments system. The viewmodel had the Amplify auth calls defined (bad I know), so I whipped up a LoginFragment that utilizes the same viewmodel. Then, I added the HostedUIRedirectActivity to AndroidManifestto upgrade from the Response Handler described in the docs. Not sure why I didn't do that originally, but it is the root of my problem.
The Problem
After updating AndroidManifest, the sign in/out flows using the Cognito Hosted UI are producing errors and otherwise strange behavior. Amplify.Auth.signOut() calls respond with a timeout error, and I can set a breakpoint in the onError callback to prove it. Amplify.Auth.signInWithWebUI() seemingly works by bringing me to the Hosted UI, and then back to the LoginFragment, but is not hitting any of the code in the onSuccess callback. Also, once the user is logged in and the Login button is clicked again, the Hosted UI flashes for a second, but I expect it to ask to sign in as the same user or another user.
What I've Done
- Moved the auth code straight into the
LoginFragmentto make it easy to post here, got the same behavior. - Noticed that in the Hosted UI Activity in
AndroidManifesthad a line<data android:scheme="myapp" />so I changed that value to the actual name of the app. The problem persists. - Noticed in the docs that Amplify versions 1.17.7 and below "have known issues with sign-out after signing in via web UI". This sounded likely to be my issue, so I did a
npm i -g @aws-amplify/clito update just in case. I'm on version 5.0. Problem persists.
I will post my code below. I can clarify anything or post more if necessary. Any help or suggestions are greatly appreciated. Thanks!
My Code
class LoginFragment : Fragment() {
private val viewmodel: AuthViewModel by viewModels()
private lateinit var binding: FragmentLoginBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
// Inflate the layout for this fragment
binding = FragmentLoginBinding.inflate(inflater)
binding.authViewModel = viewmodel
val view = binding.root
binding.btnSignIn.setOnClickListener { btnLoginOnClick(view) }
binding.btnSignout.setOnClickListener { btnLogoutOnClick(view) }
return view
}
fun signInWithWebUI(a: Activity) {
Amplify.Auth.signInWithWebUI(a,
{ Log.i(tag, "loginSuccess") },
{ Log.e(tag, "loginError", it) } )
}
fun btnLoginOnClick(view: View) { signInWithWebUI(activity as MainActivity) }
fun signOut() {
Amplify.Auth.signOut(
{ Log.i(tag, "logoutSuccess") },
{ Log.e(tag, "logoutError", it) } )
}
fun btnLogoutOnClick(view: View) { signOut() }
}