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();
// ...
}
});
Related
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
I'm building an Android App that searches for nearby locations. I use Firebase login system (Login with email and password, and login with Google, Facebook, etc), therefore I would also like to build an API with Firebase. (also because I need the app to be more complicated) I have built a serverless API with Firebase Cloud Functions and I can make GET/PUT requests with Postman. However, I would like to secure these endpoints, similar to how JWT secure a RESTAPI, so that only users who logged in the App can make requests. How do I achieve this? I have looked at "authorized-https-endpoint" but it seems like it only allow Google-Sign-In.
Or is there a way that I can still use Node and Mongodb RestAPI, and secure it using the accounts logged into Firebase?
Here is a piece of the backend code
app.get('/api/read/:item_id', (req, res) => {
(async () => {
try {
const document = db.collection('items').doc(req.params.item_id);
let item = await document.get();
let response = item.data();
return res.status(200).send(response);
} catch (error) {
console.log(error);
return res.status(500).send(error);
}
})();
});
exports.app = functions.https.onRequest(app);
Thank you guys so much in advance.
Use Firebase Callable Functions. They fulfill your requirement.
Refer: https://firebase.google.com/docs/functions/callable
In the case where there are issues with the function calls, please refer to this: firebase.google.com/docs/functions/callable-reference.
As mentioned here this is to be used only if the SDKs don't work for you
The authorized-https-endpoint example supports all forms of auth on the client, as long as it's going through the Firebase Auth SDK. In all cases, the client can send an auth token to the function, and the function code can use the Firebase Admin SDK to verify the token. It doesn't matter how the user authenticated - any Firebase user account will work.
You can also use a callable function, which will automatically perform the validation for you in the exact same way. Your code must then check to see if a user was authenticated using the calling context before continuing.
I am integrating Firebase with my existing Authentication in Android app. As per Firebase documentation, below steps needs to be followed to achieve authentication
Generating a Secure Token on a Secure Server
Authenticating Clients
I am confused in generating a secure token, Do I need to generate it on a secure server? What does it meant? I am thinking of generating the token in the android client itself.
Let me explain my existing Authentication mechanism, After getting credentials as input it will check against MongoDB which is connected with MongoLab API through Retrofit
After this, I am thinking of integrating with Firebase in the below way
From Login User UID which I get after successful login and in the android client itself I will generate a Secure Token (JWT).
With the generated JWT, I will again authenticate a client (Second time with firebase, as Initially with my existing authentication mechanism)
Generating Secure Token (JWT)
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("uid", "uniqueId1");
payload.put("some", "arbitrary");
payload.put("data", "here");
TokenGenerator tokenGenerator = new TokenGenerator("<YOUR_FIREBASE_SECRET>");
String token = tokenGenerator.createToken(payload);
Authenticating Clients
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
ref.authWithCustomToken(token, new Firebase.AuthResultHandler() {
#Override
public void onAuthenticationError(FirebaseError error) {
System.err.println("Login Failed! " + error.getMessage());
}
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("Login Succeeded!");
}
});
Here it looks like a round trip, like Authenticating a User 2 times, with my existing authentication and again with Firebase Custom Authentication. Is there any better way to achieve the above process?
The custom token has to be generated on a backend server. Generating it on the client side will expose your project credentials compromising your entire users. Any attacker who can install your app will be able to figure out your service account credentials and have full access to your users.
I'm using the Google Speech API in an Android app. The README states:
In this sample, we load the credential from a JSON file stored in a raw resource folder of this client app. You should never do this in your app. Instead, store the file in your server and obtain an access token from there.
Are there any samples regarding how to properly obtain an access token for a production app?
From what I've gathered, it seems that I can use Application Default Credentials provided via Compute Engine or GAE, but I have no idea how to actually respond with an access token to my app.
I'm the author of the sample.
Here's the part that should be on the server side. Basically, you have to store the JSON file securely on your server side, and fetch a new access token when you get a request from your mobile app. Mobile app should always talk with your server to get an access token. This way, you don't need to put your service account key in the APK.
// In response to a request from a mobile client
// Open the JSON file stored on the server side.
final InputStream stream = ...;
try {
// Initialize the credentials
final GoogleCredentials credentials =
GoogleCredentials.fromStream(stream)
.createScoped(SCOPE);
// Fetch a new access token.
final AccessToken token = credentials.refreshAccessToken();
// Return the token to the mobile app.
} catch (IOException e) {
// Maybe report this as an HTTP error.
}
If you don't use Java on your server side, you can find a client library for the language you use at Google Cloud Client Libraries.
Refer to Google Cloud Platform Auth Guide for basics about how to send requests from your backend to the API.
For Android, you might instead want to use the Android sample for Google Cloud Speech as the Cloud client library does not currently focus on Android support.
The online reference for Google APIs for Android, shows a public method summary for the Games class which includes:
static PendingResult<Games.GetTokenResult> getGamesAuthToken(GoogleApiClient apiClient)
But the latest release available (8.4.0) does not include this method. I use this to get the APIs:
dependencies {
compile 'com.google.android.gms:play-services:8.4.0'
}
Where is Games.getGamesAuthToken?
This is actually a documentation problem. getGamesAuthToken() has been removed because it was not as secure as it needs to be.
For reference, you can read http://android-developers.blogspot.com/2016/01/play-games-permissions-are-changing-in.html
The best way to handle this is to:
After the player is authenticated on the device:
Get an auth code to send to your backend server:
GetServerAuthCodeResult result =
Games.getGamesServerAuthCode(gac, clientId).await();
if (result.isSuccess()) {
String authCode = result.getCode();
// Send code to server.
}
On the server, exchange the auth code received for a token by
making an RPC to https://www.googleapis.com/oauth2/v4/token to exchange the auth code for an access token.
You’ll have to provide the server client ID, server client secret (listed in the Developer Console when you created the server client ID), and the auth code.
See more details here: https://developers.google.com/identity/protocols/OAuth2WebServer?utm_campaign=play games_discussion_permissions_012316&utm_source=anddev&utm_medium=blog#handlingresponse.
Once you have the access token, the player's ID is retrieved using:
www.googleapis.com/games/v1/applications/<app_id>/verify/ using the access token.
Pass the auth token in a header as follows:
“Authorization: OAuth ”
The response value will contain the player ID for the user. This is the correct player ID to use for this user.
This access token can be used to make additional server-to-server calls as needed.