Multiple public Firebase Database Instances in Android - android

I'm working on an assignment. I've to use Database provided by a provider 'hacker-news'. Also i've to use Firebase Authentication. I've setup a new project in my own account. Retrieving data from Hacker-news database works with below line. I'm able to fetch publicly accessible data with firebase child() APIs is
database = FirebaseDatabase.getInstance("https://hacker-news.firebaseio.com/");
But when i implemented Firebase Authentication and once user logs in it is giving error
Provided authentication credentials are invalid. This usually indicates your FirebaseApp instance was not initialized correctly. Make sure your google-services.json file has the correct firebase_url and api_key
I've spent lot of time on internet and found a link to implement multiple databases in single project -
Working with multiple Firebase projects in an Android app by Google
This works only if you are the owner of those Databases. Is there anyway i can access Hacker-news Database using SDK not REST-API?

FirebaseOptions options = new FirebaseOptions.Builder()
.setDatabaseUrl(getResources().getString(R.string.dbURL))
.setApiKey(getResources().getString(R.string.api))
.setApplicationId(getResources().getString(R.string.appID))
.setProjectId(getResources().getString(R.string.projectId))
.setStorageBucket(getResources().getString(R.string.storageBucket)).build();
//set all variable above as your need
boolean hasBeenInitialized=false;
List<FirebaseApp> fireBaseApps = FirebaseApp.getApps(getApplicationContext());
for(FirebaseApp app : fireBaseApps){
if(app.getName().equals("any_name")){
hasBeenInitialized=true;
}
}
if (!hasBeenInitialized) {
smaTeacher = FirebaseApp.initializeApp(this, options, "any_name");
}
database=FirebaseDatabase.getInstance(FirebaseApp.getInstance("any_name"));

Related

Firebase custom auth with Gigya

My goal is to integrate Firebase Realtime Database within my Android app which already has an authentication layer (Gigya) that isn't managed by me.
The DB structure could be:
{
"users":
"gigya_id1": {
// user's objects
},
"gigya_id2": {
// user's objects
},
.....
}
I also want to add a little of security and rules to avoiding that a user can't READ/WRITE other users stuff.
I read about firebase custom auth but as I said, I don't have access to backend (and there is not doc about gigya custom token and firebase integration)
Does anyone have experienced with an integration like this one?
What you want to do can be achieved pretty easily.
You can pull the JWT from Gigya whenever a user authenticates by calling to
gigya.accounts.getJWT()
And pass the JWT in the response from Gigya to the custom auth method in Firebase, following this guidelines: https://firebase.google.com/docs/auth/web/custom-auth

Can two different Firebase project be used in one Android app, specifically crashlytics, messaging and performance extensions

For a couple of reasons we had to use multiple Firebase projects in one app. At the moment we have implemented auth extension to user one Firebase project and via code initialisation and crashlytics, performance and messaging to use another via the config file. We would like to make crashlytics and performance extensions to use the project that the auth extension uses and messaging to use the same one that it uses now.
I went through some initialisation examples but could not find anything related to crashlytics or performance extensions.
This is how I initialise different project for auth extension.
// credentials for auth project on Firebase
final String authAppName = BuildConfig.AUTH_APP_NAME;
final String authAppApplicationId = BuildConfig.AUTH_APPLICATION_ID;
final String authAppApiKey = BuildConfig.AUTH_APPLICATION_KEY;
List<FirebaseApp> listOfActiveApps = FirebaseApp.getApps(context);
if (!listOfActiveApps.isEmpty()) {
for (FirebaseApp app : listOfActiveApps) {
if (authAppApiKey.equals(app.getOptions().getApiKey())) {
return app;
}
}
}
FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId(authAppApplicationId)
.setApiKey(authAppApiKey)
.build();
return FirebaseApp.initializeApp(context, options, authAppName);
Fabric/Firebaser here, great question - this behavior is generally not supported today, due to the way Crashlytics and Performance need to initialize, particularly when mixed with Auth.

