I'm suppose to develop a new option for our Android app that allows new users to sign in with their Google account. We need to retrieve basic user info (First name, Last name, Date of birth, Email, Country etc.) and store them on server. It should happen only the first time user logs in to the app so the next time all the button is doing is simple authentication to access the member's area.
Currently, our app prompt for permission using oauth2 and AccountManager and can retrieve the user info through oauth2 api. I would like to do the same thing on our server instead.
So to sum it up here is the flow I'm thinking about:
User chooses to sign in with Google
If he hasn't authorized the app yet, request permission to access his info; retrieve and store them on the server and log in. If he has already authorize the app, simply log in.
We still need a local copy of user info on his android device though so he can view his own profile.
Note: The reason I'm thinking of doing the data import process on our server is to speed up the app and save some bandwidth. but I also feel that user might want to modify his data before they get saved to the server.
I'm really confused and the oauth2 documentation doesn't help much.
I don´t understand the problem. Sorry.
Just retrieve information about the customer from the OAuth api, send the information through HTTP/HTTPS post request to the server, save it there. Then save the same information in the SQLite database in phone and after first time when the app launches just check the user table in SQLite for if the customer exists.
Here is an awesome example: http://www.androidhive.info/2012/01/android-login-and-registration-with-php-mysql-and-sqlite/
In order to do this, you need to follow the documentation for Cross-Platform single sign-on and Cross-client Auth from Google. In essence, your flow should be:
Check to see if the user is authenticated (probably best as a POST to your remote system), if so, continue to your main activity. If not, show the sign on button.
Once the user clicks sign-on, connect the GoogleApiClient, retrieve the current person, save their information on the device (if needed).
Request an auth token for the user via GoogleAuthUtil.getToken.
Send the token to your web server (must be https). On your web server, retrieve the user's information from the token, and save it to the database.
Also, I suggest you use a persistent cookie store for your requests (I prefer loop4j's Android Async-HttpClient). This will allow you to save the session easily, so you do not have to authenticate too often.
Related
I'd like to a make a mobile app that makes requests on behalf of a user. I understand the following OAuth flow:
Open user in web view to give my app access to make requests on their behalf
When they hit grant access, my server side app will receive a call with an authorization code
My server side app then needs to exchange the authorization code for an access token
My confusion starts in Step 2. Uber makes a request to my endpoint with the authorization code, but I have no way of knowing what user that authorization belongs to. I can exchange it for an access token and store it in a DB for 30 days, but I have no way of getting it back to the user to use to make requests.
One thought was I could have the user sign in to my app with an email address which I could then use as a key to get the appropriate access token from my server app, but I have no way of associating the access token with an email address in my DB table in the first place.
I'm wondering what the best practices are here. How is my mobile app supposed to know what access token to use for a given user?
(I reached out to Uber API support directly, but they asked me to open a StackOverflow question instead)
Obviously this is kind of a broad question and is highly dependent on what type of app you're building, what you want the user-flow to look like, etc etc but I'll do my best to point you in the right direction.
First, the Uber API has the /v1/me endpoint which will return the users first name, last name, and email address, among other things. So one possible flow is that a User opens your app, they then go through the whole OAuth flow, and once you exchange the authorization code for an access token you immediately use it (from the server) to make a call out to the /v1/me endpoint and then use either the users email address or UUID as a key in your database. If you used email address, you could just allow users to login to your app using this same email address and allow the account creation process to just be the OAuth flow.
I'm not a mobile developer, but my understanding of embedded web views is that they can use cookies just like any other browser. In that case, another thing you could use is sessions / cookies. Assuming you have some kind of identifier for your existing users, you could add that as a cookie for your web server and then when your user gets redirected to your web server with the authorization code, the attached cookie will tell you which user to associate the access token.
Finally, the Uber developer platform includes a state parameter in the authorization phase of the OAuth flow as seen here https://developer.uber.com/docs/authentication You could do something similar to what I describe in the previous paragraph, except instead of using cookies you could store the user identifier in the state parameter and it'll be sent back to you when the user re-directs. You can use that piece of information to tie the access token back to a specific user in your DB.
I hope that helps! Don't hesitate to reach out if you're still confused.
Cheers!
Background:
I am building an Android app which would required the user to sign-in/register to the service if they wish to contribute.
The service will need some basic info of the user (name, gender etc) on the backend in order to register them.
The app will be providing Google Sign-in as well.
My understanding:
Sending the Id-token to the backend could only give me the email of the user (check the JSON the tokeninfo endpoint returns). In order to retreive additional user info on the backend irrespective of whether the user is signed-in or not I will need to get Offline Access permission (more intimidating) from the user, get the access- and refresh-token, and then get the info.
Another option would be to retreive these info on the app and then send them to the backend along with the Id-token for verification and registration.
Question(s):
Can I pull additional info on the user while the user is still online (using the app) through the Id-token, on serverside/backend? Or should I request additional permission for offline access in order get them? Or, as mentioned in the previous section, pull the required info on app-side and send it over to the backend along with the Id-token?
If you just want the information once then in my opinion it would be better to get the additional information in the app itself rather than asking for additional (with potential denial from user) permission to be used on server.
This will also make sure you have all the needed information while the user is being signed in.
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.
\
We have a working website and now developing android application. Some API calls are public however some api calls requires valid user. One server side it is being maintained through sessions and cookies. How can I communicate with server securely from app. I want that user login once until user press logout or uninstall the app. I don't want to store user username and password in app because it can be easily access by anyone if device is rooted and also I don't have password if user is using facebook login method. What should I do to in app and on server side to make it secure and easy. I think apps like facebook etc use those type of approaches in their apps which I am searching.
I have done research on this and found only that I should use static HttpClient.
I am using volley library for network calls because it suites me.
You use a token. When the user logs in (over an HTTPS webservice), he sends up his username and password. The server stores that in a database and returns a token, just like a cookie would. All future requests from the app to the webservice should be done over HTTPS and should have that token as one of the parameters. The server can then lookup who it assigned that token to in its database, and send the user the appropriate data. If the token isn't there or isn't in the db, you return an error. When the user logs out, you delete the token from the DB.
The token number space needs to be big enough that a random token can't be guessed. Using a second piece of data on each request (such as user name, or something identifying the phone such as ANDROID_ID) would help prevent guessing attacks. And of course if you get repeated requests from someone with bad tokens you should treat that as an attack, just like you would with bad cookies.
I've noticed a lot of apps, even ones that handle sensitive information like finance apps, have this security model: the user first logs in with username/password and from then on just has to enter a PIN to access the app. I was wondering how this is usually implemented. Is it just done by storing hashed credentials into a local database and tying them to a PIN?
Username/password login should be the default for authentication and authorization on a remote server. You can set up your app to log in once, get an auth token from the server, and then use this auth token to log in for subsequent visits.
As an alternative, you can ask the user to log in every time.
You should use a PIN to restrict access to the entire app, including any local data. Having said that, PINs aren't particularly secure. If you want an additional level of security, consider using an OTP.