One big problem with OAuth on mobile apps is this scenario. I've seen this in the wild for non security-critical apps. As far as I can tell, it's not a bug so much as it is a problem with the OAuth protocol and webview permissions:
1) MyLittleApp wants OAuth access to BankOfMars
2) MyLittleApp bundles BankOfMars SDK into MyLittleApp
3) MyLittleApp requests oauth access via SDK
4) SDK opens WebView for user to log into BankOfMars
5) MyLittleApp has full control over the DOM presented to the user since the WebView is technically its own.
6) MyLittleApp extracts the user's password from the DOM of the WebView
2. User enters something to identify themselves into the web view (eg. email address, phone number)
3. We dispatch a notification to the user's registered device (ie. the Mondo app where the user is logged in – this may be the same device or a different device)
4. User opens the Mondo app and accepts/rejects the authorisation request
5. User returns to MyLittleApp, OAuth flow completes
In this flow, the user is not exposing their login credentials to the app… at worst, the app could extract their email/phone number. It also introduces another factor into the auth flow: the user's registered device.
I have two factor auth configured on my most sensitive logins (Microsoft account, Google account, Lastpass), and it works almost exactly the same. Except I use a standard Authenticator app. No need for proprietary protocols or apps.
This is unnecessary - if you are assuming that people will have Mondo app already, then the SDK will simply trigger an intent to open the app.
The reason webviews are present in the SDK is because of the possibility that your app is not installed.
You cannot depend on SMS pin without your app, because that can be spoofed. I don't see any option except for manual pin copy paste from the app to a well known website that can be opened in the browser.
You misunderstand. I'm not advocating for an app only flow. I'm suggesting that your own flow is restricted to work well only if the Mondo app is preinstalled ... In which case your flow is useless anyway.
I think you should talk about the case when a customer does not have Mondo app installed and another app asks for authorization to access. How will the auth flow work.
SMS spoofing is a problem if the flow depends on the user sending an SMS, and generic impersonation (by the client app) is a problem if users have to do something like click a link in the SMS and enter a password. But if a phone number is already associated with the account, and the only SMS is one from the service to the user containing a randomly generated login code, it should be safe, no? At least, that's the flow everyone and their dog seems to use these days.
> and the only SMS is one from the service to the user
There is zero possibility of a customer actually recognizing a phone number...or even a shortcode.
Assume that whatever SMS comes in your phone is going to be trusted by users.
However the one thing that people will know how to do is Google their banks name and go to the corresponding website.
The customer doesn't need to know the number, that's the point. The only sensitive info is what is being sent, so there is absolutely nothing to gain by spoofing a number and sending junk to the user.
It's like me telling you I'm going to email you the passcode to a gate. If Bob overhears this and knows your email and my email, he still isn't in a position to do anything if he can spoof emails. Best case is he sends you the wrong code and you don't get access until you get the real code from me.
The problem we are attempting to solve is that a third party app is demanding access to your bank account, but you only want to enter your password on the bank page. So the trust that needs to be establishmed, is that a page (being shown by the app through webview) is a genuine bank page and you can go ahead and put in your password there.
Bob is impersonating you in the first place and asking for the password. How do I know whether it is you or him?
Bob sends me a code, I type it in to his phishing site. So what? It doesn't actually result in him gaining anything useful because I still haven't revealed any banking login credentials.
What does replacing the auth page gain the attacker? At worst the user enters their email address into a phishing page. The important thing is that there isn't a password :)
>What does replacing the auth page gain the attacker?
If the spoof app has a "Connect with Twitter* (and you don't have the Twitter app installed), and then a webview is opened, the spoof app can replace Twitter's login page with their own, and capture the username and password.
In the proposed implementation above, the _only_ piece of information that a user enters inside the web view is a username. The user must then use the native Mondo app on a previously-authenticated device to complete the OAuth flow. The Mondo app could also require biometric (ie. Touch ID) authentication.
While a malicious application can inject JavaScript to intercept the username, this alone is useless to an attacker.
Well, the malicious application can inject a password-field, and an unsuspecting user might not realize that (s)he is giving an app/attacker the password, and not the correct third party.
User education only goes so far, this type of attack can also make a web view that traditionally asks for a TOTP one-time password code susceptible to leaking a users password, even if the normal login flow doesn't ask for that password.
[ed: note that it's pretty trivial to eg: set up hidden cameras in voting booths, if you want to spy on a few people, or perhaps have people film themselves in a voting booth - the point is rather that if most people make an effort to follow the common rules wrt. voting booths, the system is reasonably secure. And it's not trivial to make similar claims about a (presumably) centralized on-line system.]
On Mondo, there simply are no passwords at all. Instead, when the user wishes to log into our first-party apps, we send a login link to their registered email.
We'll almost certainly add additional required factors to this process (eg. biometrics), as we see the user logging into the Mondo app on a new device as one of the most critical from a security perspective.
because people will install your app and then uninstall it. However they may still retain the OTHER developer's app that includes your SDK. This is just how customers behave.
If your flow is blocking on Mondo app being installed - that's fine. This means that the surface area of attack is restricted around your app. That's totally OK.
However - that is a very different positioning than oauth. I would say Oauth will degrade gracefully to your protocol if the endpoint is restricted to another app that must mandatorily be installed on the host device.
Yup. That's every app's problem though. I can also create a webpage and design a fake "bank login" inside of it to make you enter your credentials there. There is nothing you can do about that other than educating the user.
Yes, but browsers design goal is to allow educated users to distinguish fake and legitimate sites (URL bar should never be forgeable). With mobile apps, the app can display anything and there is no way for even well educated user to recognize forgeries.
Ok, so in that case the malicious app is able to steal your password... but if login requires two factor auth, the password is useless without also having access to SMS (or whichever 2fa solution) on the associated device.
This describes the flow for a "trusted client", which is not the correct flow to use for securing this scenario. Instead, the "untrusted client" flow looks like this:
1) MyLittleApp wants OAuth access to BankOfMars
2) MyLittleApp bundles BankOfMars SDK into MyLittleApp
3) MyLittleApp registers itself with BankOfMars,
which then has sole discretion over whether
to allow it to access data hosted by BankOfMars.
5) If approved by BankOfMars, MyLittleApp can now
request oauth access to a user's data
with the BankOfMars SDK.
6) SDK opens WebView for user to approve MyLittleApp's
request to access user's data hosted by BankOfMars.
User may reject the application's request.
7) If the user approves the application's request,
the user is then prompted for authentication.
This can be in the form of a username/password,
but may also include two-factor authentication
or whatever BankOfMars deems necessary for security.
8) Should BankOfMars or the user choose to do so,
either can revoke the right of MyLittleApp
to access BankOfMars data.
Now, with this said, this is actually one of Eran Hammer's criticisms of OAuth2: It's hard to get all of these pieces just right! Good security should be easier.
Chatmasta's (OP) flow is not incorrect, he just didn't describe it all. It is perfectly valid. The issue comes when the SDK opens the auth server's authorize endpoint in a WebView. In all cases, if the user is not authenticated with the auth server, he will need to log in. Technically this should be done via a browser redirect on the same page, not a WebView. So instead of the SDK opening a WebView, it should redirect the full browser window to the auth server's authorize endpoint, which will prompt the user to authenticate if he doesn't already have a session.
This is a problem with mobile apps unfortunately, since this type of browser interaction is going to be all over the place. For web apps it works just fine.
OAuth is, like much of authentication and authorization that has been well marketed, very technically flawed. It makes a big show of not trusting the recipient application with credentials, but anyone who's actually interested in stealing creds still can.
Plus it's way more complicated and has way more failure scenarios than simple password auth.
The only saving grace that I saw was that a service no longer has to store users' passwords to other systems, for persistent interaction with their data. I think this is really why people bother using it.
It makes a big show of not trusting the recipient application with credentials, but anyone who's actually interested in stealing creds still can.
How so, if you're in a browser and you check the URL? It's only flawed here because the app controls the browser itself, but that wasn't the original use case of OAuth.
Is #6 and #7 something you've seen happen, or conjecture about what might happen if some nefarious actor manages to develop a native app that requires banking integration, gets people to download it, then gets people to plug in their banking info?
I've seen DOM manipulation in the wild for other purposes (e.g. clickjacking for sending invites to friends). Beyond that, mostly speculation, yes. But there's nothing preventing the DOM hijacking from grabbing the password right out of the <input> field. (Unless there's some HTML5 permissions on those fields that I'm unaware of, certainly possible).
The other thing here IMO is if I'm a bank, and I have a 3rd party app making OAuth requests... I'll want to verify code before mass release. Or at least limit the amount of bearer tokens issued without approval (Nest does this for example).
Someone should internally want to review code, especially for a bank.
As a bank, if you provide an SDK for 3rd party developers to use, you are not in a position to review the app before release. Only Apple/Google gets to see that code.
The proper solution would be either 1) the ability to register 3rd party libraries with apple and require some kind of integrity check before approval (but even then, the 3rd party app could override library methods at runtime), or 2) code signing the binary blob library separately for every 3rd party developer (but then the problem is enforcement of where developers get the library from -- how do you verify SDK integrity from the bank server side?)
The fundamental problem is that, as soon as you give 3rd party developers the ability to natively integrate with your service via an SDK in their own app, you are playing a cat and mouse game.
It depends if that SDK has an API key barrier or not. I mean if I'm providing 3rd party access, I want to see how each individual app is performing and what it is doing.
But yes, aside from that potential difference, I understand what you're saying.
The presence of an API key is not sufficient to verify the client loaded your SDK with the same checksum as the one you released. The client can modify the code of the SDK to perform any arbitrary logic, including bypassing integrity checks.
Also, it would help greatly to be able to generate multiple auth users on your bank account (e.g. a read-only identity for giving access to MyLittleApp). I have seen this occasionally on banking portals, but it's very rare.
Wouldn't this be a reason to promote the use of (trusted) web browsers and web applications instead of native apps or third party API's for high security scenarios? While TLS verification is something that is not flawless, it is something that users are being constantly reminded of by their banks and governments (check the domain name, check the green lock next to it), and modern web browsers go to great lengths to improve the user experience for keeping an eye on the validity of a website.
When I pay for something at a webshop via my bank account using a common standard created for that purpose (IDEAL in the Netherlands, other countries have similar systems) I get forwarded to my bank's authentication service to authorize that payment. I can clearly see that the TLS certificate belongs to my bank, and my browser is content that it is valid.
This is why the OAuth Identity Providers that take security most seriously do not allow WebView login (or at least provide an SDK where you don't need it).
It's very hard to do but you can at least make your SDK do a fast app switch to safar rather than use a WebView. Of course evil apps can find a way around it like you said but at least you can make your SDK and Documentation point the right way,
I am not experienced with iOS but I also suspect there are more advanced WebView detection tricks. It also doesn't help that Apple really doesn't like fast app switching.
How exactly does one do this in iOS? There is a reason that Apple only allows Safari to power WebViews. How exactly would you extract the user's password from the DOM of the WebView on a non-jailbroken device using ANY APPLE APIs if the page was legitimately loaded from https://yourdomain.com ??
yeah, we need some kind of email version of oauth - where the id provider emails a link for the user to click on to authn and approve the auth code to go to the client app. it's a bit weaker UX, but your described scenario is a massive gaping hole.
mmm, thinking about it, might be compatible with the current spec.
1) MyLittleApp wants OAuth access to BankOfMars
2) MyLittleApp bundles BankOfMars SDK into MyLittleApp
3) MyLittleApp requests oauth access via SDK
4) SDK opens WebView for user to log into BankOfMars
5) MyLittleApp has full control over the DOM presented to the user since the WebView is technically its own.
6) MyLittleApp extracts the user's password from the DOM of the WebView
7) MyLittleApp disappears and... profit?