How do I refresh the Firebase Provider Access Token? - firebase

Is there a Firebase method to access and refresh the OAuth Provider token, similar to the Firebase ID Token?
I'm using Firebase Auth with Microsoft as my provider. Firebase returns two tokens:
Provider Access Token: this is the Microsoft token that I can use to make calls to Microsoft APIs
Firebase ID Token: this is the Firebase Auth token that I can use to access Google resources
I'm using signInWithRedirect and getRedirectResult to access these tokens:
signInWithRedirect(authInstance, provider)
# ...later in the file handle redirect
const result = await getRedirectResult(authInstance)
if (result) {
const credential = OAuthProvider.credentialFromResult(result)
const accessToken = credential?.accessToken
const idToken = credential?.idToken
}
There is an easy method to access the Firebase ID token that will automatically refresh it if expires, for example: authInstance.currentUser.getIdToken(). I'm having to set the accessToken in a cookie because there doesn't appear to be a method to retrieve it from Firebase. After one hour, the accessToken expires and I need to refresh it.
I can't find an easy way to retrieve and refresh the Provider Access Token outside of the getRedirectResult(). The OAuthProvider.credentialFromResult() method receives a UserCredential type that only seems to be returned after logging in.
How have others solved this issue -- how do you access and refresh the Provider Token in a place after the initial login?

Related

Does firebase auth store and manage access token for different provider

I am working on a flutter app where the user will sign-in using Facebook. Later I want to access facebook graph API and for then I need the access token of the user.
I of now I am storing the access token in firestore and assessing from there. But is there any way using which we can get the access token from currentUser. Because in the current situation the access then gets expired and I need to refresh it again and again. Does firebase handle it automatically?
Below is my code which I use to sign in with Facebook using firebase.
FacebookLogin facebookLogin = new FacebookLogin();
FacebookLoginResult result = await facebookLogin.logIn(['email', 'public_profile', 'user_friends']);
switch (result.status) {
case FacebookLoginStatus.loggedIn:
AuthCredential authCredential = FacebookAuthProvider.getCredential(accessToken: result.accessToken.token);
FirebaseUser user = (await FirebaseAuth.instance.signInWithCredential(authCredential)).user;
//Here I save user details in firestore
}
In order to do this you will need to set up your own token via Facebook's sign in system. When you sign in using Facebook, you can configure it such that their token IS the Facebook token as well.
Check out this for a from-scratch Facebook login.
And this for creating a custom Firebase token.

When using Firebase.auth, accessToken expire after 1h, how do we get a refreshToken?

We are using Firebase with VueJS to manage sign-in to our application. And we also need to access other Google APIs using the accessToken, unfortunatly, the token expire after one hour.
import firebase from 'firebase'
firebase.auth().signInWithPopup(provider)
.then(firebaseUser => {
var accessToken = firebaseUser.credential.accessToken;
})
How can we renew periodicaly the accessToken in order to keep accessing other google API without having to sign-out and sign-in from Firebase ?
I've done some research and i did not find any suitable, simple solution to this issue.
Similar questions
Application expires after 1h even when regularly reporting my activity
Retrieve Google Access Token after authenticated using Firebase Authentication
Edit
This question is related to the refresh of accessToken not IdToken
firebaseUser.credential:
accessToken: "ya29.GlwyBic64v6PW8......"
idToken: "eyJhbGciOiJSUzI1NiIsImt...."
providerId: "google.com"

How can I create long-lived tokens with Firebase Node.js SDK

