I have just started learning AWS Amplify and I am integrating it to my android project to authenticate users. I have successfully logged-in but UserState is still SIGNED_OUT.
AWSMobileClient.getInstance().signIn(userName, password, null, callback)
Callback Code snippet
fun fetchAuthenticationCallBack(): Callback<SignInResult> {
return object : Callback<SignInResult> {
override fun onResult(result: SignInResult?) {
when (result?.signInState) {
SignInState.DONE -> {
// AWSMobileClient.getInstance().confirmSignIn()
Log.d(TAG, "LOGIN SUCCESS ${AWSMobileClient.getInstance().tokens.accessToken}")
}
SignInState.NEW_PASSWORD_REQUIRED -> {
Log.d(TAG, "NEW PASSWORD CHALLENGE")
}
else -> {
// Unsupported sign-in confirmation:
}
}
}
override fun onError(e: java.lang.Exception?) {
TODO("Not yet implemented")
}
}
}
I want to get the accessToken but it gives me Exception
Token does not support retrieving while user is SIGN_OUT
Is there anything that I am missing in the authentication part?
If anyone will face this issue in the future.
Kindly check your awsconfiguration.json file there is something went wrong. In my case CognitoIdentity credentials were wrong. I have just fixed the awsconfiguration.json file everything is working as expected
Related
I've been struggling with this problem for more than a week help me out if you know the fix.
enter image description here
I am trying to delete the data from a child node in the Realtime Firebase but it keeps regenerating even when I delete the token data.
This is my code:
when a user logs in an FCM token is generated automatically (onCreate).
when I try to log him out of his account I want the token to be deleted from the token list but it keeps regenerating even when I logout
this is the User fragment is redirected to after login:
val currentUser : String = firebaseAuth.currentUser?.uid.toString()
val databaseReference = FirebaseDatabase.getInstance("https://trial-38785-default-rtdb.firebaseio.com/")
.getReference("AppUsers").child("Doctor").child(currentUser)
FirebaseMessaging.getInstance().token.addOnCompleteListener {
if (it.isComplete) {
val firebaseToken = it.result.toString()
val myRef =
FirebaseDatabase.getInstance("https://trial-38785-default-rtdb.firebaseio.com/")
.getReference("AppUsers").child("Doctor").child(currentUser)
myRef.child("Token").orderByChild("token").equalTo(firebaseToken)
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val token : Token = Token(firebaseToken)
if (snapshot.exists()) {
return
} else {
databaseReference.child("Token")
.child(currentdate.toString()).setValue(token)
}
}
override fun onCancelled(error: DatabaseError) {
Toast.makeText(context, error.message, Toast.LENGTH_LONG).show()
}
})
}
}.addOnFailureListener {
Toast.makeText(context, it.message, Toast.LENGTH_LONG).show()
}
This is another fragment where the doctor logout.
pressing logout button this is the code i ran
val delRef = FirebaseDatabase.getInstance().getReference("AppUsers")
.child("Doctor").child(currentId.toString())
.child("Token").child(key.toString()).removeValue()
delRef.addOnSuccessListener {
println("Removed.")
}.addOnFailureListener {
println("Not Removed.")
}
When using the Query#addValueEventListener() method, it means that you are trying to listen for real-time updates. That being said, every change that takes place in the database and corresponds to your query, always triggers your onDataChange() method. Since when you are logging out, you remove a value from the query you are listening to, your token gets written again, hence that behavior. This is happening over and over again.
To solve this, simply change the above method call to Query#addListenerForSingleValueEvent(). This means that it listen for changes only once.
I finally figured out what I was doing wrong, I just had to move my code (myRef) outside of FirebaseMessaging.
I am trying to implement MSAL in Android for logging in user using their Microsoft credentials.
On clean install, first time I am able to get the token, and use it further for accessing Microsoft Graph API.
As expiry time for MSAL token is 1 hour by default, after 1 hour if I try to re-start the app, I face token authentication exception.
Now I am stuck on how to refresh the token again ?
In MSAL I have followed the examples, but nowhere is there any mention of refreshing a token using Android SDK [we can use API calls otherwise to get and refresh token, but I am not using API approach, I am using SDK for handling all the flow.]
I am trying to get through this for some days now.
private val AUTHORITY = "https://login.microsoftonline.com/common"
private var mSingleAccountApp: ISingleAccountPublicClientApplication? = null
private var mActiveAccount: MultiTenantAccount? = null
fun startTokenProcess(
activity: LoginActivity,
preferenceManager: PreferenceManager
) {
this.mActivity = activity
this.mPreferences = preferenceManager
mSingleAccountApp = null
// Creates a PublicClientApplication object with res/raw/auth_config.json
PublicClientApplication.createSingleAccountPublicClientApplication(activity,
R.raw.auth_config,
object : IPublicClientApplication.ISingleAccountApplicationCreatedListener {
override fun onCreated(application: ISingleAccountPublicClientApplication?) {
// initialization of ISingleAccountPublicClientApplication object
mSingleAccountApp = application
// check for existence of any account linked in cache
mSingleAccountApp?.getCurrentAccountAsync(object :
ISingleAccountPublicClientApplication.CurrentAccountCallback {
override fun onAccountLoaded(activeAccount: IAccount?) {
if (activeAccount == null) {
// nothing found
// start new interactive signin
mSingleAccountApp?.signIn(mActivity, "", getScopes(),
object : AuthenticationCallback {
override fun onSuccess(authenticationResult: IAuthenticationResult?) {
mActiveAccount =
authenticationResult?.account as MultiTenantAccount?
// save access token in SP
authenticationResult?.accessToken?.let {
mPreferences.putString(
KEY_ACCESS_TOKEN,
it
)
}
callGraphAPI(authenticationResult?.accessToken)
}
override fun onCancel() {
Timber.d("Canceled")
}
override fun onError(exception: MsalException?) {
Timber.d(exception?.errorCode)
}
})
} else {
// Founded an valid account in cache
// get account token from SP, call Graph API
// todo: check if access token expired ? ask for new token, clear SP
mActiveAccount = activeAccount as MultiTenantAccount?
val accessToken = mPreferences.getString(KEY_ACCESS_TOKEN)
if (accessToken != null) {
callGraphAPI(accessToken)
}
}
}
override fun onAccountChanged(
priorAccount: IAccount?,
currentAccount: IAccount?
) {
Timber.d("Founded an account $priorAccount")
Timber.d("Founded an account $currentAccount")
}
override fun onError(exception: MsalException) {
Timber.e(exception)
}
})
}
override fun onError(exception: MsalException?) {
Timber.e(exception)
}
})
}
I have tried to get token Silently and Interactively again, but no success.
SILENTLY:
mSingleAccountApp?.acquireTokenSilentAsync(getScopes(), AUTHORITY, getAuthSilentCallback())
private fun getAuthSilentCallback(): SilentAuthenticationCallback {
return object : SilentAuthenticationCallback {
override fun onSuccess(authenticationResult: IAuthenticationResult) {
Timber.d("Successfully authenticated")
/* Successfully got a token, use it to call a protected resource - MSGraph */
callGraphAPI(authenticationResult?.accessToken)
}
override fun onError(exception: MsalException) {
/* Failed to acquireToken */
Timber.e("Authentication failed: $exception")
if (exception is MsalClientException) {
Timber.e("Exception inside MSAL, more info inside MsalError.java ")
} else if (exception is MsalServiceException) {
Timber.e("Exception when communicating with the STS, likely config issue")
} else if (exception is MsalUiRequiredException) {
Timber.e("Tokens expired or no session, retry with interactive")
}
}
}
}
OR
INTERACTIVELY:
if (activeAccount == null) {
mSingleAccountApp?.signIn(mActivity, "", getScopes(),
object : AuthenticationCallback {
override fun onSuccess(authenticationResult: IAuthenticationResult?) {
mActiveAccount =
authenticationResult?.account as MultiTenantAccount?
// save access token in SP
authenticationResult?.accessToken?.let {
mPreferences.putString(
KEY_ACCESS_TOKEN,
it
)
}
callGraphAPI(authenticationResult?.accessToken)
}
override fun onCancel() {
Timber.d("Canceled")
}
override fun onError(exception: MsalException?) {
Timber.d(exception?.errorCode)
}
})
}
Edit 1:
Exceptions I am geting:
CoreHttpProvider[sendRequestInternal] - 414Graph service exception Error code: InvalidAuthenticationToken
CoreHttpProvider[sendRequestInternal] - 414Error message: Access token has expired.
CoreHttpProvider[sendRequestInternal] - 414SdkVersion : graph-java/v1.9.0
CoreHttpProvider[sendRequestInternal] - 414Authorization : Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI[...]
CoreHttpProvider[sendRequestInternal] - 414Graph service exception Error code: InvalidAuthenticationToken
Throwable detail: com.microsoft.graph.http.GraphServiceException: Error code: InvalidAuthenticationToken
Error message: Access token has expired.
When I re-try to get token silently, I get the following exception:
l$getAuthSilentCallback: Authentication failed: com.microsoft.identity.client.exception.MsalServiceException: AADSTS700016: Application with identifier 'Some_ID' was not found in the directory 'Some_ID'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.
Trace ID: 'Some_ID'
Correlation ID: 'Some_ID'
Timestamp: 2020-08-15 06:06:11Z
getAuthSilentCallback: Exception when communicating with the STS, likely config issue
Edit 2
As per exceptions I was getting regarding config issue, I got the issue, it was related to the Authority URL which I was using. msal-client-application-configuration
DIAGNOSING
Are there any error details you can provide? And have you traced the HTTPS token refresh message?
WHAT IT SHOULD LOOK LIKE
The MSAL library should be sending a Refresh Token Grant message, as in steps 15 and 16 of my blog post.
My app uses AppAuth libraries but MSAL will work the same way, since that is standard for a mobile app.
I am using Pusher Beams for sending notification to my users. It worked fine but today I got this error, and I don't know how to solve it.
PushNotificationsAPI: Failed to register device: NOKResponse(error=Unauthorized, description=The device token provided could not be validated against any known credentials)
This is my code:
private fun setPusherBeam() {
try {
val tokenProvider = BeamsTokenProvider(
BuildConfig.PUSHER_BEAM,
object : AuthDataGetter {
override fun getAuthData(): AuthData {
return AuthData(
headers = hashMapOf(
"Authorization" to getHawkString(AUTH_TOKEN)
),
queryParams = hashMapOf()
)
}
}
)
PushNotifications.setUserId(
DbHelper.getUser()?.user_id.toString(),
tokenProvider,
object : BeamsCallback<Void, PusherCallbackError> {
override fun onFailure(error: PusherCallbackError) {
Timber.i("BeamsAuth Could not login to Beams: ${error.message}")
}
override fun onSuccess(vararg values: Void) {
Timber.i("BeamsAuth Beams login success $values")
}
}
)
} catch (ex: Exception) {
Timber.i("BeamsAuth ex ${ex.localizedMessage}")
}
}
After 2days of struggling with this error, finally, it resolved due to these steps.
1-stop the API
PushNotifications.start(applicationContext, BuildConfig.INSTANCE_ID)
PushNotifications.stop()
PushNotifications.removeDeviceInterest("example")
PushNotifications.clearDeviceInterests()
2-clear android studio cash and reset it
3-remove the app from mobile and reinstall it
4-replace code from step1 with this
PushNotifications.start(applicationContext, BuildConfig.INSTANCE_ID)
PushNotifications.addDeviceInterest("example")
5-repeat 2 and 3
Delete the generated values.xml under app\build\generated\res\google-services\debug\values, then delete the app and build again. Took me a while to figure this out.
I'm trying to make an Android app with a sign in screen on Android in Kotlin using AWS Amplify, here's my sign in code:
AWSMobileClient.getInstance().signIn(username, password, null, object : Callback<SignInResult> {
override fun onResult(signInResult: SignInResult) {
runOnUiThread {
Log.d("DEBUG", "Sign-in callback state: " + signInResult.signInState)
when (signInResult.signInState) {
SignInState.DONE -> Log.d("DEBUG", "Sign-in done.")
SignInState.SMS_MFA -> Log.d("DEBUG", "Please confirm sign-in with SMS.")
SignInState.NEW_PASSWORD_REQUIRED -> Log.d("DEBUG", "Please confirm sign-in with new password.")
else -> Log.d("DEBUG", "Unsupported sign-in confirmation: " + signInResult.signInState)
}
}
}
override fun onError(e: Exception) {
Log.e("DEBUG", "Sign-in error", e)
}
})
I used the documentation of Amazon here, copied and pasted the block found at the Sign In chapter into Android Studio that automatically converted the Java code into Kotlin.
Using logs I see that my code above this one is executed when I press the login button but the onResult block is never called. The logs only print a D/AWSMobileClient: Sending password. from AWS sdk.
I remember that this code worked before Christmas holidays so I think that it's maybe a change on the Amazon side but I find nothing in the documentation.
Do you have any idea of what's wrong here ?
I have an android application which uses Firebase Authentication via Facebook. A user can delete their account in the application using the following function:
override fun deleteUserAcc() {
val user = FirebaseAuth.getInstance().currentUser
val userToken = FacebookAuthProvider.getCredential(authTokenProvider.provideToken())
user?.reauthenticate(userToken)?.addOnCompleteListener { task ->
user.delete()
}
}
After this a user really gets deleted on the Firebase servers. However when they try to access the application again and log in one more time, they are not able to do this (their account with uid had been deleted and somehow they are not assigned a new one uid).
The login function and the onSuccess callback are both implemented and called.
override fun login(): Completable {
LoginManager.getInstance().logInWithReadPermissions(
activityReference.get(),
listOf("public_profile", "user_birthday", "user_location")
)
return CompletableSubject.create().apply {
loginSubject = this
}
}
override fun onSuccess(result: LoginResult) {
val credential = FacebookAuthProvider.getCredential(result.accessToken.token)
authTokenProvider.saveToken(result.accessToken.token)
firebaseAuth.signInWithCredential(credential)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
getInfoOnFirestore(loginSubject)
} else {
loginSubject.onError(task.exception!!)
}
}
}
What can possibly be the cause of the following issue?
A little late to the party but I know what the issue is. Firebase deletes only the authentication, which means that the real-time database is still there with the same uid. In order to delete the database entry as well, you need to upgrade to the blaze program and add the extension.