I am looking to build an app using Vue with Firebase for auth and SQL Server as the db behind Express.
I understand the db workflow will be:
Vue => Express => MySQL
However, when performing the authentication should the workflow be:
Vue => Express => Firebase
or
Vue => Firebase
There are 2 things involved here. Firebase SDKs are meant to be used on client side so you'll have to first sign in user with Firebase Authentication. This way you can easily use security rules for other Firebase services like Firestore, Cloud storage, etc.
To authenticate users on your server (Express application), you can pass current user's token in your API requests as shown below:
const idToken = await auth.currentUser.getIdToken()
await fetch("URL", { headers: { authorization: idToken } })
Then verify the ID Tokens on the backend that should give you the user ID. You can then query your database for user's data and return it.
Alternatively, you can use session cookies so you won't have to pass the token in headers for all requests. Checkout the documentation for more information.
Related
I've created a custom Firebase App Check provider for my firebase apps. My question is, how do I properly send a successful request using Firestore REST API after getting the token from my custom app check. Thanks!
You need to set the appCheck token in the headers of your request like so
// Include the App Check token with requests to your server.
const apiResponse = await fetch('https://yourFirebaseRestApiURL/Endpoint', {
headers: {
'X-Firebase-AppCheck': appCheckTokenResponse.token,
}
});
This is not documented in the Firestore Rest API but in the AppCheck docs
https://firebase.google.com/docs/app-check/web/custom-resource
Due to some constraints of my project I need to manage my api server and database separately from firebase, however there is nothing stoping me from using their other tools like analytics and in this particular case authentication.
I wanted to ask if following scenario is possible:
I authenticate user on my client app using their SDK's
I send relevant jwt data in headers of my API
Can I then somehow validate this on my server, so in essence avoid complex auth service and use firebase for this instead? Are there any examples, preferably for NodeJS server.
Yes you can, it's very common use case and firebase auth has been made with such usage in mind. As you said, send jwt data on headers, then on the server, you verify the token with firebase service:
var admin = require('firebase-admin');
admin.initializeApp(); //may require other steps, see last link
// idToken comes from the client app
admin.auth().verifyIdToken(idToken, true)//second argument is optional, checks whether the ID token was revoked
.then(function(decodedToken) {
let uid = decodedToken.uid;
// ...
}).catch(function(error) {
// Handle error
});
https://firebase.google.com/docs/auth/admin/verify-id-tokens
https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#verifyidtoken
https://firebase.google.com/docs/admin/setup
I an planning to make a social media application using flutter. I want to give the user ability to sign in using Google or Facebook accounts which can be easily done using firebase authentication but I am worried about the cost because within 2 months the number of users will be approximately 100,000. I was thinking of we could just sign up/sign in using firebase and store data and push/pull all the other requests from a hostgator server(mysql db).
And if it is possible can I do it using just dart language or do I need some other languages too like ruby, C# it python (I am not a big fan of php)
Yes, you can use Firebase just for authentication and your mysql db on Hostgator for everything else. Firebase auth is free (except to phone auth), as #Doug Stevenson has mentioned.
The (firebase) authentication can be done in your Flutter app. You do not need a server code to do this. Firebase auth gives back 'user' object with attributes like user name, email, profile photo url etc which you can store in your mySQL db as well (if required).
Firebase Authentication doesn't cost anything to use for signing in with Google or Facebook accounts. It doesn't cost any more based on the number of users you have. You are only going to be charged if you use phone authentication past the initial free tier limits, as described on the pricing page. So I wouldn't bee too concerned about costs.
You can do all the signups in client app code. You don't need a backend at all to use Firebase Auth, but you can bring any backend you want.
import 'package:express/express.dart';
import 'package:firebase_admin/firebase_admin.dart';
void main() async {
// Initialize the Firebase Admin SDK
await FirebaseAdmin.initializeApp(
credential: FirebaseAdmin.ServiceAccountCredential(
'/path/to/serviceAccountKey.json'));
// Create a new Express app
var app = Express();
// Implement the API endpoint for authentication
app.post('/login', (request, response) async {
// Get the user's email and password from the request body
var email = request.body['email'];
var password = request.body['password'];
// Verify the user's credentials using the Firebase Admin SDK
try {
var userRecord = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
// If the login was successful, create a new session for the user
request.session['uid'] = userRecord.uid;
// Return a success response
response.send({'success': true});
} catch (error) {
// If the login failed, return an error response
response.send({'success': false, 'error': error.toString()});
}
});
// Start the server
app.listen(3000);
}
Using react-native-firebase:4.3.x
I'm able to connect to RealtimeDB, us requiring security we've set up rules.
But looking through the docs I can't find where how to setup Auth token payload when connecting to firebase. All it has is to connect to DB call the following:
db = firebase.database();
no parameters or anything. Am I to use, the firebase.auth()?
Short answer: Our whole approach on Firebase RealtimeDB's ruleset was incorrect from the beginning; we had done the rules without understanding Firebase Auth and its tie in with RealtimeDB. We had setup, rules based on uid and RealtimeDB only, storing some random token on RealtimeDB hoping we could somehow pass the token on auth payload to the user.
Long answer:
As stated on Firebase's own Database Security docs Database Rules directly uses Firebase Authentication.
From then on, implemented Custom authentication from Authentication RNFirebase.io
client side:
let postLogin = (userCredentials) => {
db = firebase.database();
//...do stuff
}
firebase
.auth()
.signInAndRetrieveDataWithCustomToken(token)
.then(postLogin);
firebase console:
Project Settings -> Service Accounts -> Generate new private key.
which generates json formatted firebase private key and some identifier values. Import that in whatever library you're using on server-side in our case kreait/firebase-php
Do not enable anonymous authentication, that would defeat the purpose.
php using kreait/firebase.php:
use Kreait\Firebase\Factory;
use Kreait\Firebase\ServiceAccount;
$serviceAccount = ServiceAccount::fromJsonFile($pathToJson);
$firebase = (new Factory())
->withServiceAccount($serviceAccount)
->create();
$token = (string) $firebase->getAuth()->createCustomToken($uid, $payload)
I did not need to be aware of payload on client side. It is passed through client side in the signed JWToken.
I'm currently developing a node.js service with firebase 3.0 that is called by a web application that uses firebase 2.4.
I'm sending the current user Firebase ID token (Auth.$getAuth().token) in my header call and trying to validade this token with
var idToken = req.headers["x-access-token"];
auth.verifyIdToken(idToken).then(function(decodedToken) {
var uid = decodedToken.sub;
console.log(decodedToken);
}, function(error){
console.log(error);
});
But I'm getting:
[Error: Firebase Auth ID token has no "kid" claim]
getAuth():
UPDATE
I'have just tested generating and validating the token on the server side and I'm getting the same problem.
var auth = firebase.auth();
var token = auth.createCustomToken(userId, {"premium_account": true});
console.log(token);
auth.verifyIdToken(token).then(function(decodedToken) {
console.log(decodedToken);
}, function(error){
console.log(error);
});
Any suggestions?
UPDATE 2: [SOLUTION]
The problem in my case was that the Tokens generated with AngularFire 2.X.X are not compatible with the Firebase 3.X.X that is running in my server. So after digging into some thoughts that people wrote here and in this google group topic the workaround was to use jsonwebtoken as follows:
var jwt = require('jsonwebtoken');
jwt.verify(idToken, fbKey, function(err, decoded) {
if (!err){ console.log(decoded); }
});
You can find the fbKey accessing the new firebase console and going into Settings -> Project Settings -> Database.
The documentation states that a Firebase ID Token is not the same as a Custom Token, and that verifyIdToken() is not intended for verifying tokens generated with generateCustomToken().
Old style custom tokens still seem to work (signed with a database secret instead of a service account private key). You can generate and verify these yourself using firebase-token-generator.js and/or jsonwebtoken.js.
Copied from Firebase Project > Settings > Database > Secrets
Create custom database authentication tokens using a legacy Firebase
token generator. At least one secret must exist at all times.
Seems like there is no way to use firebase's createCustomToken and verifyIdToken in a couple.
Method createCustomToken uses method sign from jsonwebtoken module which does not put "kid" claim in header section of jwt by default.
And createCustomToken does not put it itself.
I suppose at this time you can use jsonwebtoken module directly to generate token with own key id.
firebase#3.0.2
--jsonwebtoken#5.7.0
The token you pass to your server is not a JWT token, and verifyIdToken need a JWT Token.
To obtain a JWT token in your web application, run firebase.app().auth().currentUser.getToken().
Personnally I removed angularfire, the basic firebase framework made angularfire pretty useless in my opinion. Plus, a compatible version with firebase 3.0 of angularfire is not yet released, probably in the next week according to the firebase team.