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.
\
Related
I would like to discuss a common scenario: An app wants to authorize users using multiple OAUTH providers, such as Facebook, Google+ or Twitter.
Essentially this question has been asked two years ago here Mobile API Authentication Using Existing Web App with Multiple OAuth Providers and stays unanswered, so I will elaborate a bit further. (I will use Facebook as an example for the OAUTH2 provider, so this does not become too generic.)
Essentially, user registration works like this: OAUTH/OAUTH2 providers typically provide a workflow where a (mostly short-lived) token is obtained from a provider either via the AccountManager on the mobile device or a login dialog such as the "Login with Facebook" button. The token is then shipped to App Engine by calling a REST endpoint (either in the body or as an additional header, never in the URL).
The provider's AppId and AppSecret (here: Facebook) are store on App Engine and App Engine adds these to the token, then ships it back to Facebook in exchange for a (long-lived) token.
At this point both, client app and App Engine app have certainty that the user has been previously authenticated by Facebook. Also, if Endpoints Authentication is used to authenticate the call, App Engine probably has the Google credentials of the user and/or the ClientId of the app, and Google guarantees that the request has been made from the correct client app.
At this point, we can try to find the user in our datastore and let registration fail (or silently sign in the user) if it already exists, or otherwise create a record.
Until here I am pretty sure I'm on the right track. Now comes the problem:
Let's look at the datastore for this. Let's assume we have two entities:
User entity, where each user in our own system is registered under a unique user id.
Account entity, where each account is registered and where a userId field points to the User entity.
In relational database terms, we would say we have a 1:n relationship between User and Account.
For each User in our system, we keep a User record. In above example, we may have two accounts: Facebook and Google, which both point to the user and where the unique Facebook or Google id/email is used as account identifier.
Technically it would now be possible that the app uses the Facebook or Google account on subsequent requests. But we would have to store and look up the 3rd-party token on each request because we cannot decrypt it ourselves. We could ask the provider to do this, but that wouldn't make much sense either. Plus we would have to translate the provider's Account id to our own User id on each request.
To solve this problem I would most probably either create our own token or set up our own OAUTH provider which creates a token signed by our own system, and where the unique User id is used as identifier, and only use that token during subsequent requests.
Is this a good approach? Is anybody using a different better workflow? Does anybody see security flaws with this design?
Essentially it works around Google's endpoints system, but Google can only authenticate against their own systems, so if we want to offer sign-in using further providers, we will need to work around this, except if anybody knows a workflow where we can keep both, but then we have the problem that we can/should only add a single token in the "Authorization" header and REST principles discourage us to use custom headers to ship more tokens.
When your app authenticates a user, store an object in a session which contains an oauth provider that has been used to access the app and, optionally, a token to be used for subsequent requests.
Now you can check for this object in every call to the server. If the object is not present - a user is not authenticated, redirect to the login page. If an object is present, take a token and use it.
I use a similar approach for multiple authentication options, not only oauth. Except I don't need to store a token after a user is authenticated - I have no use for it within the app.
Let's say I have this application developed for Android which needs to use a Facebook (or Twitter or Google or all of them) based authentication so it can access this private API I've developed with nodejs' Express for example (could be any other platform too). I've read this answer here that gave me a hint on how to associate my authentication model with my user model (and another one here that made me realize those two parts are different), Facebook authenticates and I use some information they provide to create an "identity" for this user, but what exactly is this information that will create a link between the user and the identity? no abstract terms please, do I need to use and send either the access token or the Facebook user id? or would I just send the access token and let the server get the user id?
Regarding new requests after this user has been authenticated, I've read about API keys of some sort, which are basically some random strings that I should add to my identities (or users? this part confuses me) entities, and they should be securely stored in the mobile device as a mechanism to authenticate further requests, but how do I securely get this random string to the device in the first place? am I misunderstanding the way API keys work? are Facebook authentication and API keys mutually exclusive? if so, what would I use for further requests just using a provider for my authentication? it seems illogical to pass the access code in every request, even more so passing the user id.
The focus of this question is for me model a solid strategy for managing this authentication-user-identity behavior, would love any insights on how has this been done before since the material I've found in SO and the web has been very lacking, often referring just to server side implementations or just authentication answers, not addressing the issue of further requests.
The Facebook/User ID is there to identify the (returning) User. Keep in mind that you only get an "App Scoped ID", not the "real" ID - it will be unique in the App, but different in another one. See changelog: https://developers.facebook.com/docs/apps/changelog
Access Tokens are there to make calls to the Graph API. There are 3 different Tokens (App Token, User Token, Page Token), you can read more about them in those articles:
https://developers.facebook.com/docs/facebook-login/access-tokens/
http://www.devils-heaven.com/facebook-access-tokens/
You can store Access Tokens for later, but in most cases you don´t need to store them - only if you need to access the API while the User is not using your App.
In general, App Tokens can be used to request public stuff and to change App settings. User Tokens can be used to request (or post) User stuff and Page Tokens can be used to request insights of a Facebook Page and other things.
If you want to deal with Access Tokens on your own, make sure to activate appsecret_proof in the settings. I suggest reading this article about securing API calls: https://developers.facebook.com/docs/graph-api/securing-requests
I've read many, if not all, answers to previously asked questions about the same topic, but questions themselves are not exactly about my case.
I have an OAuth 2.0 server running. It has an endpoint that provides access tokens to users. Programs and websites requesting the access token may or may not be owned by me, in other words, I may add a tool for website users and locate it on the same or neighboring website and my users may create an app and with their API key request access to user's data. Now I am developing the app that will operate user's data.
I realize that storing the API secret on the device is not a good solution. I have read about creating an end-point to which I make request directly from the app and then the endpoint makes API requests, but the endpoint will have to exist on the same host and probably server as OAuth server.
Is there a way to authorize mobile application to access user data when I am in controll of the application and the OAuth server? Should I create a separate end-point? Should I pass it device ID and/or any other information?
P.S. I know that plain old authorization would work here, but then what if some user wants to create his own mobile extension (not allowed currently for security reasons)? Also, current system has a button that is recognized by many people and they know what exactly will happen after clicking it. With the app, it may be an issue when the user sees a login dialog instead of the "Login with *" button. I really hope there is a clever solution to this.
Your concern is spot on. Your API Secret should not be stored on the device.
However, I am not sure why you would be concerned to build a separate endpoint, since OAuth 2 has a authorization flow for these use cases.
https://www.rfc-editor.org/rfc/rfc6749#section-9
In your use case, I'd suggest using the implicit grant flow to fetch the access token and store that on the local device. There would be no refresh tokens and the access_token can have an expiration date. Of course, the token on the device can be compromised, but the damage will be limited to a particular user and not the entire application.
If this level of security is not acceptable, then you can look at splitting up your API Secret in different parts of your app and then assemble it at run time in your app.
I have 4-5 Android applications and I want to implement Single Sign on for all these apps. So that if user has logged into any one of that apps he won't be asked to log in again for other applications. How can I accomplish it in Android??
Implementing a SSO requires having a common database holding the user credential information. One way of doing it is implementing your own authentication server which exposes a login, register, reset and forgot password APIs which each of your apps would use to login into the application.
Lets say you are using JWT to maintain statelessness, which means auth server responds with a JWT for every successful login through any android app.
So your launcher activity in each of your app should not be login but the dashboard or whatever the user sees after login. In the on_create of the dashboard, check if there is an existing jwt available in the shared preferences. If there is one, go ahead with the dashboard. But if there isnt one, goto login activity and let the user login first. Once logged in, preserve the jwt in shared preferences for the other apps to use it. You need to make sure that all the shared preferences are using the same namespace to access the jwt.
To make it more effective, you can implement a library module for login, regd and forgot password to be included into each app and you would have that part for all the apps ready. The XML files for three activities can be included into the lib itself and app will load them from the lib file if it doesnt find it in the app drawables.
Now coming to server part, implementing your custom auth server, say using OAuth2 is one way but to make it easier, there are 3rd party solutions like Stormpath or CAS which would provide such a service. May be you can find one which is free too.
Instead of JWT, you could use userId (primary key in the user database) to identify if the user is logged in or not.
Another point to consider is if the application server for each of these apps, if they have one, are using JWT or userId to respond to app requests and based on that auth server communication token should be decided. Needless to say, that application server and the auth server should also communicate among them to sync user information for app. This would be the same even if you are using a 3rd party auth server which would talk to a single database holding the entire user information but you might need to work on syncing your application server with 3rd party auth server
However, the tricky part is in logout and reset password and change password. I am not talking about the logout process if JWT is used, which has its own challenges to meet, but I am talking about the logout when SSO is used. If the user logs out from one of the apps you need to decide if the user has to be logged out from the rest of the apps or not. Both can be handled though but usually it would be a single sign out for ease of implementation and it would provide a good UX too.
Also, if any of these apps has a website version and the user changes or resets password from the website, you need to make sure that user logs in again on the device when he first uses the app after the change. However this logic has to be managed entirely on the server side inside the auth server.
Though your question is related to android app only, you might have to implement a server for that and modify the appl server too for each of the app. There might be a chance that this might not be your question essence entirely, but your actual requirement might help me to help you implement this.
I'm intested in building some kind of password-less login between a mobile app and an API (assuming I can control both). The motivation is that having to login is very annoying for users and has security risks (eg. users will reuse existing passwords) and I want the users to be able to get started with the app immediately.
I'm wondering if there are some techniques that could work. For instance:
Generate and random login/password on the mobile device and store the password in the keychain.
Signup with the API using this login/password combination. This returns a token.
Token is used in subsequent calls
The drawbacks are:
Login/passwords can be lost if user deletes app (this could maybe be mitigated by using iCloud to store the login - but that would be bad for the password?)
Password is stored on the device (however it's in the keychain)
So my questions: is something like this feasible and secure enough? Are there known techniques to do that?
Here's what we did:
Basically, the idea is pretty similar to the "forgot password" most services offer:
Ask the user for an email
Send an email with an activation link. The email contains a deeplink with a one time token, something like myapp://login?token=......
User opens the email on the device where the app is installed this is crucial for the deep link to work, but it what happens on 99% of the cases anyway. The user clicks the button with the deeplink
User is redirected back to the app, you extract the token from the deeplink on the app and send it to the server api to authenticate. After authentication is done, create a session for the user so they won't need to authenticate again
The good:
More secure: Users don’t have to think of new passwords (which are usually too simple) and there is no risk of users reusing passwords. For us as developers, it offers a solution that has only one (and simple!) path of authentication that is easier to understand and hence to protect. Also, we don’t have to touch any user passwords / hashed passwords.
Smoother onboarding flow to the user: if you pre-enter the email in the input field the login flow can be as short as 2 button clicks and they're in. (unless you wanna take their name / other details as well but that requires additional input fields in traditional login as well)
The less good :)
Users might not be used to this flow very well and might wonder why they don't need a password. I would add a small link explaining "why we don't need passwords?"
If app is deleted or the user logs out, they will need to use their email to log in again. This is less of a problem for mobile apps where users don't occasionally log out and in etc
I've already implemented this flow into our app, you can read a more in depth explanation here:
http://www.drzon.net/passwordless-login-in-mobile-apps/
Some more considerations:
To make it more secure, make the token available to use one time only and also put an expiration on it (like an hour). You can also tie the token to the specific device by sending the server a unique device id of some kind along with the email address. This way the user can't simply forward the email to another person and he will open it instead
About the deep link - I found that some email providers block the use of links with custom url schemes like app://. The way to overcome this is by making the link point to your server instead and redirect there to the actual deep link
https://myserver.com/login?token=... ---> myapp://login?token=...
Mozilla wrote about it as well here
This is very open ended, but generally: don't reinvent the wheel, use a standard solution such as OAuth and/or OpenID Connect (uses OAuth). This has the drawback that users might required to login via a WebView or similar to get a token, but you won't have to store the passwords.
Things to consider:
you can't really generate a random password, since the server needs to know it as well
Android doesn't have a public keychain-like API, so you have to take care of securing the password yourself.
As for 'secure enough', pretty much everyone uses OAuth nowadays(Twitter, Facebook, etc), so it's at least proven. The actual security will depend on your particular implementation.