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.
Related
I have integrated the docuSign Android SDK in my app and been able to achieve embedded signing. But it asks for the customer to login before signing the document. As its a customer facing app, we dont want them to enter the organisation docusign credentials.
How can we skip the login or authenticate implicitly using the SDK methods or some other way?
Thanks in Advance!!
In Android SDK, we provide the following apis to login or authenticate.
Login with Access Token:
You can invoke the following SDK API:
// accessToken - Access Token which authenticates the user
// refreshToken - If the access token can be refreshed, the refresh token. Optional
// expiresIn - The number of seconds from the time the access token was provisioned to when it will expire
try {
DSAuthenticationDelegate docusignAuthDelegate = DocuSign.getInstance().getAuthenticationDelegate();
docusignAuthDelegate.login(accessToken, refreshToken, expiresIn, context,
new DSAuthenticationListener() {
#Override
public void onSuccess(#NonNull DSUser user) {
// TODO: handle successful authentication here
}
#Override
public void onError(#NonNull DSAuthenticationException exception) {
// TODO: handle authentication failure here
}
}
);
} catch (DocuSignNotInitializedException exception) {
// TODO: handle error. This means the SDK object was not properly initialized
}
You can retrieve access token the following ways:
a. Using JWT Grant authentication by following steps mentioned at https://developers.docusign.com/platform/auth/jwt/jwt-get-token/
b. Using Authorization Code Grant by following the steps mentioned at https://developers.docusign.com/platform/auth/authcode/authcode-get-token/
Using JWT Grant authentication to fetch access token needs to be implemented at your backend and once your server receives access token from DocuSign using this approach, then your server needs to pass that access token and the expiration time to your app and your app can invoke the above mentioned Android SDK login api with access token and expiration time.
Login using OAuth:
UI is displayed where user enters credentials.
Get the OAuth Client Id/Integration key, secret key and redirectUri from your account. (Please refer to https://developers.docusign.com/platform/auth/authcode/authcode-get-token/ on how to retrieve the clientId, secretKey and redirectUri from your account).
While initializing the DocuSign SDk, pass these values as shown in below
DocuSign.init(
context,
clientId,
secretKey,
redirectUri,
DSMode.DEBUG
).setEnvironment(environment)
DSAuthenticationDelegate authenticationDelegate = DocuSign.getInstance().getAuthenticationDelegate();
authenticationDelegate.login(REQUEST_LOGIN, this, new DSAuthenticationListener() {
}
This will open the OAuth login screen. Enter your username and password and you should be able to login.
In your use case, you can use SDK 'Login with Access Token' approach.
As the title says, I'm trying to use the Google Sign-In API with a Spring Boot backend server, as described here.
Just to describe the context, the Spring backend is basically a resource+authentication server, that is currently providing Oauth2 authentication to a second spring boot application containing the frontend website, via Google SSO or simple form login (similar to what's described here).
My original idea was to mimic the #EnableOauth2Sso annotation by simply providing an access token to the android app and attach it to every request as "Bearer ".
Using the user credentials for this was pretty straightforward: I simply make a request to the server at "/oauth/token", using those credentials inserted by the user as authentication and I correctly receive the access token.
Now, I have absolutely no idea on how to build a similar procedure with the Google API in Android. The tutorial page I linked before describes how to get a token ID and how the server should validate it, but after that I don't know what to do.
So far I've managed to add a filter to the security chain that simply checks the token like this:
private Authentication attemptOpenIDAuthentication(#NonNull String tokenString){
String clientId = authServices.getClientId();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, factory)
.setAudience(Arrays.asList(clientId, androidClient))
.build();
try {
GoogleIdToken token = verifier.verify(tokenString);
if (token != null) {
return authServices.loadAuthentication(token.getPayload());
} else {
throw new InvalidTokenException("ID token is null");
}
} catch (GeneralSecurityException | IOException e) {
throw new BadCredentialsException("Could not validate ID token");
}
}
This manages indeed to create an Authentication object, but how can I generate an access token after the authentication filtering?
To recap, so far I've got:
The Android app successfully retrieves the Google token ID and sends it to the server
The server sucessfully intercepts the request and validates the token
I'm basically missing the third point where I return a proper access token to the Android client.
Here you are a simple scheme to better understand the situation:
Is there any other way to validate the token and get an access token from the server, or should I completely change the authentication procedure on Android?
As far as I can tell: Yes, you need an access token from the server. If I understand this correctly, a webapp is already authenticated via Oauth on your backend, so the procedure is similar here: Load the user with the google-ID and generate a token. In my application I used a JWT which is valid for 30 days. If the token expires, the Google authentication in the app is usually still valid, so the token can be renewed using the Google ID. With Oauth you can also send a refresh-token directly.
It is important that the app always checks the Google authentication first and only in a second step that of the backend.
For the Authentication process on the backend u may need to manually implement a dedicated securityConfiguration for this. Have a look at the jhipster project, they implemented a custom jwt-authentication which may give you an idea how it works.
I'm trying to implement custom authentication for Android in my app.
The form I want is a phone number only. Currently I'm doing this:
I have an application using heroku in IntelliJ that generates the custom token.
I deployed that app to Heroku.
The problem I'm facing is that I am running the Java application in Heroku. However, all I have right now is:
String uid = "some-uid";
HashMap<String, Object> additionalClaims = new HashMap<String, Object>();
additionalClaims.put("premiumAccount", true);
FirebaseAuth.getInstance().createCustomToken(uid, additionalClaims)
.addOnSuccessListener(new OnSuccessListener<String>() {
#Override
public void onSuccess(String customToken) {
// Send token back to client
}
});
What I'm confused about:
How do I communicate from the Android client with the server running in Heroku?
How do I get the token which I generated?
Typically, you create custom tokens when you're handling the user authentication by yourself. Then we can envision the following information flow:
Android app sends user credentials (e.g. username and password) to your backend server in Heroku.
The backend server authenticates the user, and creates a custom token (the code you have at the moment).
The custom token is sent back to the Android app as the authentication response.
Now you can use the custom token in Android app to authenticate with Firebase.
Hope this clears things up.
You will need to see up a web framework like Spark to receive requests from your Android app and send responses back to your Android app. On your Android device, you would make an HTTP request to your Heroku instance (which will be at some URL), you will use Spark running in Heroku to receive the request, you will mint a custom token using Firebase Admin, and then you can send the custom token back to your Android device as a Spark response.
I am having trouble integrating LinkedIn authorization from OAuth .io with Firebase on Android.
I am able to authenticate my user through LinkedIn, and OAuth .io is able to save the token into the Firebase database (on the application table not the system table, yet).
But when I pass the received token to Firebase as shown on the code below, firebase replies with an error.
oauth.popup("linkedin2", new OAuthCallback() {
#Override
public void onFinished(OAuthData data) {
String token = data.token;
FirebaseAuth.getInstance().signInWithCustomToken(token);
}
The error I get is:
com.google.firebase.auth.FirebaseAuthInvalidCredentialsException: The
custom token format is incorrect. Please check the documentation.
How can I make this work?
Just a suggestion, why dont you do the normal authentication with either
Facebook TwitterGitHubPersonaEmail/Password
And then after successful signing ask the user to retrieve their data by signing in to their linkedIn account.
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();
// ...
}
});