"Could not reach Firestore backend", multiple Firebase apps, Android

I'm migrating from Realtime Database to Firestore. Because I can't have both a Realtime Database instance and a Firestore instance in the same project, I have to init the Firestore instance manually, rather than have it pick up the google-services.json file automatically as part of the build. I've done that like this:
FirebaseOptions firebaseOptions = new FirebaseOptions.Builder()
.setProjectId("***")
.setApiKey("***")
.setApplicationId("***")
.setDatabaseUrl("https://***.firebaseio.com")
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(this, firebaseOptions, "dev");
FirebaseFirestore db = FirebaseFirestore.getInstance(firebaseApp);
All the values are taken from the google-services.json file I downloaded for the new project.
Calling FirebaseFirestore.getInstance() is fine, but when I later try to get a document, I see this in logcat:
W/Firestore: (0.6.6-dev) [OnlineStateTracker]: Could not reach Firestore backend.
The Task for a get() call to a Document has an exception message of:
Failed to get document because the client is offline.
The device is online, for sure. The new project in the console does NOT have the SHA certificate fingerprints set, because I can't use the same one as for the original project.
What am I missing?
[Edit]
I know that is a little late for the answer. In my case, I had the same problem because I try to test Datastore and I lose the possibility to use Firestore in my project. When I try to create a new project for Firestore, I have to init the Firestore instance manually and I had the same problem.
In my case, the problem was that one of the parameters of FirebaseOptions was wrong (in my case was project_id because I had put project_number). I had taken all parameters from google_services.json from the new project:
FirebaseOptions.Builder()
.setApplicationId("X:XXXXXXXX:android:YYYYYYY") // FROM client_info -> mobilesdk_app_id.
.setApiKey("AIzaXXXXXXXXXXX") // FROM api_key -> current_key
.setDatabaseUrl("https://XXXXXXX.firebaseio.com") // FROM firebase_url.
.setProjectId("XXXXXXXX") //FROM project_id
.setStorageBucket("XXXXXXX.appspot.com") //FROM storage_bucket
.build();
After that everything start to work fine.

How to integrate firebase authentication with google app engine endpoints

I am writing a backend server for mobile applications.
The backend is running on google app engine and written in Java.
I want users to be able to login with federated identity such as facebook.
I saw that google supports this kind of authentication for mobile apps via firebase authentication. What would be the best way to integrate firebase authentication with my current app engine endpoints?
I already use the cloud platform's datastore and don't wish to work with the firebase database, only use the authentication method.
Thanks.
I'm also looking for an answer to this. My best 5c so far is to
Use FireBase to set up sign in methods etc. from the console
Use FireBase UI (in beta) for web or "Federated identity provider integration" for iOS/Android to set up the authentication flow
Retrive token/authentication details on your web/iOS/Android client and pass it on to your Cloud Endpoints as e.g., HTTP Request Headers
Inject the javax.servlet.http.HttpServletRequest to your endpoint methods (just add an argument and Google with inject the request object automatically)
Create a method that your Endpoint will call for each request (that needs authentication) that will handle the validation of the credentials you have passed on as HTTP Request Headers
Use FireBase Java SDK to call FireBase to validate the credentials (in order to do this, you need to export the json configuration from the Firebase console) and load the SDK with them, e.g., in one of your servlets:
#Override
public void init(ServletConfig config) {
try{
InputStream in = config.getServletContext().getResourceAsStream("/WEB-INF/firebase-privatekey.json");
FirebaseOptions options = new FirebaseOptions.Builder()
.setServiceAccount(in)
.setDatabaseUrl("YOUR_DATABASE_URL")
.build();
FirebaseApp.initializeApp(options);
log.info("Authentication enabled");
}
catch(Throwable t) {
t.printStackTrace();
log.warning("AUTHENTICATION DISABLED. Only public resources will be available");
}
}
You should be able to use Google Cloud Endpoints as an authentication proxy in front of your app. Endpoints supports validating Firebase Authentication tokens by configuring your OpenAPI template:
# Configure Firebase as an AuthN provider
securityDefinitions:
firebase:
authorizationUrl: ""
flow: "implicit"
type: "oauth2"
# Replace YOUR-PROJECT-ID with your project ID in the issuer and audiences fields
x-google-issuer: "https://securetoken.google.com/YOUR-PROJECT-ID"
x-google-audiences: "YOUR-PROJECT-ID"
x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken#system.gserviceaccount.com"
# Add Firebase as an authN provider to specific endpoints...
security:
- firebase: []
Alternatively, you can use the Firebase Admin SDK to write authentication middleware that validates your tokens:
FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
// ...
}
});

