Storing API keys in the cloud for an iOS app - api

I am trying to find a way to store API keys for 3rd party services in the cloud (for example say I want to connect to twitter, i would need api key and secret to make oauth requests)
I specifically am looking for a way to store it in the cloud and somehow making use of it on demand (I don't want to embed it in the app itself). I don't want the api key and secret to be easily accessible but still want users to be able to make 3rd party api requests.
I'm not a security expert so just off the top of my head I had the following idea:
Store the api key and secret on my server (For example store twitter api key/secret)
Whenever user wants to make request to the 3rd party service, the iOS app makes a request to my server for the app key/secret pair
When the iOS client receives the key/secret, it starts oauth authentication process using the app key/secret it just received from my server (plus the user credentials)
Is this safe enough as long as I send/receive the key/secret values over https? Or do i need to encrypt them further? And would even that be enough?

I would not recommend you returning client credentials (API key and secret) for a 3rd party service to your client. You cannot keep these things secret on a public client like an iOS app.
A better way is to have your server make the call to the 3rd party API and proxy the results back to your app. That way, the API key and secret can be stored safely on your server and if the 3rd party API ever changes, you only have to update your server code, and not all your iOS apps.

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.

Secure App with Api server with static jwt token

This may have been asked but maybe 2018 there is a better way. I"m trying to secure my api server and only grant access to my client apps I have created. Mobile / Web client apps that is using vue.js for client app and express.js on node for api server.
Would is be wise to create a static token code it in on the client app. It would be sent with every api call. Then on the api server have my secret to the token. Verify the token before api call can be sent back.
Is there a better way? It seems to work fine but maybe there is something I don't know. Maybe everyonce and a while replace the static token and secret? The network would be https for sure. I am sending the token with every api call req.body.clientAppToken
What do you think? Thanks everybody!
Update this is express api middleware below.
App sends a manually created token to the api server on every request. Token is the same for all apps. I verify the token with the secret stored on the server. If it passes they get the data if it does not they do not.
const jwt = require('jsonwebtoken')
const config = require('../config/config')
module.exports = {
authClientAppToken (req, res, next) {
// start see if client app jwt is correct
/* eslint-disable */
console.log('req.body.clientAppToken', req.body.clientAppToken)
try {
let decoded = jwt.verify(req.body.clientAppToken, config.jwtAppSecret)
next()
} catch (err) {
res.status(400).send({
error: 'We got problems'
})
}
/* eslint-enable */
// end see if client app jwt is correct
}
}
I"m trying to secure my api server and only grant access to my client apps I have created. Mobile / Web client apps that is using vue.js for client app and express.js on node for api server.
The cruel truth here is that you cannot truly secure a web app because any kind of secret, be it a JWT token, a signed JWT token, an API Key or anything else you may want to use is very easily retrievable on the client side just by using the browser developer tools, aka F12.
On a mobile app developers may think that once they ship a binary that they can hide a secret there and keep it safe, well mobile apps are not as trivial to look into as using F12 in the browser, but they are easy enough to reverse engineer with tools like the Mobile Security Framework, that will extract all the code in the binary, thus exposing all the secrets stored on it. But even if the secrets are computed at runtime this tool is capable of doing runtime introspection on what your mobile app is doing, thus able to extract also dynamic computed secrets.
Would is be wise to create a static token code it in on the client app. It would be sent with every api call. Then on the api server have my secret to the token. Verify the token before api call can be sent back.
So as said previously any secret generated or stored in the client side can be extracted and reused outside of the scope it intended to. Despite this I still encourage the use of them as 1 more layer of defence.
It seems to work fine but maybe there is something I don't know.
I would recommend you to go through this series of articles on Mobile Api Security techniques to understand how https, certificate pinning, api keys, tokens, HMAC can be used to secure the API server and how they can be bypassed. While the article is in the context of a mobile api, almost everything applies in the context of an API serving a web app.
Maybe everyonce and a while replace the static token and secret?
Using short lived expiration times on tokens is wise and recommend, but they just make the window where they can be malicious reused shorter but they will not prevent API abuse.
The network would be https for sure.
While https should be always used by itself only guarantees that the data in transit is encrypted and cannot be readded by third parties, thus protecting the secrets in transit but will not prevent them to be reverse engineered from the app itself.
Is there a better way?
For web apps you can make it hard by using a javascript obfuscation tool, implement reCaptcha V3 and if you want to go more advanced a User Behaviour Analytics Software solution on your API server.
Regarding mobile apps is possible to build them in a way that is not needed to store secrets in them in order to pass down in each call to the API server. The technique is called Mobile App Attestation and consists of a mobile sdk and a cloud service that work together to ensure that the mobile app is the same one uploaded to Google Play or to the App Store. The mobile sdk runs in the background and communicates with the cloud service that will issue a valid JWT token when the app is the original one and is not running in a jailbroken or rooted device or being object of a man in the middle attack. A valid JWT token is one that is signed by a secret only known by the cloud service and the API server, the mobile app does not know it at any moment, thus is not possible to reverse engineer or fake it. An invalid JWT token only differs from a valid one by being signed with a secret not known by the API server, thus making it indistinguishable from a valid one. This type of security solution can be found at Approov and this is where I currently work.

Mobile app with api authorisation access

I'm creating a mobile app for customers that need to access an api that I use.
The api requires authentication and the app needs to call the api to receive some data that is specific to each individual customer(mobile app).
I just want to make sure that the right way to do this is for the mobile app to send the query to my server which will then make the authenticated api call and return the response to the mobile client?
or is it possible to have the mobile make the api calls directly, presumably using the same authorisation key?
This is primarily an opinion-based question, however I'll give it a go:
[paraphrased] Can my server act as an API proxy to make authenticated calls to another API on behalf of my unauthenticated users?
This is a common occurrence in the API world, but some things you need to consider:
It's an extra layer in between the user and the service, which adds time to the data transport. Make sure you build your proxy to be scalable or use a 3rd party service that can manage that on your behalf. Either way, don't forget to factor in cost.
Usually service providers require authentication for a reason. Are you violating any license agreements by opening up their API like this?
Is the authentication per-application, or per-user? If it's per-user (e.g. each user logs in and retrieves a unique access_token) then you're going to be making calls to the back-end API as a user instead of an application.
Is the destination API rate-limited? Instagram's API, for example, only allows 5000 requests per hour. If you have 10,000 users that use it once per hour, you'll have already hit that limit.
Are there security concerns opening up the destination API like this? Is there sensitive information that you need to protect? If so, opening it up like you do are you creating security holes?
Is it possible to have the mobile make API calls directly to the target API, presumably using the same authorization key?
Absolutely this is possible - provided that you follow the authentication flow established by the target API. You'll want to consider the same list of concerns listed above though, in addition to:
If you're using an auth flow like OAuth2, the standard dictates that each user should authenticate as themselves and make API calls using a unique access_token. Does your target API provider offer this service? If so, that's the way to go, that way if an access_token is compromised, only that user's data/account/etc. is at risk.
If you're using app-level authentication (e.g. your app's client_id and client_secret) directly in your mobile app, be warned that it can be obtained and compromised with little effort, and thus an attacker could gain access to the entire target API this way.

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.

How should I authenticate API users in my client-server system?

I am writing an API to use with my mobile app. I want to use Api Key authentication.
In this kind of system, should I give an api key to each user? Or should I only give Api Key per application that connects to the API?
The reason that I asked that is:
If I give every user api key and authenticate them by their api key, authenticated user will be only one, and I can make requests like /reviews/ and server will return all reviews which are done by authenticated user.
On the other hand, the app will authenticate to use the api, and I should make request like "/reviews?userId=23842374283423".
Which one is the most used type of authentication?
Normally the API keys are issued to the developer who consumes the API rather than the application. Although in most cases each key is used only for one application, in theory you could have another one using the same key. I would recommend going for the second approach.