I working on a mobile app that has some functionality that is not implemented natively but only on an external website. The user is logged in into the app, but when opening the external links (both in a webview and in the external browser) it has to log in again to access the functionality.
Is there any way to authenticate the user in the browser too without compromising security and/or user experience?
Any experience / best practice to share?
If you're using something like a REST API to log in then it may be returning something like a session token in the response cookies so that subsequent requests to the API will know which user they refer to. For that case you would need to copy the API cookies into the URL request for the web view or into the web view's cookie store before making the request, as I recall.
Related
I need your suggestion on this particular problem.
I am trying to embed a web-app into flutter mobile using WebView or just say an mobile app in general. That web-app does has the authentication, only users have correct username/password can login.
However, The mobile has the authentication part as well. I dont want users to login 2 times, mobile app then web app, but in the mean time, I dont want users access web-app or mobile app without logging in.
I would like user login to the mobile app and somehow authenticate to access to the web-app as well. I am trying to make this connection secure.
Solution that i am thinking now is that: getting username and password from mobile app. Then pass it to the url of that web-app. and then the Web-app will do the rest.
Any suggestion ? Thank you.
Do NOT put the password into the URL. That has severe security issues- anyone within your company who has access to your http logs will be able to see your user's passwords.
If the web app is being brought up as part of the mobile app it should be easy. When you authenticate, you sent some token down to recognize future requests. Send that token as a header or cookie when you go to the website, and have the web app look for that header and authenticate with that token. Your web app is already doing that via cookies, so if you send the token as a cookie and your web and api servers use the same authentication tokens, you're good.
If the web app is being brought up in an external browser, then you're pretty much out of luck and they'll have to log in twice.
what is the correct way of handling OAuth on mobile devices? Android, iOS, etc..
As I am seeing most apps just do load the login screen into an in-app browser like WebView, or so..Isn't it actually trampling the whole principle of OAuth? because I can as a developer easily read the password the user enters into the textfield..Is there a way how to do that with the startActivityForResult pattern (on Android particularly)? Because when the user would enter their login and password into the main system browser, it should be a way more solid approach to maintaning security and trustfulness for the app?
Passing data between the app and the browser
You have to read the response (the reloaded url) from the page, after the user has logged in, to get the authorization code used to request the authentication and refresh tokens. If a (default) browser has to take responsibility for returning the authorization code for you, then it has to have (documented) implementation of receiving such intents for such a result.
Letting the browser know your app's credentials
There is another even more serious problem - usually you request authorization/authentication using your app's credentials (client id + client secret). You put them somewhere in the headers or in the url as parameters. You'll have to provide them to the browser to put them in the headers/url of the request for you.
Combined:
And when the browser has both authorization code and your app's credentials it can acquire auth/refresh tokens for the user's account and not only have access to it but also pretend to be your app. Having in mind that this is the built-in browser that comes with the device the user will be calm because he'll probably trust the manufacturer as he's buying it's device but can the app's developers trust the manufacturers? And when a user chooses a 3rd party browser as default and/or uninstall the built-in one?
In short:
Instead of the user trusting the application he/she installs, both the user and the developer have to trust the 3rd party - the browser
What is the point of using OAuth 2.0 client-side authorization in Android if built-in WebView browser doesn't have access to cookies of default user browser? I mean, if I open some oauth-url (e.g. http://blablabla.com/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=token) in WebView - the user will anyway be prompted to enter his credentials to sign in to "blablabla.com" social network. Because even if he is already signed in with some of his browsers (Opera or Dolphin, or default browser), the WebView browser doesn't know anything about corresponding cookies.
EDIT:
I'll try to make it a bit clearer.
The main goal is to simplify sign-in procedure in my application. I'd like to implement such mechanism that we can see on many web-sites: "Login with... Facebook/Google/Twitter/whatever". And in desktop browser that approach works perfectly, because the end-user is already signed in to aimed service WITHIN THIS BROWSER. So basically to sign-in in to my site all he needs is:
Press button "Sign in with..."
On redirected window/popup press
"Approve/Confirm".
Get redirected back, already being signed-in.
The main benefit is that user doesn't need to enter his email/name/whatever - I've already extracted it from his social-network account.
And I'm wondering how to get same effect on Android. The problem is that, as I can see, we can't let user avoid entering password, because the application (WebView) never knows if he is signed-in to some outer service or not. That's why user anyway will be prompted to enter some of his details and all of OAuth benefits become annihilated.
The workaround depends on what you are trying to do. It's not clear to me, looking at your question again, because you do not explain your use case. Instead you are indirectly asking for something that looks very broad as if you want to maintain an Android system-wide login state that spans over multiple applications using shared cookies.
Due to security reasons that is neither good nor wanted. A rogue app could do whatever it wants to do with existing access tokens requested by other apps or just temper with or read existing cookies created and maintained in other apps.
Assuming you are trying to authorize your own app access to a web service using OAuth 2.0 by letting the user log in with a WebView, you need to implement your own WebViewClient, override its onPageStarted or onPageFinished method and check whether the URL argument matches your redirect URL.
If there is a match you need to extract the access token from the URL string. If there is also a refresh token available, then extract that one, too.
(This however only works for a certain type of OAuth flow, which adds the access token to the redirect URL.)
Now you have at least an access token available. Store that token in the private preferences of your application and use it in your service requests until you get a 401 not authorized error message back from the service. At that point you can use the refresh token if available to request a new access token or you have to show the login WebView again.
If you are trying to access a Google service from your app you may find the article Getting started with the Tasks API and OAuth 2.0 useful.
Have you considered launching the browser externally (non-embedded)?
That will benefit from existing cookies and also give users the trusted UI they are most comfortable with when entering credentials to these services. (in other words - users see the SSL lock, the correct URL in the address bar, etc.)
Since this issue is about three technologies I'd like to quickly introduce each of them:
node.js: javascript on the server side (consider it my webserver)
PhoneGap: framework that allows me to write Android applications in HTML/Javascript/CSS.
facebook authentication: using everyauth to let my users login with their facebook account
The objective: I need my PhoneGap application to communicate with my server using a REST based protocol. Many of these requests may only be made when the user has logged in to my server, using their Facebook account. Thus, the user needs to login and then go to the logged in state of the PhoneGap application.
The issue: When I setup everyauth for facebook I basically have an URL, like domain.com/auth/facebook which will redirect to Facebook's login "popup". When the user then accepts the login, the server will know, and so far everything is good. The problem is that
the user now has to be redirected to some external URL, while he should simply get back to the PhoneGap application (in a logged-in state)
The PhoneGap app does not retrieve the authentication token, or whether authentication was successful or not, because the login process is done in the external URL domain.com/auth/facebook while the PhoneGap application's HTML is stored on and run from the phone itself
Cause of the issue: the reason this issue appears while it does not for a normal web application, is that the PhoneGap application's HTML files are stored and run from the phone itself while authentication goes through domain.com/auth/facebook, which is considered to be a different domain.
Suggested approach #1: a PhoneGap user has recommended me to use this Android-Facebook plugin for PhoneGap. The issue here is that the server does not act as an authentication middle-man. Thus, the user would have to inform the server of their authentication token instead of the normal approach where the server informs the user of a successful authentication procedure and the corresponding tokens. This seems like a severe vulnerability.
How should I tackle this issue?
With the ChildBrowser plug-in, a PhoneGap app can monitor location changes from the authentication site.
We used this approach to integrate a PhoneGap app with a node.js openid module
I have implemented one solution for Twitter using jsOauth and ChildBrowser (tut./src here) for a PhoneGap / Android app. I know this doesn't include custom registration with a nodejs server; it allows access to Twitter REST only. AFAIK this is the only way to do it currently, that is, have the child browser check each new location to see if it's your app's return-to url, then intervene (close browser window) and go to your own app.
With jsOauth library, the auth token key/secret are stored for you and sent with every request.
Re: security - No expertise here, but discussions conclude this kind of data on one's personal phone are no more at risk than everything else on the phone.
Tut. using PhoneGap / Android Facebook plugin in next on my list. Thanks for link to everyauth!
I have a C/S solution, which take Android as its client and PHP as its server.
I have my own account system.
I'm wondering whether I could provide my user to login my system with Google Account?
I saw there are web-solution for this, like this stackoverflow.com could use Google Account to directly login.
Is there a solution for C/S system?
Not without a web browser.
If the user isn't logged in to google (or any other provider), he has to authenticate with the provider first. This is done via a web browser, and you shouldn't even try doing it in any other way (for security reasons, the user should be sure that he is connected to the provider, for example by seeing the url in his browser).
However, even if the user is logged in, the provider needs to know that -- usually using a cookie. And cookies are stored within a web browser. So in theory, you could parse the browser's cookie file, and then try immediate authentication, but that won't work until you login and authorize the relying party via a web browser first.