.net core Web API and Firebase Auth - asp.net

I am developing a web application using .net Core Web API. So far I have used Identity to authenticate and manage users. Is it often the case and suggested to use an auth service like Google Firebase Auth while still having an own server backend?
I am thinking about using Google Firebase Auth so that users can login in different ways (using Facebook, Google, etc.).
However, I want to have a self hosted backend application and database.
Now I am asking myself:
How do I store user data on my server: Should I use the uid (returned from Firebase) as foreign key to save user related data in my database?
How can I make use of Roles (Identity)? How can I add/remove a Role from a particular user?
Should I store additional user data (like email, name, etc.) in my database or should I always retrieve those infos from the token!? Are those infos provided by Firebase Auth at all?
Thank you for bringing light into the darkness!

You have your own user database. You can verify the Firebase ID token when a user signs in and get your internal users Firebase custom token.
docs/auth/users
You store them in you own database and add them to you Firebase custom token.
That depends on how much data you need and if the data can differ from the Firebase base data.

Add Firebase to Your app
<script src="https://www.gstatic.com/firebasejs/4.1.3/firebase.js"></script>
<script>
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(config);
</script>
If you haven't yet connected your app to your Firebase project, do so from the Firebase console.
Enable Email/Password sign-in:
In the Firebase console, open the Auth section.
On the Sign in method tab, enable the Email/password sign-in method and click Save.
Create a password-based account
Create a new account by passing the new user's email address and password to createUserWithEmailAndPassword:
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
for more information please go through
https://firebase.google.com/docs/auth/web/password-auth

Related

Is it possible to initialize the Firebase Admin SDK with an impersonated service account?

I'm trying to build a system where I can access the Firestore database in another Google Cloud project by impersonating a service account that has access to that project's Firestore database using generating short-lived access tokens instead of service account keys for a more secure integration. When I try to use this kind of credential I get the following error:
Must initialize the SDK with a certificate credential or application default credentials to use Cloud Firestore API.
I'm wondering if I'm missing something here because it seems weird to me that it's just impossible to access Firestore with an impersonated account.
Thanks!
Yes, it is possible to initialize the Firebase Admin SDK with an impersonated service account.
The following steps are to be followed:
Using admin SDK and service account initialize Firebase app backend with:
admin.initializeApp({
credential: admin.credential.cert(service_account_json),
})
Obtain authentication token for the user you wish to impersonate:
const userId = "[impersonating user uid string]"
const token = await admin.auth().createCustomToken(userId)
Using frontend Firebase SDK authenticate user with:
const token = "[token string obtained in step 2]"
firebase.auth().signInWithCustomToken(token)
Just had a similar problem during development. I needed to use a service account to authenticate firebase admin to generate a email sign in link with
const link = await auth.generateSignInWithEmailLink(email, actionCodeSettings); I go the error here that Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the identitytoolkit.googleapis.com
My solution is now:
Impersonate the service account, by getting an Impersonated Client:
const auth = new GoogleAuth();
const client = await auth.getClient();
const targetClient = new Impersonated({
sourceClient: client,
targetPrincipal: 'myaccount#myproject.iam.gserviceaccount.com',
lifetime: 3600,
delegates: [],
targetScopes: ['https://www.googleapis.com/auth/cloud-platform'],
});
Extract the Oauth2 credentials
const credentials = await targetClient.getAccessToken();
Feed the credentials to initializeApp()
initializeApp({
credential: {
getAccessToken: async () => {
return {
access_token: credentials.res.data.accessToken,
expires_in: Date.parse(credentials.res.data.expireTime) / 1000,
};
},
},
});
initializeApp(appOptions)
Credential
GoogleOAuthToken
Example with Impersonated Credentials
Some notes:
What I didn't want to do is create a service account key, download it and use that to authenticate (this would have been the easiest way).
The contents of getAccessToken() response is not documented and I've pieced it together from looking at the content and tried out the token I've found in there.

Can we use firebase with flutter just for authentication and custom server for everything else?

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);
}

How to access Twitter OAuth token once page got refresh?

