Xamarin Firebase Auth with claims - xamarin.forms

I have a Xamarin Forms project that we are using Firebase Authentication, Storage and Realtime Database. We are storing credentials for the users (for internal api access) in custom claims. Currently, we are using FirebaseAuthentication.net but it doesn't return any claims beyond DisplayName, email, phone, etc.
How do others retrieve custom claims on Xamarin Forms apps (iOS and Android).

You could use Firebase.Xamarin instead. This package is easy to get the DisplayName, email, etc.
var authProvider = new Firebase.Xamarin.Auth.FirebaseAuthProvider(new FirebaseConfig(""));
var auth = await authProvider.SignInWithOAuthAsync(authType, accessToken);
var uName = auth.User.DisplayName;

Thank you! I needed to get the custom claims and with this library 6 years old, not sure it will get it done. I like that it has database in it too - but not sure its worth the effort. I see 40 open bugs and they are all old (2016-2018 with only two in 2019. What I did find was Plugin.FirebaseAuth which does allow me to query for the custom claims configured for the user. But - it looks like it is breaking the database access I already had.

Related

Firebase create user with customClaim

I'm using the Firebase SDK on a React Native app. I'm authenticating users with onAuthStateChanged - works great.
If it doesn't return a user, they can sign up using their phone number.
For that I use the following on submitting the phone activation code:
...
const credential = firebase.auth.PhoneAuthProvider.credential(
verificationId,
verificationCode
);
await firebase.auth().signInWithCredential(credential).then((response) => {// creating a record on firestore. onAuthStateChanged will be re-triggered and store the user and token in state});
...
I would also like to set custom claims for the user. How do I do that? I cannot use admin SDK since this is the frontend and I also don't want to. I could fire a call to my graphQL to do it, but there is probably a way to add a custom claim in the flow above. How?
There is no supported way to modify custom claims from within a client app. Since custom claims are normally used to give special secure authorizations, it obviously be a security hole to allow user to assign claims to themselves. That's why it's recommended to use the Admin SDK on a secure backend you control.
Custom claims can only be set from a trusted environment. Otherwise anyone could make any claim they want about themselves, which defeats their purpose of securely adding information to a user profile.

Automatic merge when existing account with email&password provider on Firebase

I've been using invertase#react-native-apple-authentication to implement Sign in with Apple combined with firebase authentication.
When I perform this code snippet and choosing "Share my Email" and I already have an existing “email & password-provider” on Firebase with the same email as the one I have on my Apple ID, the providers automatically merge.
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: AppleAuthRequestOperation.LOGIN,
requestedScopes: [AppleAuthRequestScope.EMAIL, AppleAuthRequestScope.FULL_NAME],
})
const { user, email, nonce, identityToken } = appleAuthRequestResponse
const appleCredential = firebase.auth.AppleAuthProvider.credential(identityToken, nonce)
const userCredential = await firebase.auth().signInWithCredential(appleCredential)
If I instead were to use for example Facebook sign in through react-native-fbsdk to sign in with these lines:
const credential = firebase.auth.FacebookAuthProvider.credential(accessToken)
firebase.auth().signInWithCredential(credential)
the auth module correctly throws an error ‘auth/account-exists-with-different-credentials’ since it detects that an account already occupies the email-address on firebase.
The issue is that I cannot stop the merge from happening during the sign in flow, unless I manually prevent it by looking up the authenticated Apple email's firebase login providers in-between the request and the sign-in.
I’d wish to be able to handle an error such as auth/account-exists-with-different-credentials even when signing in with Apple, but unfortunately nothing gets thrown.
Is this behaviour intended?
react-native-firebase version 5.6.0
Firebase/Auth version 6.15.0
Kind Regards, Jonathan
This is the expected behavior since Firebase consider some providers for instance Facebook as not trusted provider.
Is it possible to check if an email is confirmed on Facebook?
In case of trusted providers for instance Apple / Google the merge can happen automaticly.
Note: if you first sign in via non trusted provider later you sign in via trusted provider, then the non trusted provider will be unlinked / overwritten for security reasons. After all if you want to login via non trusted provider (for instance your unlinked provider) then 'auth/account-exists-with-different-credential' will be thrown since the email is already registered with another provider in this case you have to ask user to login with a known provider then manualy link the two auth providers.

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

Check if user has my Facebook app installed

My website uses a Facebook application which sends notifications to its users.
On one of my pages the user can subscribe or unsubscribe (depending on whether or not he is subscribed).
Therefore I want to check if the user is using my app. How can I do that? I guess I could do the following to see if the app can access the data:
FacebookClient c = new FacebookClient(accessTokenClaim.Value);
c.AppId = MYAPPID;
c.AppSecret = MYAPPSECRET;
dynamic access = c.Get("/me/permissions");
if(access != null)
{
//has access
}
The one thing I don't like about this, however, is the fact that I have to use an access token to see if the user has the app installed.
I would prefer not to use access tokens since they tend to expire.
In my database I store the Facebook userIds of all my website users.
Therefore it would be ideal if I could do something like the following:
/get?appinstalled&userid=USERID
What would be the best way to go about this?
To get the current user ID - to compare it with your DB - you will have to access FB graph API using an access token. So I think there is no way to find any info about the user without using FB access tokens.
Edit: And do not worry about the expiration of the token, FB SDK will handle that for you. i.e. it will refresh automatically by the SDK. Here:
Facebook's official SDKs manage the lifetime of tokens for you. When
using iOS, Android or our JavaScript SDK, the SDK will handle making
sure that tokens are refreshed before they expire.
And
Access tokens on the web often have a lifetime of about two hours, but
will automatically be refreshed when required. If you want to use
access tokens for longer-lived web apps, especially server side, you
need to generate a long-lived token. A long-lived token generally
lasts about 60 days.

Does Firebase support validating a pre-existing facebook access token?

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.

Resources