Secure client token authentication for API - api

I have a mobile iOS application that I want to authenticate to a RESTful API.
Every user potentially has multiple devices linked to the same account.
So far I came up with the following:
Client-side
Let user login with username/password
Send username/password & unique device id to server
Get authToken from server and set it in the HTTP Authentication header for each API call
On logout, remove authToken
Server-side
API uses SSL
user has many associated devices
devices are represented by unique device id and authToken
each time the user changes password, regenerate all authTokens
if a device is removed, delete authToken for that device
Would that be a secure approach to access the API and manually add/revoke devices?

Yes, this is a fairly standard approach. Google has a document that describes this approach (a majority of the document is geared toward getting the token from the server to the client so that may not be as useful to you). And some more detailed description of bearer token authentication.
You should see if the application framework you're writing the server in already supports an authentication mechanism like OAuth, so you won't have to write your own.

Related

Storing client secret on client side

I'm using an external service called auth0 in order to get an access token and let my users use my api. Auth0 is using Oauth2 protocol.
In short The user adds a username and a password, I'm doing a call to auth0 by using a client_id (apps have an id) and client_secret and I get an jwt access token in return. Then from there I carry this access token to have access to my own api since I can check its validity.
I have been looking around about how secure it is to store client_id and client_secret on the client side (e.g. web (javascript)/mobile (native or hybrid with ionic)) and everybody was saying that it's not secure since everybody can reverse engineer the code and get the client_id and client_secret. Ok...I can take it...what Can I do with them if I don't have credentials in order to get the access token?
Given that I don't want to store the client_id and the client_secret, one solutions I have thought is to make a direct call to my api (Java) with the credentials and then my api make a call to auth0 and return the corresponding access token. In this way the client_id and client_secret is stored in the backend and somebody cannot get them easily. Is that safe?
However I have some endpoints, e.g. creating use account, sending sms for phone validation etc, that cannot have credentials. How do I protect the api in such case? If I can't store my own access token on the client side how could I get an access token and access my own api without credentials?
Thanks
One possible solution that OAuth spec suggests is that you could have three different servers for your application.
client-side
backend server and an additional authentication server.
The preferred way of doing this would be that the client would send the user credentials to the authentication server. The authentication server would be a back-end server which contains the client secret
The authentication server will authenticate the credentials and return back the token.
The client will then use the token obtained from the authentication server to access the resource API server.
If you wanna know more check out this video
https://www.youtube.com/watch?v=rCkDE2me_qk
In my opinion you are almost certainly using the wrong OAuth flow. I use Auth0 with Ionic as both a web app and a native Cordova app. I don't have the client secret in my client code at all.
If you follow the Auth0 quickstarts (https://auth0.com/docs/quickstarts), you should be choosing (Native/Mobile App) if you are deploying to app stores, and (Single-Page App) if you are deploying the web version of Ionic. From there you can pick Cordova (for native) or Angular (for SPA). These should give you instructions that implement OAuth flows which DO NOT require your client secret. My guess would be you are referencing a "Regular Web App" quickstart, which runs server-side and CAN safely hold the client secret. That's not the world you're coding in if you are using Ionic Hybrid/Native.
I would consider wrapping the call to Auth0 into your own server side implementation as safe. Your API takes user credentials and then calls Auth0 and this way your client_id/secret are secure on your server and the client can be reverse-engineered all the way without compromising your security.
Regarding the other APIs which cannot have credentials you are pretty much out of luck. Their very use case is to be used by an unauthenticated third party, so at least the account creation API cannot really be protected. However you can still use some nicely designed constraints to limit the attack surface. E.g. you can require an email address/phone number to register and you will not allow the same address/phone number twice. If you set up your process that you first need to confirm your email address before you can validate your phone number this will make the life of an attacker a lot harder. He would need a real working email address, and some automation to receive your confirmation mails before he could get to call your SMS service. You could also rate-limit the service per IP-address so an attacker cannot cause your SMS cost to skyrocket by issuing a lot of calls for SMS validation in a short period of time.

API oauth2 which grant type should I choose

I'm working on a personal project composed of an API and 4 clients (web, android, iOS, windows phone).
I'm using django-rest-framework and oauth2 toolkit on the API side and I wonder which grant_type would be more suitable in my situation.
I read somewhere that the implicit grant_type is appropriate for working with mobile clients.
I'm currently using the resource owner password credentials system.
My current workflow is:
The user creates an account on the API registration page (http://mysite/api/register) then gets redirected on the web client.
The user have to authenticate himself on the API from the web client (the secret and client ID are store in the web client). If the authentication is successful the access_token and refresh_token are both stored in the user session.
Each time the user want to access a page I verify if he is authenticated by requesting the API using his access_token. If the request fails, I retry with the refresh_token. If it's fails again I redirect the user on the auth page.
The user can use the API on a mobile client with the same account without extra manipulations (the secret and client ID are store in a secure location ex. share preferences or keychain)
I like this workflow, it's simple and convenient for the user: he registers once and can use all the clients and I get a perfect separation between the logic (API) and the UI (client). But I'm worried about the security of this system. I don't want to expose my users to threats. Do you guys have any thoughts, recommendations, suggestions?
You help in this matters would be very appreciated.
Thanks in advance!

Secure third-party API calls on mobile app

I have an API with the following method:
https://api.example.com/services/dosomething
I am providing this service to three different mobile apps, each one with hundreds of users. When a user logs in in the mobile app, a call to my API needs to be made.
I know that providing each one of the three mobile apps a different API Key and doing a HTTP Basic Authentication with it is not secure, since the API Key would be unsafely stored in the device an anyone can take it and make bad use of it.
The approach of OAuth2 doesn't work, since I only have information of my three customers, not their hundreds of users.
What is the best approach to secure the calls to my API on mobile?
In your case, your approach with OAuth2 is good: mobile apps (clients) receive delegation from resource owners (your users) to call protected resources on a resource server (your API).
You only have information about your clients because OAuth2 is not dedicated to authentication of your users but authorization of you clients.
The clients are identified with a client ID. In your case and if you want to know which client calls your resource server, then each client should have a dedicated client ID. You may also identify it using other information such as the IP address or a custom header in the requests it sends.
If you want to know who your users are, you should implement the OpenID Connect extension. This extension works on top of an authorization server based on OAuth2.
The authentication of the user is performed by the authorization server. An ID Token is issued with information about the user. The client (or mobile app) does not have to get or store user's credentials.
There is an excellent video where the both protocols are explained (especially from 4:44 to 11:00).

REST API authentication for web app and mobile app

I'm having some trouble deciding how to implement authentication for a RESTful API that will be secure for consumption by both a web app and a mobile app.
Firstly, I thought to investigate HTTP Basic Authentication over HTTPS as an option. It would work well for a mobile app, where the username and password could be stored in the OS keychain securely and couldn't be intercepted in transit since the request would be over HTTPS. It's also elegant for the API since it'll be completely stateless. The problem with this is for the web app. There won't be access to such a keychain for storing the username and password, so I would need to use a cookie or localStorage, but then I'm storing the user's private details in a readily accessible place.
After more research, I found a lot of talk about HMAC authentication. The problem I see with this approach is there needs to be a shared secret that only the client and server knows. How can I get this per-user secret to a particular user in the web app, unless I have an api/login endpoint which takes username/password and gives the secret back to store in a cookie? to use in future requests. This is introducing state to the API however.
To throw another spanner into the works, I'd like to be able to restrict the API to certain applications (or, to be able to block certain apps from using the API). I can't see how this would be possible with the web app being completely public.
I don't really want to implement OAuth. It's probably overkill for my needs.
I feel as though I might not be understanding HMAC fully, so I'd welcome an explanation and how I could implement it securely with a web app and a mobile app.
Update
I ended up using HTTP Basic Auth, however instead of providing the actual username and password every request, an endpoint was implemented to exchange the username and password for an access key which is then provided for every authenticated request. Eliminates the problem of storing the username and password in the browser, but of course you could still fish out the token if you had access to the machine and use it. In hindsight, I would probably have looked at OAuth further, but it's pretty complicated for beginners.
You should use OAuth2. Here is how:
1) Mobile App
The mobile app store client credentials as you state yourself. It then uses "Resource Owner Password Credentials Grant" (see https://www.rfc-editor.org/rfc/rfc6749#section-4.3) to send those credentials. In turn it gets a (bearer) token it can use in the following requests.
2) Web site
The website uses "Authorization Code Grant" (see https://www.rfc-editor.org/rfc/rfc6749#section-4.1):
Website sees unauthorized request and redirects browser to HTML-enabled autorization endpoint in the REST api.
User authenticates with REST service
REST site redirects user back to website with access token in URL.
Website calls REST site and swaps access token to authorization token.
Here after the website uses the authorization token for accessing the REST service (on behalf of the end-user) - usually by including the token as a "bearer" token in the HTTP Authorization header.
It is not rocket science but it does take some time to understand completely.
3) Restricting API access for certain applications
In OAuth2 each client is issued a client ID and client secret (here "client" is your mobile app or website). The client must send these credentials when authorizing. Your REST service can use this to validate the calling client
I resolved this for my own API quite easily and securely without the need to expose any client credentials.
I also split the problem into 2 parts. API authentication - is this a valid request from a recognised entity (website or native app). API authorisation, is that entity allowed to use this particular endpoint and HTTP verb.
Authorisation is coded into the API using an access control list and user permissions and settings that are set up within the API code, configuration and database as required. A simple if statement in the API can test for authorisation and return the appropriate response (not authorised or the results of processing the API call).
Authentication is now just about checking to see if the call is genuine. To do this I issue self signed certificates to clients. A call to the API is made from their server whenever they want - typically when they generate their first page (or when they are performing their own app login checks). This call uses the certificates I have previously provided. If on my side I am happy the certificate is valid I can return a nonce and a time limited generated API key. This key is used in all subsequent calls to other API endpoints, in the bearer header for example, and it can be stored quite openly in an HTML form field or javascript variable or a variable within an app.
The nonce will prevent replay attacks and the API key can be stolen if someone wants - they will not be able to continue using after it expires or if the nonce changes before they make the next call.
Each API response will contain the next nonce of if the nonce doesn't match it will return an authentication error. In fact of the nonce doesn't match I kill the API key too. This will then force a genuine API user to reauthenticate using the certificates.
As long as the end user keeps those certificates safe and doesn't expose the method they use to make the initial authentication call (like making it an ajax request that can be replayed) then the API's are nice and secure.
One way of addressing the issue of user authentication to the API is by requesting an authentication token from the API when the user logs in. This token can then be used for subsequent requests. You've already touched on this approach - it's pretty sound.
With respect to restricting certain web apps. You'll want to have each web app identify itself with each request and have this authentication carried out inside your API implementation. Pretty straight forward.

Identify mobile application

Is it possible to identify (authenticate) a mobile application HTTP request ?
for example a request from a web server can by identified by the domain or IP, assuming I know from where it should come from I can accept the request or deny if it came from an unexpected origin.
doe's mobile application has some sort of unique id (that cannot be mimicked)?
If you need to make secure HTTP calls (webservice API) from a mobile app (a native compiled app), you can try the following approach:
Edit: This approach assumes that you can't rely on the user operating the app for authentication purposes (because then you could simply ask the user to type in a secure password in the app).
Assuming you are implementing the app, save some sort of secret API key in the code.
When the app makes an API call via HTTP, it will always be done using HTTPS (so everything is encrypted).
The app will send the secret API key as a URL parameter.
The server will authenticate by checking if the secret key is correct.
Sniffing the app traffic will not reveal the secret key (because of the HTTPS).
You are mostly vulnerable to someone reverse-engineering your app to discover the secret key inside. This can be made tough by using various obfuscation and anti-debugging techniques, but cannot be made truly impossible. As long as you're using a compiled language (like Objective-C, not JS for a web-app) this will already be tough without any special games. If you avoid placing your API key string as-is and compute it using some short code in the app, you've made it about 1000 times tougher to discover.
Without knowing more about your specific problem, it's hard to suggest alternate approaches. Please give more details if you are looking for something different.
There are two methods used in practice. HTTP basic authentication (not much secure for mobile apps) and OAuth2 (secured compared to HTTP basic authentication).
HTTP Basic Authentication: The process is simple for both technical writers of API services, and also developers using them:
A developer is given an API key (typically an ID and Secret). This API key usually looks something like this: 3bb743bbd45d4eb8ae31e16b9f83c9ba:ffb7d6369eb84580ad2e52ca3fc06c9d.
He is responsible for storing API key in a secure place on their server, so that no one can access it. He makes API requests to the API service by feeding the API key in the HTTP Authorization header along with the word 'Basic' (which is used by the API server to properly decode the authorization credentials). The key is also Base64 encoded.
For example key could be: 3bb743bbd45d4eb8ae31e16b9f83c9ba:ffb7d6369eb84580ad2e52ca3fc06c9d
encoded in base64: M2JiNzQzYmJkNDVkNGViOGFlMzFlMTZiOWY4M2M5YmE6ZmZiN2Q2MzY5ZWI4NDU4MGFkMmU1MmNhM2ZjMDZjOWQ=.
The API server reverses this process. When it finds the HTTP Authorization header, it will decode base64 result, read the API key ID and Secret and validate these tokens before allowing the request to be processed.
HTTP Basic Authentication is simple but for mobile apps securing the API Key is a main concern. HTTP Basic Authentication requires raw API keys to be sent over the wire for each request, thereby increasing chances of misuse in the long run.
Also it is impractical as you cannot safely embed API keys into a mobile app that is distributed to many users.
For instance, if you build a mobile app with your API keys embedded inside of it, a user could reverse engineer your app, exposing this API key, and abusing your service.
So HTTP Basic Authentication risky in open environments, like web browsers and mobile applications.
NOTE: Like all authentication protocols, HTTP Basic Authentication must be used over SSL at all times.
OAuth2 for Mobile API Security:
 OAuth2 is an excellent protocol for securing API services from open devices, and provides a better way to authenticate mobile users via token authentication.
OAuth2 token authentication works from a user perspective (OAuth2 name it password grant flow):
When a user starts the mobile app he is prompted for username or email and password.
The developer sends a POST request from app to API service with the login data included (over SSL). Then validate the user credentials, and create access token for the user which expires after a certain amount of time. This access token can be stored on mobile device, treating it like an API key which allows access to API service. When the access token expires user is prompted again for login details.
OAuth2 generates access tokens that can be stored in an open environment temporarily and are secure. It is secure because the access token are generated for temporary purpose and it reduces damage potential.
The token is stored according to the mobile platform used. For Android app, access tokens can be stored in Shared Preferences and for iOS app, in the Keychain.
It depends on how you define "mobile application". Any application running on a mobile device ? Web browsing running on a mobile device ? What is a mobile device to you ?
Anyways, the general short answer, is that you can detect the device type using the User-Agent sent in the HTTP headers. All popular mobile browsers sends this. But be aware, that:
It can be spoofed (easily)
Some applications (ie iPhone or Android apps and similar) can be written in such a way, that they don't send a user agent with the HTTP requests. Best practice mandates to send the User-Agent though.
I don't know of a more reliable way to do this; and as long as stuff happens over HTTP there generally won't be any way of knowing anything about the client for certain. For mostly all the use cases, you will be alright with looking at the User-Agent.
You can buy access to User-Agent databases containing various device data, if applicable, two of such being WURFL or DeviceAtlas.