Implementing JWT authentication in Android using Account Manager - android

I’m implementing a Android app and that must contain a user login. To do this I create my own authenticator with the purpose of login only once. Then AccountManager can request access tokens, so the application is not handling passwords directly. The AccountManager stores the user account and the token.
I’m using JWT (Json Web Token) to authenticate the user in my REST API.
I wonder whether this flow is correct or there is a better approach to do this in Android.
Here is the flow I am currently using:
The user enter user and passwords in the login screen at first time.
I make a request to server to retrieve a valid token (JWT) that is stored in the Account Manager.
Subsequent requests use the received access token until it is expires (1 hour) to retrieve content from the API.
After the token is expired, it can be refreshed up to two weeks after issue time. From this moment, user credentials are needed to retrieve a new token.
Is this process the correct way to work with the token, and refreshing it? Is the process safe? Are there other options?
Considering this flow is not using a “refresh token” to generate a new one but the access token, what would be the best usage of the Android Account Manager? What other tools should I use? Is it recommended an Oauth2 implementation along JWT in order to implement a “refresh token”?
Cheers!

I can tell, you are on the right road of using JSON Web Tokens and reproducing it.
but the safety you mentioned is all about encrypting the token you retrieved and then saving it in Account Manager (also the same with user credentials) with some encryption method of your choice like AES or RSA and then decrypt if when you wish to use. Also using a server-generated secret key with a secret algorithm would kill the shot for any hacker.
As you understand everyone with a root access can get hands on the saved credentials database and use it.
Using these tricks will lower the need of using Oauth 2.0 which involves a refresh token.
hope it helps

Related

Handling Oath 2.0 Authorization from Backend Job

I am trying to find a solution to the following:
Requirments
There is exists an app that allows users to add integration providers
These integration providers use oath 2.0 authorization to secure their data
The app needs the ability to have a backend job fetch data on-behalf of the user once per day
The data fetched is ingested and merged into a report that is compiled on the app for the user
Problem
User Delegated Access Token from Backend Job - I'm having trouble finding the solution that allows me to have a valid access token that is on behalf of the user without having to generate the access token from the app side
What I have tried
Refresh Token - I have tried the approach of using the refresh token to constantly get a new access token but this solution is fragile in the sense that there might be a situation that a new token is not generated in time or for some reason the user still needs to reauthenticate the connection to the provider
Automated Browser Flows - I have tried automating the user's authentication flow from the backend using saved credentials given in the app. This approach is just sketchy, costly, and would require a lot of work on the user agreement side ensuring that is being done on the backend has been consented by the user which essentially reinvents the wheel on user consent which the identity providers should have already been handling
We can use JWT for this. By doing it with JWT we'll create a token and save to the database and on every request it will decrypt the token and get the required data from the token.
Link- https://jwt.io/

How can I secure the cloud database for my mobile app?

I'm working on a mobile app that has both local database and AWS RDS. Data needs to be passed both ways so that user data can be backed up and updated data can be sent to the app. I set up an API to avoid putting database credentials in the app itself. The API triggers code hosted in the cloud to interact with the RDS.
As I understand, Android APK files can be easily hacked. I would like a solution for how to prevent someone from reverse engineering the app's API calls and getting private user data from the RDS. As it is currently, if someone knows how to format an API call they could access data belonging to any user.
You need an API Authorization mechanism. Normally APIs are protected with Authorization Token which is obtained by a successful login. When the user successfully logs in, you should issue the authorization token, Store in device shared preferences that need to be passed with further API calls. I suggest using JWT, simple and available in all major programming languages. Encode the user's unique identifier in JWT token and design your API such a way that the user can only create, read, update, delete based on the identity encoded in JWT. By this, suppose if user token is compromised, that token can be only used to misuse the user-specific data and not all the data in your database.
Consider the given flow for your reference.

How can I securely store user credentials for my app

I have an Android app that allows users to interact with a third-party service via their API. This API makes use of Basic Authentication, so I need the user's username and password for every API call. Ideally I don't want to store the user's credentials locally as this is very insecure. I don't know much about authentication but this is what I think my ideal solution would be:
The user provides their credentials to this service once for verification
Once verified, I send the user's credentials to a backend service to store them, which gives me an auth token. I store this token locally (is encryption important here?)
Whenever I want to make future calls to this service, I use this auth token to talk to the backend service, which provides me with the user's username/password for Basic Authentication to make API calls
Is this a good solution? If so, are there backend services in place that I can use to facilitate this process? I've looked at Firebase Authentication but I don't know if it fills my needs as I'm trying to store credentials for a third-party service, not specifically for my app. I've heard of Auth0 which may be what I'm looking for but appears to be overkill for a small app like mine.
You can easily use Firebase Auth and get all the functionality you need while keeping your users secure. It provides the features you need:
Firebase supports password authentication and properly stores hashed/salted password credentials according the industry standards. This would be one API to createUserWithEmailAndPassword or signInWithEmailAndPassword.
Firebase provides a mechanism to verify email addresses. It is also one API: user.sendEmailVerification()
On sign in, Firebase Auth returns an ID token (user.getIdToken()) which you can use to identify your users in all authenticated requests. They also provide an Admin SDK to parse and verify that token (auth.verifyIdToken(idToken)). A refresh token is also provided to continuously refresh ID tokens on expiration. This means the sessions are indefinite and the user should not need to sign in again on the device.
The ID token provides additional user data like email_verified which you can use to ensure the user is verified. The ID token is a JWT which can't be compromised without the Firebase Auth backend private key.