Following Firebase documentation on Twitter Authentication we get to something like this:
<script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-app.js"> </script>
<script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-auth.js"></script>
<script>
// NOTE: pseudo code
// initialise the app
firebase.initializeApp({
apiKey: "API_KEY",
authDomain: "AUTH_DOMAIN",
databaseURL: "DATABASE_URL",
projectId: "PROJECT_ID",
storageBucket: "STORAGE_BUCKET",
messagingSenderId: "MESSAGING_SENDER_ID"
});
// create Twitter provider
provider = new firebase.auth.TwitterAuthProvider();
// auth with popup
firebase.auth().signInWithPopup(provider).then(function(result) {
// in theory we could now access the OAuth token so we can make further requests to the Twitter API.
var token = result.credential.accessToken;
var secret = result.credential.secret;
});
So far all good. We can access the token and secret and make any request to the twitter API.
Also on the documentation there's reference to the firebase.auth().currentUser method which we can call after a page refresh (for example).
In this object we have access to some information previously obtained when we first login, however we can't access the OAuth Token nor the secret.
There's further documentation regarding Auth State persistence where some other methods are mention like firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL) which I think its what I need. However I still can't access the Token nor the secret.
Am I suppose to store it in a cookie or localStorage entry when the user first logs in? Is this even secure? Any help would be appreciated as I don't want to force my users to login to twitter every time they close the site and open it again.
Thanks
Firebase Auth doesn't manage 3rd party OAuth tokens. They only return the OAuth tokens on sign in and discard them afterwards. They don't store these data so you will not be able to get them after sign in unless you store them locally. Firebase Auth is currently only focused on providing an AuthN solution and not AuthZ.

Migrate users to firebase auth, force uid generation before login

We are building an app that will launch soon on which users can authenticate using Firebase (Google and Facebook). Previously we have run a website to preregister users. On this website users can authenticate through Google and Facebook. On the website we haven't been using Firebase authentication.
The problem is that a lot of our code in the app works on the firebase auth uid. If a user that has signed in on the website contacts another user through the app, we connect them using the Firebase uid. This is a problem if the user hasn't logged in on the app after registering on the website. (The uid we keep in the backend changes from FB or Google uid to Firebase uid).
How should we connect the users on the website to the users in firebase? Is there a way we can predict/force the uid to something we can control?
Ideally registrations on the website should also still work after go-live.
You need to migrate your Google/Facebook user to Firebase Auth using the Firebase CLI SDK and then use Firebase to authenticate these users after migration. During migration you can use whatever UID you need for these users: https://firebase.google.com/docs/cli/auth#authimport
You can set up a server where you can create users with the Firebase Admin SDK. By default, a random uid is created, but you have the option to assign a specific uid. Here's the website's example using Node.js:
admin.auth().createUser({
uid: "some-uid",
email: "user#example.com",
phoneNumber: "+11234567890"
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
})
.catch(function(error) {
console.log("Error creating new user:", error);
});
The Admin SDK also offers the functionality for Java and Python if you prefer one of those languages.

Cloud function authentication with limited privileges

I am creating a RESTful API for my firebase database using Cloud functions. All the tutorials and guides I found suggest using firebase-admin to get admin access to the database.
Here is my question:
Is there a way to access the database the same way as the user would have directly? Like getting the auth token from the user and passing it on to the database to make changes the same way the user would. The security rules should prevent me if I try to make changes to a different user.
Possible solution:
Access the database using the built-in REST API of the database and use ?auth=CREDENTIAL to authenticate the user. Is there an alternative using the firebase SDK?
Is there a way to access the database the same way as the user would have directly?
Yes there is, I recommend you check out the sample here. But it requires that your code decodes and verifies the JWT of that user. The easiest way to do this is with the Admin SDK.
The sample uses the JavaScript SDK to get the token from the client:
firebase.auth().currentUser.getToken()
It passes this token to the server, which then verifies it using the Admin SDK:
admin.auth().verifyIdToken(idToken)
You can then create a second instance of the admin SDK and set this UID for your database requests:
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://databaseName.firebaseio.com",
databaseAuthVariableOverride: {
uid: "my-service-worker"
}
});

Resources