If I intercept an access_token from an example on this page:
https://developers.google.com/picker/docs/
...it looks like this:
ya29.Glx7BW_OsFJ1CSjJ_kdt9iZixJAZHjvllMtJO09EccpURJPbCXudNP6teBz6HZ0T_ioaQLNna323UPpBQN-N0aCLWXfDVCvq4xXkbi5kKQhfwS0xakcsrNmzD5B8OA
If I paste that into here:
https://jwt.io/
...I'm told it's malformed. However, if I paste a Firebase auth token into there, it's well-formed and you can see its payload.
Ultimately, I'm trying to use the Firebase auth token in the Google Picker API, but I can't figure out how to translate it.
I was using firebase.auth().currentUser.getIdToken, but it looks like firebase.auth().getRedirectResult() gets an auth token that is the same format as the Picker API.
Google API access is scope based https://developers.google.com/identity/protocols/googlescopes
You must specify the scopes needed when requesting an access token.
Each access token you receive back, is limited to the scope and application from its original request. They are not inter-changeable.
You will need to setup a specific Google Picker API request, in order to get the access token you require https://developers.google.com/identity/protocols/OAuth2
Hope this helps
"ya29.*" token is Google's access token and it is not a jwt (it is opaque for the api callers).
Yes firebase allows you to add scopes during the sign-in process. After that you get an id token that says who the user is and a separate access token that you can use to access Google APIs.
If you look at https://firebase.google.com/docs/auth/web/google-signin you will see this:
Then, you can also retrieve the Google provider's OAuth token by calling getRedirectResult when your page loads:
firebase.auth().getRedirectResult().then(function(result) {
if (result.credential) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// ...
}
// The signed-in user info.
var user = result.user;
Related
I'm using Firebase v8 with the GoogleAuthProvider.
Firebase documentation provides the following code to authenticate the user.
firebase.auth().signInWithPopup(provider).then((result) => {
/** #type {firebase.auth.OAuthCredential} */
var credential = result.credential;
// This gives you a Google Access Token. You can use it to access the Google API.
var token = credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
})
Questions
Google's Using OAuth 2.0 to Access Google APIs article recommends incremental authorization (it's not Firebase, but the recommendation is clear)
It is generally a best practice to request scopes incrementally, at
the time access is required, rather than up front. For example, an app
that wants to support saving an event to a calendar should not request
Google Calendar access until the user presses the "Add to Calendar"
button.
AFAICT, there is no way to achieve incremental authorization with Firebase without re-authenticating the user. While scopes can be added to GoogleAuthProvider using addScope, a subsequent call to signInWithPopup is required (i.e. the user is re-authenticated). Is there any way to prompt only for authorization (e.g. Drive access) without re-authenticating?
Assuming the access token is short lived, can the Google ID token be used to obtain a new access token? Is re-authenticating the user the only way to obtain a new access token?
Is there a way to determine whether the access token has expired?
I have a web application where users can sign in with Google.
To the sign-in process, I add a scope to be able to access Google Calendar.
Now that the user is signed in, I would like to - in server-side - get their current Google access token in order to make a request and get a list of their events.
Is there a way to get the current OAuth token (no need for refresh token) in order for me to make this completely on the server-side?
I'd say that you can check this article and put special attention to the recommendation for websites.
I understand you have configured already the consent screen, which is the first step of the basic steps on using OAuth 2.0. So I understand that you only have to perform the following steps:
Obtain an access token from the Google Authorization Server
Examine scopes of access granted by the user.
Send the access token to an API
I think you can also give a look to this other doc for more GCP insights over your goal to authorize the request using user tokens
Edited:
Regarding the Firebase Authentication, I understand this happens at the user's device, and you could use some code to retrieve the token and then send it to your back end servers as mentioned in here.
As a sample here there's the sample code for retrieving the token in Android:
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(#NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// Send token to your backend via HTTPS
// ...
} else {
// Handle error -> task.getException();
}
}
});
A little about OAuth 2.0
Whenever a user signs up to your app/website via Google or 3rd Party, an Authorization Code, this Authorization Code is exchanged for an AccessToken & RefreshToken.
The AccessToken sent via Google are valid generally for 60 minutes.
Offline Access (Server Side)
Let's break it down to two parts:
If your need to update within 60 minutes of user's last activity
You can use firebase along with gapi to achieve that. You'll be provided with the AccessToken that can be sent back to server to add to calendar.
More info on implementation
If you need to update after 60 minutes of user's last activity
Firebase & gapi's most method handle the AuthorizationCode flow internally. They even further refresh the AccessToken after 60 minutes. This is beneficial for most developers as they won't have a headache of managing all the tokens.
This method but, hides RefreshToken & AuthorizationCode from the developer. That is even if your server has the access token, it won't be able to refresh it and it would be deemed useless.
To achieve complete offline access, in the initial request to get AuthorizationCode you will need to send a HTTP GET parameter access_type to offline
GAPI provides you with grantOfflineAccess() method which returns the AuthorizationCode that can be later used on your server to fetch access token & refresh token.
Note: If you are storing AuthorizationCode in your database, make sure it is secure. The limitation in Firebase are set due to security reason. It is more secure to not talk with AuthorizationCode generally.
More links
https://developers.google.com/identity/protocols/oauth2/web-server
https://developers.google.com/identity/sign-in/web/reference
https://developers.google.com/identity/sign-in/web/server-side-flow
https://developers.google.com/identity/sign-in/web/backend-auth
Retrieve Google Access Token after authenticated using Firebase Authentication
I created custom Auth Token via createCustomToken(), see https://firebase.google.com/docs/auth/admin/create-custom-tokens.
But later on when I try to verify this token via verifyIdToken() function it throws following error
Error: verifyIdToken() expects an ID token, but was given a custom token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
Which is rational, because there is no such ID... But what I need - is to simply verify the token, similar to jwt.verify()...
Has anyone came across this problem and what solution was found? Is it possible to verify Firebase auth token via jsonwebtoken library?
P.S. I am gonna use verification in Google Cloud Function endpoints
SOLUTION: Looks like I just found a solution https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library Just need to grap public key from https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com and use jsonwebtoken library to verify it...
verifyIdToken like the name is to verify IdToken, not custom token.
CustomToken is for client to sign in. This custom token can be verify using simple JWT verification like your solution (it expire after one hour).
But the IdToken is another story, you need to do sign in process using firebase auth.
To Get The Id Token from client after signIn, it's depend whether the client is Android, Web, or IOS.
The code to get the IdToken can be read in this section
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.
Suppose, for the sake of argument, that I already have a facebook access token for a user of my application. In that case, I don't really need to go through Firebase's whole auth.login("facebook") process, I really just want a trusted server to make sure this is a real access token (e.g. by making a GET request to "https://graph.facebook.com/me" with it) and then to set the Firebase user ID appropriately. Can Firebase do this?
Firebase Simple Login was recently updated to support logging in with an existing Facebook access token.
This means that you can integrate directly with then native Facebook JS SDK in your application, and then pass that Facebook access token to Firebase Simple Login (skipping a second pop-up) via:
var ref = new Firebase(...);
var auth = new FirebaseSimpleLogin(ref, function(error, user) { ... });
auth.login('facebook', { access_token: '<ACCESS_TOKEN>' });
See the access_token option on https://www.firebase.com/docs/security/simple-login-facebook.html for more information.