User Session Management in android

I want to maintain user session once the user logs into his/her account so that they are logged in even after the application is closed and started again. Searching on Google and SO, people referred SharedPreferences. I understand that I have to store user details in SP(SharedPreferences), but what if the user updates his/her data? Plus, the HttpGet call I send to the link to get user data returns the valid data(JSON) only when the user is logged in. Is SP the only way to do this, or is there other and more efficient way to do this?
P.S. - I am working as a freelance for a startup, and they have API to their PHP website. I have to make an android app for their website. To log in the user to the website, I make a Http POST call to their API and the result I get is a JSON. If the JSON contains "success" value to the "result" key, then the user is logged in. But as soon as I use intent to go to the next activity(where I have to display the user data by making Http Get call to another API, which only works if the user is logged in), the session is lost. Since I work as a freelance, they don't really trust me giving cookies to user sessions. So, I was hoping there might me some other way?
You can always use cookies (with, say, an authentication token?), Android OS manages them for your app automatically - as long as the cookie is correctly set by the server (ex. expiration date) your app should work fine. But this is a little old school.
A more modern way is to use OAuth or integrate an already existing login system (Facebook, Google, etc.) to authenticate users.
Using Shared Preferences is a wrong tool for this job. It's a workaround for doing proper authentication. There are ways that are trustworthy and secure and take care of all kinds of edge cases, and while it takes a little bit of work to set up, it's a much better option, IMO.
You should try to integrate android AccountManger APIs because storing the credentials in shared preferences is not especially desirable from security point,especially if your app is going to run on rooted devices.
From the docs:
public class AccountManager extends Object java.lang.Object ↳
android.accounts.AccountManager Class Overview
This class provides access to a centralized registry of the user's
online accounts. The user enters credentials (username and password)
once per account, granting applications access to online resources
with "one-click" approval.
Different online services have different ways of handling accounts and
authentication, so the account manager uses pluggable authenticator
modules for different account types. Authenticators (which may be
written by third parties) handle the actual details of validating
account credentials and storing account information. For example,
Google, Facebook, and Microsoft Exchange each have their own
authenticator.
Many servers support some notion of an authentication token, which can
be used to authenticate a request to the server without sending the
user's actual password. (Auth tokens are normally created with a
separate request which does include the user's credentials.)
AccountManager can generate auth tokens for applications, so the
application doesn't need to handle passwords directly. Auth tokens are
normally reusable and cached by AccountManager, but must be refreshed
periodically. It's the responsibility of applications to invalidate
auth tokens when they stop working so the AccountManager knows it
needs to regenerate them.
\

Getting a OAuth2 authorization code that can be shared with a server

My Android app needs to send an authorization code to my server so that the server can use that to acquire an access token for the user's Google Drive account. I have been trying to figure out how to acquire the authorization code and I found this in the Google API documentation (Using OAuth 2.0 for Installed Applications):
This sequence starts by redirecting a browser (system browser or
embedded in the application as a web view) to a Google URL with a set
of query parameters that indicate the type of Google API access the
application requires. Like other scenarios, Google handles the user
authentication and consent, but the result of the sequence is an
authorization code. The authorization code is returned in the title
bar of the browser or as a query string parameter (depends on the
parameters sent in the request).
After receiving the authorization code, the application can exchange
the code for an access token and a refresh token. The application
presents its client_id and client_secret (obtained during application
registration) and the authorization code during this exchange. Upon
receipt of the refresh token, the application should store it for
future use. The access token gives your application access to a Google
API.
Now I am not sure how to get this authorization code in my Android app since the Android examples I have seen seem to get the access tokens directly. I am looking at the Android AccountManager class and it has a method getAuthToken but this seems to refer to the access token and not the authorization code.
So how does one acquire the authorization code that can be shared with a server? If it is possible I would greatly appreciate some example code. If this is not possible what are the possible workarounds?
You may want to take a look at the Cross-client Identity document. It should keep you from needing to pass user tokens back and forth.
I believe you can actually take the access token returned by the Android AccountManager, send this to your server, then have your server make a call against the Google Drive API using that same access token - it is a bearer token and not bound to the channel that created it, so please take good care of it and only send over encrypted connections.
Documentation on how to get that access token can be found here:
https://developers.google.com/drive/quickstart-android
While that access token is good for immediate use, it will expire in less than 1 hour, so if you are looking for a solution that enables your backend server to have continued access to the Drive data, without the user being present at your app at the time of request, an alternate approach will be needed.

Categories

Resources