I'm trying to implement the Authorization Code Flow to link actions on google with my firebase users:
https://developers.google.com/actions/identity/oauth2-code-flow
So far I've understood the flow as follows:
1 - User access the application and is redirected to the authorization url endpoint
2 - User signs in and google receives an authorization token
3 - Google sends this authorization token to the token url endpoint and gets an access token a refresh_token and a expiration time
4 - Google sends the refresh token to get a new access token when the access token is going to expire and gets a new acess token and a new expiration time
Did I get everything right?
As authorization token and access token I'm using the custom tokens from Firebase. My question is, how can I implement the refresh token? I cannot get this token from the Firebase Node.js SDK server side.
How can I greate long-lived tokens with Firebase Node.js SDK?
Is there another approach?
Yes, you got the OAuth2 process right.
The Firebase Admin SDK lets you sign the user in to your Firebase service using generated custom tokens. Though the custom token expires within 1 hour, once user is signed-in, they should be authenticated indefinitely (i.e. until user signs out). As such, there is really no need for SDK to generate refresh token.
I'd suggest a different approach. Use Actions on Google's SignIn helper intent to get user's info, such as email, name etc. Using this info, you will be able to sign the user in to Firebase as follows (referenced from the "Create Custom Token" Firebase doc):
var uid = "some-uid";
admin.auth().createCustomToken(uid)
// token == custom token
.then(function(token) {
firebase.auth().signInWithCustomToken(token).catch(function(error)
{
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
})
.catch(function(error) {
console.log("Error creating custom token:", error);
});
References:
"How to use refresh token?" from Firebase's GitHub
"Create custom tokens" from Firebase's docs
"Request Signin helper" from Actions on Google docs

Get Google access token

To get Google access token after firebase auth login, I know I can simply do this:
firebase.auth().signInWithPopup(provider).then(function(result) {
var token = result.credential.accessToken;
}
but what if the user is already authenticated and I need the token? is there any way to extract it from the Firebase auth?
I've been through every value of authState but I couldn't find the google access token I've been looking for.
You can't get the access token from the onAuthStateChanged listener or the currentUser. You can only get it immediately after authentication when calling signInWithPopup, reauthenticateWithPopup, linkWithPopup, getRedirectResult, etc. Firebase Auth does not manage OAuth tokens for users. If you feel strongly about this feature, please file a feature request for it on the Firebase forum: https://groups.google.com/forum/#!forum/firebase-talk
You can also just use the GApi library to get the Google access token and pass it to Firebase to sign-in via signInWithCredential. The advantage here is that GApi will manage that OAuth token for you.

Authenticate with signInWithCredential()

I'm trying to connect to the second Firebase app and authenticate with signInWithCredential(), but I don't know how to get valid idToken for the second app:
connect(accessToken: string, config: FirebaseAppConfig) {
let one: firebase.app.App = this.angularFireTwo.database["fbApp"];
one.auth().currentUser.getToken()
.then(idToken => firebase.auth.GoogleAuthProvider.credential(idToken, accessToken))
.then(credential => {
let two = firebase.initializeApp(config, `[${config.apiKey}]`);
return two.auth().signInWithCredential(credential);
})
.catch(console.warn)
.then(console.info);
}
I'm getting and error from https://www.googleapis.com/identitytoolkit/v3/:
Invalid id_token in IdP response
If I use signInWithPopup() I can authenticate and connection is working:
two.auth().signInWithPopup(new firebase.auth.GoogleAuthProvider())
Anyone knows what should I do to get valid idToken?
UPDATE:
I've been trying to figure out authentication process and, as far I understand it , it's something like this:
from config: FirebaseAppConfig firebase reads apiKey and authDomain
it contacts the servers and gets Web Client ID for enabled Google provider 123.apps.googleusercontent.com
with this Web Client ID and authDomain it contacts www.googleapis.com, which returns idToken
this idToken is then used to identify the app that's asking user for permission to access user's profile, etc.
when user agrees, callback returns user details + credential used for this authentication, which contains idToken of the web app and accessToken of the user
Now, if I use signInWithPopup() steps 2-3-4 are done in the background (popup window). I just need a way to generate idToken for the step 4, so I can use it to generate credential firebase.auth.GoogleAuthProvider.credential(idToken, accessToken) and sign-in using signInWithCredential().
I have access to everything I need to sign-in to the second app - it's; apiKey, authDomain, Web Client id 456.apps.googleusercontent.com, and user's unique accessToken.
But still can't figure out how to do it. I tried white-listing apps' one and two Web client IDs in their auth configurations, hoping that will allow them to accept each others idTokens, but that didn't work...
When you call:
firebase.auth.GoogleAuthProvider.credential(idToken, accessToken))
The first parameter should be a Google OAuth Id token. You are using the Firebase Id token and that is why you getting the error. Besides, if you are already logged in, why are you logging in again with signInWithCredential?
If you need to sign in with a Google credential you need either a Google OAuth Id token or a Google OAuth access token.
To duplicate Firebase OAuth sign-in state from one app to another, you get the credential from signInWithPopup result and use it to signInWithCredential in the second instance.
two.auth().signInWithPopup(new firebase.auth.GoogleAuthProvider())
.then(function(result) {
return one.auth().signInWithCredential(result.credential);
});

Resources