from the below image in firebase docs they are saying that when user sign to app send their sign-in credentials with username(email) and password, they said that response will contain a custom token but for me in the response only showing access token and refresh token, if we use any of these two token for signInWithCustomToken getting an error of invalid token, please pull me out of this issue
Thanks in advance
I think you are misunderstanding this. For custom auth, you are typically using your own auth system and not Firebase. Following the docs, they assume you are using your own username/password auth system. In that case, you send both to your backend server. You verify the credentials (username, password) in your own auth system. If they are legit, you lookup the user id in your auth system database, you then use the Firebase Admin SDK createCustomToken(uid) to mint a custom token with that uid. You send it back in the response to the client. The client will then call signInWithCustomToken to complete the sign-in.
Related
I am working on project using Next JS + NextAuth package. For user authentication we are using NextAuth with Custom Credentials provider. I am making a sign in REst API request to Firebase to get the user logged in and saving all necessary bits like Firebase tokens(access and refresh) in JWT.
The flow works.
Where i am stuck: Changing user password.
Password change is pretty straight forward using firebase client SDK. But I am using Firebase API:
https://firebase.google.com/docs/reference/rest/auth#section-change-password
the flow to change password requires:
Provide latest access token in API request above.
If the latest Access token is not provided, the API would send back error like: TOKEN TOO OLD or RE AUTHENTICATE
So this to work, we need to reauthenticate the user prior to making that change password request.
What I have managed to do:
When user request password change, user needs to provide current password.
Using the current password, i would re sign in user using API end point:
https://firebase.google.com/docs/reference/rest/auth#section-sign-in-email-password
This would work but now I need to update the latest access token in the JWT using NextAuth.
At this point i am stuck:
Refreshing the JWT using Next Auth; as soon as the user is re-signed-in and again when password is changed and new access token is sent back from Firebase.
When I try to refresh the JWT with new access token (etc) token using NextAuth client side callback: https://next-auth.js.org/tutorials/refresh-token-rotation
The application breaks due to access tokens are not synced on JWT and on firebase.
Questions:
Is my flow correct changing the user password?
Is there better way of doing this?
Any help is appreciated. Thanks
I'm trying to implement OAuth 2.0 device authorization for a Firebase project that uses the Email / Password provider for sign in.
In a response from a previous question I was able to test device authorization using a Firebase Device Flow project and the Github and Google providers successfully.
For each of these providers there is an endpoint that is used to request a device code:
Google https://oauth2.googleapis.com/device/code
Github https://github.com/login/device/code
Facebook has the following endpoint, which I have successfully tested:
Facebook https://graph.facebook.com/v2.6/device/login
Is there an equivalent device code authorization endpoint for the Email / Password provider?
EDIT: Looking at the firebase auth library I don't see a credential method that takes an access token. This implies perhaps this isn't possible. Perhaps something could be built to use the credentialWithLink method; an email would be sent with device id and the sign in would enable the polling client to receive a response with a link.
I ended up building the infrastructure myself by setting up:
Endpoints: to get a device token, sign in to validate the device code, get a custom user token for a device token
Website: for the user to enter in credentials to send to validate the device code
Client app: to request the device token, show the qr code and poll for the user token and swap the custom token using the firebase auth method signInWithCustomToken
I used firestore to store the device tokens and update them with the uid, expiry timestamp and verification state with each step.
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
I can sign in users to Firebase using this HTTP API:
How do I sign out users, so that the Firebase idToken and refreshToken can no longer be used?
Also, how long is the refreshToken valid for?
If my user does not use my app for weeks, can I still use the refreshToken or will I need to get a fresh Google Sign In idToken and exchange it for a Firebase (idToken, refreshToken) pair via the /identitytoolkit/v3/relyingparty/verifyAssertion API?
I don't believe there is a sign out endpoint. You could try doing a redirect to https://accounts.google.com/Logout but I suspect that is signing out from all Google services which might not be a great idea.
The whole point of Refresh Tokens is that they can be used to access resources whether or not the user is present and signed in, so your comment "How do I sign out users, so that the Firebase idToken and refreshToken can no longer be used" is an oxymoron.
A Refresh Token is theoretically valid until a user specifically revokes it, but your app should code for the possibility that Google has expired it.
The client cannot directly revoke the ID token via the REST API, but both the Firebase Auth client SDKs (ex: Android) and the Auth Admin SDK do support it. So if your client platform isn't supported, but you are able to create a small server implementation (maybe through Firebase/Cloud Functions), you can create an HTTP endpoint that triggers ID token revocation.
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);
});