How to refresh FCM Token on user Logout? - ios

I am getting the FCM first time and save it to my userDefaults. Now When user logs out, how can I refresh the FCM token again? I have searched the docs and many other asked questions, but didn't find a better solution.
Thanks in advance.

The FCM Token is an Instance ID token, it represents the installed app and not the signed in user. Generally once the app remains installed it will have the same token no matter what user is signed in.
You would have to manage what user is associated to the token yourself. When the user signs in you should associate the token with the user's ID and when the user signs out you should remove that association.

To get a new refreshed FCM token (forcefully), first you have to delete it and then request for FCM token again. It will always provide a new token after once deletion.
To delete a saved token:
FirebaseMessaging.getInstance().deleteToken()
To request a FCM token:
Firebase.messaging.isAutoInitEnabled = true
// Get token
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
//On token fetch fail
if (!task.isSuccessful) {
//msg_token_failed
Log.e("Token failed", task.exception)
return#OnCompleteListener
}
// Get new Instance ID token
val newDeviceToken = task.result
Log.e("newDeviceToken", newDeviceToken)
})
So, in your case you can delete FCM token on logout and request it again on login. It will work.

Check this post:
Firebase Cloud Messaging - Handling logout
Mentioned security issue in #Arthur's comment is solved!

Related

Sign In With Apple refresh token validation only access token returned

I'm using the AppleAuth npm package in my server to submit token requests to Apple's servers during the sign in with Apple process. (This is based off the sample server code provided with the sign_in_with_apple package in pub.dev) I have no issues submitting the authorization code to get my first access and refresh tokens.
However, when trying to test how my app would get a new refresh token, when I submit a POST request to https://appleid.apple.com/auth/token with the grant_type set to refresh_token the response I get is different than from having the grant_type set to authorization_code.
I looked at the source code of the package, and for its AppleAuth(myConfig).refreshToken(myRefreshToken) (<- pseudo code lol) the only difference in the POST payload is:
{
grant_type: 'refresh_token', // instead of grant_type: 'authorization_code'
refresh_token: refreshToken, // instead of code: authorizationCode
... // other params
}
While the initial request with authorization code returns both an access token and a refresh token, for some reason the refresh token request is only returning the access token. I really don't think it's the package causing the error, nor can I see how my code would be the source either, since the above code is the only difference.
I tried passing the access token that it returns in a new refresh token request in order to test that I can get new refresh tokens whenever necessary in the future, but it returns a 400 status error.
Am I missing something here? Is there a reason the refresh token request returns no new refresh token? Or am I missing something entirely about how the process/flow is supposed to work? I am trying to do this for the "check the refresh token once daily to confirm the user is still in good standing with Apple's servers" part of the process.
I've really been stuck on what to do at this point. I can save the identity_token.sub field in my database to check whether my user is signed in, but of course I want to make sure my user's apple ID is still valid with apple, and that they haven't revoked access. Could it be that because I tried to get a new refresh_token too soon Apple only returned the access_token?
Oh also, the app itself is a Flutter app and I am testing all of this on my iPhone 11 so it's not an Android/Web flow.
Whether you get a new 'rolling / rotating' refresh token in a refresh token grant response is generally vendor specific:
You may get a new refresh token occasionally but not always
The primary purpose of this message is to get a new access token, not a new refresh token
In terms of token handling, the client should update its tokens similarly to the saveTokens method in this sample of mine.
I've not used Sign In with Apple but I suspect proceeding as follows would be the simplest solution:
Keep access tokens short lived: no more than 60 minutes
This forces a frequent token refresh, which by default is very quick
If the user's Apple Id is revoked I would expect this to return an invalid_grant response

How to refresh the tokens in Apple

Scenario :
User should not be logged out once tokens expired .
Apple sign up steps :
Successfully validated the authorization code and got a successful response
{ "access_token" : "",,"refresh_token" : "",expires_in: ""}
Successfully validated the refresh_token obtained from above step and generated a new access token using POST call to https://appleid.apple.com/auth/token
Problem:
How generate user data,id_token from the new access token ?
There is no UserInfo API in Apple's ecosystem now.
Their access tokens are useless at all.
The only way to get user's display name is receiving "user" json object at callback url at the first time authorization.
For email, you can get it in id_token too.

Apple sign in get user data with access token

I have a question about apple sign in. I just implemented an apple sign in, and I found that I received an identity token, access token, and refresh token. It seems that the identity token has user information in the json web token. I am wondering how I can use the access symbol to receive user information? Facebook and also Google has own endpoint where if I send in that endpoint access token I retrieve user data. Does apple sign in has something similar?
Thanks for the information
To get the user_data(email,name) I am using the following code:
if id_token:
decoded = jwt.decode(id_token, "", verify=False)
response_data.update(
{"email": decoded["email"], "name": decoded["name"]}
) if "email" in decoded else None
response_data.update({"uid": decoded["sub"]}) if "sub" in decoded else None
Here, after successfully receiving id token from "https://appleid.apple.com/auth/token" just decode the id_token and get data from it using the appropiriate fields.
Hope this solves your problem of how to get user data from apple social login.
Apple's system is basically like oAuth ... see https://oauth.net/2/

Expired FB token in Parse User table is not updated

Once a user's token expires (either because of the expiration date or because the app was removed from the FB apps list) any graph request generates an error (in my case error 190) because of the invalid token.
If the user tries to log in again I get a new token but that token does not get stored in the parse User table. For the login I use:
PFFacebookUtils.logInInBackground(withReadPermissions: permissions) {(returnedUser, error) in
I'm expecting Parse SDK to update the AuthData entry for that user with the new token and expiration date but that's not happening. Any idea why is that?

Refresh token is not returned after initial authorization

This is a follow up to question Not receiving Google OAuth refresh token
The answer is "The refresh_token is only provided on the first authorization from the user."
After revoking rights for the app and trying to authorize again, refresh token is not returned. What I get is:
{
"access_token" : "XXXX..",
"token_type" : "Bearer",
"expires_in" : 3600,
"id_token" : "XXXX..."
}
Others suggested to use access_type=offline however, according to description offline access is used if:
"application needs to access a Google API when the user is not present
at the browser"
which isn't the case for me.
What is a proper way to get refresh token?
You only get a refresh token if access_type=offline is set. You have two choices of how to handle this:
Don't use access_type=offline. Your access token will be good for 1 hour. After the access token expires, re-prompt the user to authenticate again. They'll need to do the whole OAuth dance again so that you can get a new access token.
Use access_type=offline so that you can get a new access tokens via the refresh token. If you prefer, after the user logs out, you can revoke the tokens.
Every time When you reload you application page , Access Token is Refreshed or you can say the refresh token for this purpose you should use the following but First You Need the authentication
gapi.auth.getToken().access_token;
i am also doing the same thing by the following Way
var accessToken = gapi.auth.getToken().access_token;
var xhr = new XMLHttpRequest();
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
You can use this to avoid your problem "refresh token is not returned".
Thank You!!

Resources