I want to offer some functions of my webapp to be used in other apps (I'm thinking mainly about smartphones, since they offer more capabilities e.g. GPS, Camera,..).
From what I have encountered myself so far in terms of other APIs e.g. GoogleMaps, is that a 3rd party developer would register himself at my site, he gets an API key (some random UUID) and he has to use it to authenticate his requests against my website. So far so good...
Is there a mechanism to protect the end user of a mobile app from malicious apps? E.g. a 3rd party developer could build an app and capture all username/passwords from the end user, so that he can do bad stuff with the useraccount.
(E.g. I could build a twitter app, capture all the usernames/passwords and then delete all their tweets, post new ones,..)
Is there a possibility to prevent this? AFAIK you could use oauth on the web so that my website login box would appear on another site and ask them for their username/password, so that it isn't shown to the 3rd party site.
Is it possible to implement a secure authentication for smartphone apps? How would you do it?
For Android and iPhone you can use OAuth without problems, and so far I think this is the best way to be done.
The flow for these two smartphone types is the same like in web applications, because both OS give you the possibility to start web browser from your application and redirect the user to web provider, so he can authorize your request (token), and then the browser can return your user to the application via proper callback URI. I haven't implemented oauth for mobile phones, but I've heard from a friend that it's possible and that the mobile browser can redirect the user back to your app with some special URI, like scheme://app/parameters.
Here is something for this with android: link
There are two oauth use cases: 2-legged and 3-legged
2-legged is when you want to protect your API, so that it can be called only from authenticated consumer applications. This is a popular scheme that exists from ages AFAIK - the consumer signs every request with a consumer shared key, and the provider (your API), signs the request also to see if the signature match. This way you can tell if API usage is ok for that consumer.
3-legged oauth includes the end-user of the consumer 3rd party app. It is very suitable, if you want to protect your API again like in 2-legged, because requests are still signed, but also your API can be protected by the end-user's permission. The provider of the API issues a token and gives it to the consumer application (3rd party app). Then this app saves the token locally and redirects the user to Provider for authorization of the token. When the user authorizes it, the provider sends back the user to the consumer application and then consumer can make authenticated (signed) and authorized (by the user - 3rd leg) requests to your API.
The protocol is not very complicated once you read how it works, and is very flexible - you can extend it to your needs however you like. I would highly recommend it for protecting APIs, especially if user permission is required for access to the APIs.
This is a very good site to read about oauth: http://hueniverse.com/oauth/
--- ADD ON ---
There is some security implications regarding shared key storage in the consumer application - mobile phone app in your case.
If somebody open your program and disassemble the code and extract the shared key, then he can make application which will authenticate successfully to the provider API. However this is not a very big concern if user authorization is required (3-legged), because the user will still be asked to give permission to this false application - and now it's up to the user to make the proper choice. And besides that - the false app will not be able to steal user's credentials, because with oauth, user credentials are entered only at the provider's site.
On your second question:
The benefits of oauth are:
User can be asked for permission when sensitive API is access by 3rd party;
User will never enter his credentials at 3rd party app. Every 3rd party app is untrusted and is potential attack vector.
For example, if you are gmail - provider of API and you provide web service method login(user, pass) to 3rd party app developers, then they can make login screen in their app and log in the users. However in this process their 3rd party app directly receives user credentials before sending them to gmail. I would never use such application. The problem is that most people are not familiar (especially non technical people) with the consequences of such application usage and people making applications are still exploiting this old and insecure way of doing things. However, as more people engage to implement some security protocol like oauth (or similar), the people will become familiar with this flows and will become more suspicious to such intrusive 3rd party applications.
I say intrusive, because imagine for a moment the following scenario:
You can make a payment API in a not so developed country like Bulgaria or Albania. This is a very good opportunity for businesses to use, because Credit Cards are not a common payment method at all at these locations.
And this provider API is protected by exposed web service method login(user, pass). After 3rd party app use this method with user credentials (which it has already taken), it gains access to charge(user, amount) method. It can then call this API method with whatever parameters it wants and charge the user with one hundred thousand million pessos :D
The user will not even know until later. And besides, you cannot separate API method calling by permissions - what the user is agreed to and what not.
Other drawback is that users use one password for many places - this way 3rd party app can gain access to another service that the user may use with the same password.
Related
Users sign up in my platform from the mobile app (Android & iOS). Once they have completed a form, I do a RESTful call to my server with the username and password and an API key.
https://api.example.com/v1/users/register
I assume that the API key is not protected since it is embedded in the app, so anyone can actually make that RESTful call and register as many users as they want.
How can I protect this call so that users can sign up ONLY from the mobile app? How do other apps (e.g. Facebook, Twitter,...) solve this problem?
How can I protect this call so that users can sign up ONLY from the
mobile app? How do other apps (e.g. Facebook, Twitter,...) solve this
problem?
There is no way to restrict your RESTful call just for mobile phones. Anybody could emulate that call impersonating a device manipulating headers or whatever. The only way to face this problem is to have a good security protocol design between your app and your backend.
As you mentioned, Facebook and other big companies do not store any API Key since the beginning in their app, instead they allow users to sign up through a website or mobile setting up specific user credentials. These signing ups are protected agains massive registration attacks using anti-bot techniques both from client (CAPTCHA) and server side (source IP + timings). Once those credentials are created and authenticated, their endpoint will return a client specific token which would be valid to make further REST API calls, and only this very user will be authorized to use that token for a limited period of time. One typical approach nowadays is to use Oauth 2.0 as you can see in many public API specifications like: Paypal, Twitter, Facebook, etc. I suggest to research other famous REST API specifications, you can learn a lot from them.
Almost all of known techniques mentioned before like CAPTCHA, server side checks and so on could be defeated by a hacker. However, if you still want to add some additional barriers to avoid unlimited user accounts, one good idea can be to add two-step verification process to verify an account. Unless this process is finished correctly, the user won't be able to use your backend API (apart from the one to authorize the account). Thus, a user may be able to create a few accounts with different phone numbers, but never an unlimited amount of them.
I think you have to devise a flow like reCAPTCHA. Its documentation may give you a hint.
TL;DR: I would like a native (already logged in) Android application provide auth tokens to third party applications installed on same device. I would like to use as much as possible of standard spring-security-oauth2 code as I am no OAuth2 expert.
Long version:
I have a system consisting of:
an Android client application
a central web application exposing some data via REST APIs currently secured by HTTP BASIC. The central app holds a repository of user accounts.
this all works well in an isolated environment.
Turns out third party Android app providers would like to integrate with my system. Actualy no REST API calls will be made - the only purpose of the integration is joined user accounts.
I have created an OAuth2 (spring security based) authentication server that third party apps can use - this way the users can use same credentials both in mine and third party apps.
Thing is: my users still have to enter the credentials at least once for each app. This is cumbersome: my users are kids - they often do not remember or are simply not able to input credentials.
Instead of forcing third party providers embed WebView in their application and handling OAuth2 calls to my server I would like them to call my application which is conveniently already logged in. My app would handle the actual authorization UI (via native activities) and respond back to calling app with proper tokens.
The main problem is: I do not know how to start.
Can I force spring-security-oauth2 to use JSON only? I see that the most important authorization endpoints generate html on the fly.
Do I have to create my own endpoints handling this approach or any standard OAuth2 flow would do?
Background
We have developed a web application featuring a rest-api using oauth2/oidc and support for third party apps
We have developed our own native apps for android and ios. Currently they retrieve a long lived token from user credential flow (no consent screen needed).
We are currently extending our authentication flow to also accept external login by google/office365. This is also supported by specifying acr value in authorization code/implicit oauth flow.
Issue/Problem
We of course want to be able to fully trust our native app and not show a consent screen for the best user experience. While using the authorization code/implicit flow though nothing can be considered a secret and a malicious hacker could potentially exploit (without user knowledge) the user if no consent screen is shown.
How can we avoid having to show consent screen for our own native app while still being sure user is as safe as possible?
How to solve?
Doing a separate office365/google login to retrieve refresh token from this idp and then implementing a way to publicly authenticate using this token to retrieve a longlived token from our webapp.
Simply ignore security flaw and never ask for user consent given the nonsecret mix of `clientId/clientSecret/redirectUrl` with the excuse "it's quite difficult to hack this".
Ignoring security flaw if external login with the excuse "google/office365 should show a consent screen anyhow when requesting a refresh token".
Some unknown way to make sure that its not a malicious app/user
The reason i don't like (1) above is it both opens up a somewhat new authentication flow in our webapp and forces native app to implement a more complex authentication flow.
Is there something im missing here, what would be considered best practise?
The point is that Google needs to authenticate the user outside of your app to make sure your app does not see the user credentials and thus defeat the purpose of OAuth.
The user also needs to allow the app explicitly to avoid random apps obtaining tokens from the user: anyone with a Google account can create a client_id/client_secret/redirect_uri combo. You/your app is not trusted by Google with tokens for arbitrary users without asking those users first. As you mention at (1) the user only needs to go through this once. The app may retrieve a long-lived refresh token and keep using that to refresh access tokens.
Hence best practice is to spawn a browser/webview and handle the authentication/consent flow in there. There's no way around that. If there was a way it would be a vulnerability because the system was designed to avoid it.
I'd say something like nr 2:
Have a way to mark a client (identified by clientId and clientSecret) as trusted (e.g. with a superuser interface), and thereby automatically give consent.
The client secret should be safe; if it's not, you have other security problems.
We're developing a REST based API that developers would call from their mobile apps, e.g. google play apps.
How can we make sure that the app developer doesn't steal the users user/pass by storing them or sending them to "EvilServer".
If we do not trust the app developers, does a technical solution to this problem exist?
Could one solution be to have our own trusted authentication app on the native platform and let app developers use it to authenticate?
What I would recommend is to first remove the ability for a third-party application to log a user to your service using his credentials, so there is no reason for an app to ask for the user's credentials in the first place.
I would instead provide an OAuth authentication endpoint (take a look at the server-side flow) to third-party developers in order for them to use your authentication service to register and authenticate users in their app. This is interesting because users have to be redirected to your authentication endpoint when they log in, so there is no chance a third-party application can have access to their credentials at any point.
However, nothing prevents the developer of an evil app from creating a fake form requiring the user to provide sensitive informations in order to log them in, such as an email and a password.
In this case, you can do two things :
First, educate your users (e.g when they create their account) not to provide their credentials on any other website than yours. This is typically done by banks and insurance companies.
Implement Multi-Factor Authentication to add another layer of security to your authentication process. Most web companies such as Google or Twitter allow you to require that while providing your usual credentials when logging in, you are still required to validate the login process using an out-of-band medium. They typically achieve this by sending you a PIN code via SMS on your phone that you must input on a web page to finish the login process.
As such, if someone tries to log into one of your user's account, it will fail unless they have also access to the user phone.
OAuth attempts to solve this problem by sending the user off to a provider to authenticate before bringing them back to the original site or app. This is how the "Log in with Facebook" and "Log in with Twitter" systems work.
There's a handy diagram at http://www.quora.com/How-does-Login-with-Facebook-option-work-on-third-party-websites that shows how the requests are passed back and forth.
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.