Google Cloud Datastore / Mobile Backend Starter - Permissions failure on update/updateAll calls

Using the Mobile Backend Starter (MBS) Android classes (those distributed as a sample project when creating a new project in Google Dev Console and demoed at Google I/O 2013) I'm able to insert new entities to the cloud datastore via calls to CloudBackendMessaging.insertAll or .updateAll. The latter will create entities if none exist so seems functionally identical to insert for new records.
The insertion/creation works fine. However when I attempt to update existing entries in the datastore, I received permissions errors e.g. (from the backend log)
Method: mobilebackend.endpointV1.updateAll
Error Code: 401
Reason: required
Message: Insuffient permission for updating a CloudEntity: XXXXXX by: USER: YYYYYYY
which results in a matching access error in the logcat client side.
In all cases I am using Secured access authenticating with a valid Google account (my own).
The entities being inserted are thus showing as "owned" by my user ID with "updated by" and "created by" showing my Google account's email address.
However when the update of the existing record is made, using exactly the same CloudBackendMessenger object and thus same credentials etc. the backend is telling me I can't update due to permissions issues. But surely if I just made the entity with the same credentials this can't be correct? Looking at the documentation it appears that I should be able to edit entities owned by the same user ID in all cases (regardless of the KindName and whether it is prepended [public], [private] or nothing).
Can anyone who has received permissions errors on UPDATES via Mobile Backend Starter for Datascore please shed any light? I have been banging my head over this for most of today.
I've faced the similar error "Insuffient permission for updating a CloudEntity" when using cloudBackendAsync.update(cloudEntity). I resolved it by making sure the cloudEntity has it's createdAt field set. createdAt is autogenerated and I think I am not supposed to touch it. But it worked for me. In my case I am first obtaining list of cloud entities. This is when I get createdAt field of cloud entities. Then when I am updating I setting the createdAt field from previously obtained entities.
Edit: Had to do similar thing for owner field also.
Similar to one of the comments above, I successfully got around this by getting the original CloudEntity before doing the insert/update/delete function.
CloudQuery cq = new CloudQuery("datastoretype");
cq.setLimit(1);
cq.setFilter(Filter.eq("_id",id));
cloudEntity.setId(id);
mProcessingFragment.getCloudBackend().get(cloudEntity, handler);
Thereafter it was trivial to do the following:
mProcessingFragment.getCloudBackend().update(cloudEntity, handler);
The docs definitely ought to be more clear on this, whether it is a strict requirement or bug.
The answers posted so far work around the problem if you don't mind all users being able to access the entity you are trying to update. However, a better solution that retains the access permissions is detailed by google here - https://cloud.google.com/cloud/samples/mbs/authentication
If you want to pass the user’s Google Account info to the backend on
each call, use the CloudBackend#setCredential() method (also available
on the subclasses, CloudBackendAsync and CloudBackendMessaging) to set
a GoogleAccountCredential object before calling any Mobile Backend
methods.
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(this, "<Web Client ID>");
credential.setSelectedAccountName("<Google Account Name>");
cloudBackend.setCredential(credential);
Setting credientials enables the client to operate when the backend is
in “Secured by Client ID” mode and also sets createdBy/updatedBy/owner
properties of CloudEntity automatically.

Categories

Resources