15
votes

I'm currently developing an app using Firebase Realtime database, however I've opted to omit using the SDK to retrieve data from the db. The reason being I don't want my code to be so closely tied with FireBase as once the app is built the api itself will be moving to a custom rest based api.

I've implemented the api calls using REST with Firebase as per the docs without issue - POST, GET, DELETE etc..

The issue I have is if I enable any kind of authentication on the database, according to the docs I need to send "access_token" with the request however I don't know where to retrieve this from. firebaseUser.getToken(true) returns what looks to be a JWT token that isn't recognised if I send it as "access_token". I get 401 Unauthorized

I also followed the instructions to setup a service account which seems to generate a token that works but then it doesn't uniquely identify the user.

So my question is can anyone point me in the direction of how to get the required access token that identifies which user is accessing that api? The login options my Firebase project supports are Google, Facebook & Twitter.

2

2 Answers

7
votes

If you are looking for the different tokens or IDs from each one of the different authentication modes, you should implement differences APIs for each one of them:

REST API

To retrieve an access token you need to use a service account. Please see the guide for using Google Service Accounts. You can create a service account credential in your Firebase project from the Service Accounts section of the Firebase console.

As an example, one way to generate an appropriate oauth2 token is with the Java google-api-client.

GoogleCredential googleCred = GoogleCredential.fromStream(new FileInputStream("service_account.json"));
GoogleCredential scoped = googleCred.createScoped(
    Arrays.asList(
      "https://www.googleapis.com/auth/firebase.database",
      "https://www.googleapis.com/auth/userinfo.email"
    )
);
scoped.refreshToken();
String token = scoped.getAccessToken();

A successful request will be indicated by a 200 OK HTTP status code. The response contains the data being retrieved:

{ "first": "Jack", "last": "Sparrow" }

The Database REST API accepts access_token=<TOKEN> on the query string or header Authorization: Bearer <TOKEN> to authenticate a request with a service account.

The following example demonstrates how you might use this with a database containing user names. You would replace [PROJECT_ID] with the identifier of your Firebase project.

Facebook

You should add the Facebook SDK to your application and implement a LoginButton and LoginManager items asking for some information as public_profile an email. It's pretty annoying to work with Facebook SDK. An Example code about how to add it is this:

// Initialize Facebook Login button
mCallbackManager = CallbackManager.Factory.create();
LoginButton loginButton = (LoginButton) findViewById(R.id.button_facebook_login);
loginButton.setReadPermissions("email", "public_profile");
loginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
    @Override
    public void onSuccess(LoginResult loginResult) {
        Log.d(TAG, "facebook:onSuccess:" + loginResult);
        handleFacebookAccessToken(loginResult.getAccessToken());
    }

    @Override
    public void onCancel() {
        Log.d(TAG, "facebook:onCancel");
        // ...
    }

    @Override
    public void onError(FacebookException error) {
        Log.d(TAG, "facebook:onError", error);
        // ...
    }
});

Also, inside the developers console from Facebook you should create an account, configure a new project with your app package name and add the SHA keys for debug and release versions of your app. After do all this things, you will successfully retrieve a token from the LoginResult object using the method getAccessToken()

You can read more about this in the official documentation.

Google

Google is easier because it is already connected to Firebase, you should add to your Gradle google play services and add a google services JSON file already configured to your application. You can get it from your Firebase console.

After this, you will need to configure a GoogleSignInOptions item using the id from your JSON file:

// Configure Google Sign In
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();

After this you will just need to make a intent to the GoogleSignInApi in your app and wait for the onActivityResult callback:

private void signIn() {
        Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                // Google Sign In was successful, authenticate with Firebase
                GoogleSignInAccount account = result.getSignInAccount();
                firebaseAuthWithGoogle(account);
            } else {
                // Google Sign In failed, update UI appropriately
                // ...
            }
        }
    }

After this you will be able to retrieve the token from the GoogleSignInAccount item. Remember to configure different SHA keys for debug or release versions of your app or Google Sign in will stop working in release version.

You can read more about this in the official Firebase documentation

Twitter

About Twitter, I didn't work with Twitter, so I can't really help you at the moment, but I suggest you to check the Twitter developer documentation and the firebase Twitter implementation post.

I will try to edit this when I will make some pocs at home checking how it works.

About Firebase tokens

Another good point to have knowledge about is the Firebase id tokens, which are unique per user and connection in your app, allowing you to check if the same account is trying to log from different devices at the same time, or send FCM Cloud Messages to use online notification in your app.

To retrieve it, you should use the FirebaseInstanceId object using the API and the method FirebaseInstanceId.getInstance(). This will retrieve you a FirebaseInstance unique ID for your user when he/she login in your app.

You can retrieve his token with the idInstance.getToken() and store it whenever you want in your application to check it and manage it in the way that you want.

The Firebase documentation about this is not pretty clear, so I recommend you to use the next link, it helped me a lot to implement it in my app.

0
votes

You can add a table in your server for USER. In that table, add fields like firebase_token, google_token, fb_token, etc. As you register in all those services one by one, update the fields in the table for user. In this way you can maintain the users_info as well as all the required tokens.