I am in the planning phase a new project. I want to be able to control multiple relays from my android powered phone over the internet. I need to use an HTTP based server as a middleman between the phone and the relays. Django is my preferred platform because Python is my strongest skill set. This would not be a "web app" (with the exception of the admin interface for managing the user and their access to the relays). Rather, the server would simply provide an API in the form of HTTPS requests and JSON encoding. Though, I should note that I have never done any web development in my life, so I don't know best practices (yet). The authentication method should meet the following criteria:
Works over HTTPS (self-signed SSL)
Provides multi-factor authentication (in the form of something you have and something you know)
Be reasonably secure (Would be very difficult to fool, guess at. or otherwise bypass)
Is simple in implementation for the server operator and end user on the mobile client
Is lightweight in in terms of both CPU cycles and bandwidth
I plan to use the following scheme to solve this:
An administrator logs into the web interface, creates a user, and sets up his/her permissions (including a username and a password chosen by the user).
The user starts the client, selects add server, and enters the server URL and his/her credentials.
The client attempts to authenticate the the user via HTTP auth
(over SSL). If the authentication was successful, the server will generate an API key in the form of a UUID and sends it to the client. The client will save this key and use it in all API calls over HTTPS. HTTP auth is only used for the initial authentication process prior to reviving a key, as a session scheme would not be nessessary for this application. Right? The client will only work if the phone is configured to automatically lock with a PIN or pattern after a short timeout. The server will only allow one key to be generated per user, unless an administrator resets the key. Hence, simple, mobile, multifactor authentication.
Is this sound from a security standpoint? Also, can anyone point me to an example of how to use the HTTP auth that is built into Django? From a Google search, I can find a lot of snipits witch hack the feature together. But, none of them implement HTTP auth in the wayit was added to Django in 1.1. The official documentation for REMOTE_AUTH can be found here, but I am having difficulty understanding the documentation as I am very new to Django.
I'm not entirely sure of how basic auth would work on Django, but I can take a shot.
The basic auth article on wikipedia covers a pretty standard usecase for logging in. For Android I've personally skipped the first part (401) and just pass my credentials in right away.
With your auth request you will have to just grab the user credentials from the request headers (WWW-Authenticate) and then do all the necessary work for that. With the credentials you can then just use the authentication framework provided in Django to verify that the user then generate their UUID (I guess).
As for basic auth on Android it's a little bit tricky at first and may leave you pulling your hair. I've found this article on Basic HTTP auth for android which helps explain how to do it.
As for the security part of it, I'm not too sure. It's pretty simple, which I'd say is a good thing :)
Related
I'm using couchbase lite in an android app with sync gateway and couchbase in the server and it works great.
Now I want to make a request to node.js from the android app, and i want to use the same session to authorize the user in the node.js app.
Is it possible?
Can I read the session in node and match it with couchbase?
You're asking about authorization. This is tied to authentication, but you should make sure to distinguish between the two. It sounds like what you want is to authenticate the user, then have your node piece authorize access based on this.
Having said that, it depends some on the type of authentication you're using to establish your session.
Basic Authentication (when used directly with Sync Gateway) just passes a username and password that gets checked. I think you get a session cookie after that. It would be very difficult to use that to authenticate to anything else (as in, you'd have to modify Sync Gateway code yourself).
OpenID Connect, in the auth flow, might give a few ways to possibly do this.
One simpler way is to have the node app also authenticate the user. If this flowed through the same browser, the browser will often keep state that would allow the user to bypass re-authenticating. This could be a little clunky, because you'd have to pass things off to a browser (or a webview, but there are security issues with that, too), which the user would likely notice.
Another approach would be to be to do a sort of double redirect. (I think this would work, but I haven't tried it. I can't find documentation on whether an authorization code can be used twice.) In the authorization flow, have the redirect go to the node app. Then have the node app redirect again to Sync Gateway. Both apps can ask for the ID token.
Yet another way would be to have your Android app ask for the ID token directly and pass this in some protected way to your node app. As always, you'd have to protect against replay attacks, and I'm not sure what else, so this could be challenging.
In any case, Sync Gateway is built to request the ID token itself, so any approach will need to ask for the ID token twice.
Here are some references you can look at to investigate this further yourself.
http://connect2id.com/learn/openid-connect - A nice write-up of the OpenID Connect protocol.
https://developers.google.com/identity/protocols/CrossClientAuth - Google Identity Provider documentation that addresses sharing authorization between a mobile app and a web app.
http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html - A post describing the distinction between authentication and authorization, and why OpenID Connect (not OAuth) should be used when needing authentication.
Note: You can't use the Couchbase Node.js SDK on the bucket that is used by Sync Gateway otherwise it will mess up with the _sync metadata and documents won't sync properly; but you can query documents, create sessions, etc. using the Sync Gateway REST API.
You can refer to the documentation of the Sync Gateway REST API to get the list of available endpoints. And if you don't want to roll out your own HTTP wrapper, a JS library is available that runs on Node.js and in the browser: http://developer.couchbase.com/documentation/mobile/1.3/develop/guides/sync-gateway/rest-api-client/index.html.
I am building a mobile app that communicates to a server. I would like the communication to be as secure as possible, but I have no experience in this field.
Upon app first launch, app submits phone number to server, gets a 6-digits code via SMS and then submit those 6-digits to server. Assuming the 6-digits code is valid, server will then return the mobile app an API secret (long unique string) to be saved on the mobile app. I am doing this, so when the user re-installs the app on a another device, the server will revoke access to the old mobile device (i.e: the API secret will no longer be valid).
Where do I go from here? My intention is using the API secret to secure all future communications from mobile app to server (i.e: all communication following signup). I took the idea from different APIs I worked with previously where I had seen that each API user is given an API key/secret. On those API's I noticed that the API secret is used in the following manner, but I have no idea if that's what I need.
params = {"method": api_function_name,
"order": 'DESC'
"key": CLIENT_SPECIFIC_API_KEY,
}
params = urllib.urlencode(params)
H = hmac.new(CLIENT_SPECIFIC_API_SECRET, digestmod=hashlib.sha512)
H.update(params)
sign = H.hexdigest()
Can anyone help me figure out what I need to do from here?
what I need to do from here
For good security, one of the first things you should do is to figure out whom or what the communication should be secure against.
One thing to do for this particular app is to design a way for the server to determine which device should replace which device in the "re-install" case.
The code in the question looks like a decent way to authenticate the client over a confidential channel between the client and the server. The client sends (params, sign) to the server, right?
From your first post I can see you are calculating a hash of the CLIENT_SPECIFIC_API_SECRET. I assume this is so that you can store a hashed form rather than the raw CLIENT_SPECIFIC_API_SECRET? This is commonly done on the server side to prevent password's being exposed in the case of a hack. This is particularly important for service providers for which a single hack could lead to the exposure of a huge number of client passwords.
In terms of using the CLIENT_SPECIFIC_API_SECRET for authentication of the client instance there is definitely prior art. A good basic example of this would be the digest authentication mechanism specified in the HTTP Authentication RFC 2617 - look specifically at the section on Digest Authentication. Note that this RFC shows Digest Authentication for HTTP but the basic principles can be applied outside HTTP. For example, Digest Authentication is also used in IMS SIP.
To authenticate a device you could have a Digest Authentication step every time a device opens a connection to the server. Of course the connection should be encrypted (TCP with SSL) as well to prevent man in the middle attacks.
I have to lay out a plan to develop a RESTful API (Python/Flask) that could be used by our future web app (Angularjs) and mobile apps (iOS/Android).
I have been researching for three days and have come across several scenarios:
Using HTTPS is one way on top of the methods below to keep it safer. But https is slower, which could mean we need faster and more expensive servers.
Using Basic-Http-Auth and sending username/password in plain (yet https) over the wire for every request to the API.
Using Digest-Auth, which is a hash of the password and the tracking would be automatic This would work for the web app, however I wasn't able to confirm if iPhones and Android would support this natively. If they do, that could be an easy solution!
Using a custom http header, where I would send a custom Auth string in http header upon a successful authentication. But then I have to make sure I am sending this auth code for every request that the user makes. This makes it exactly like 1) with the difference that plain passwords aren't used and the auth code can expire without any risk. Also problematic is the tracking of the auth code, which is no longer automated as in 2)
Using OAuth is an option. But its quite difficult to set up. If there is no better way, maybe thats the only way?
Securing the API like Amazon S3 as described in this great article. In short, he says that both server and client would know of a private key, which they would use to hash the communication. It will be like gangster handshake, that you only would trust the delivery boy, if he knows the gangsta handshake. Further down the comments someone asks:
How to keep the private key “secure” in a pure HTML5 app ?
You are exactly right; in a pure HTML5 (JS/CSS/HTML) app,
there is no protecting the key. You would do all communication over
HTTPS in which case you wouldn’t need a key since you could safely
identify a client using a standard API_KEY or some other friendly
identifier without the need or complexity of an HMAC.
So in other words there is even no point of using the method for an web app in first place. And honestly I don't understand how this should work on the mobile device either. A user downloads our app and how do I send the private key from the iphone to the server? The moment I transferred it, it will be compromised.
The more I am researching the more indecisive I am getting.
I was hoping to ask some pros who have done this previously and could share their experience. Many Thanks
You seem to be confusing/merging two different concepts together. We start of talking about encrypting traffic (HTTPS) and then we start talking about different ways to manage authenticated sessions. In a secure application these are not mutually exclusive tasks. There also seem to potentially be a misunderstanding how session management can impact authentication. Based on that I will provide a primer on web application/web api session management, authentication, and encryption.
Introduction
Session Management
HTTP transactions are stateless by default. HTTP does not specify any method to let your application know that a HTTP request has been sent from a specific user (authenticated or not).
For robust web applications, this is not acceptable. We need a way to associate requests and data made across multiple requests. To do this, on initial request to the server a user needs to be assigned a "session". Generally sessions have some kind of unique id that is sent to the client. The client sends that session id with every request and the server uses the session id sent in every request to properly prepare a response for the user.
It is important to remember that a 'session id' can be called many other things. Some examples of those are: session token, token, etc. For consistency I will use 'session id' for the rest of this response.
Each HTTP request from the client needs to include the session id; this can be done in many ways. Popular examples are:
It can be stored in a cookie - cookies for the current domain are automatically sent on every request.
It can be sent on the URL - each request could send the session id on the URL, not suggested since session ids will stay in the clients history
It can be sent via as a HTTP header - each request would need to specify the header
Most web application frameworks use cookies. However application that rely on JavaScript and single page designs may opt to use a HTTP header/store it in some other location that is observable by the server.
It is very important to remember that the HTTP response that notifies the client of their session id and the client's requests that contain the session id are completely plain text and 100% unsafe. To battle that, all HTTP traffic needs to be encrypted; that is where HTTPS comes in.
It is also important to point out we have not talked about linking a session to a specific user in our system. Session management is just associating data to a specific client accessing our system. The client can be in both authenticated and unauthenticated states, but in both states they generally have a session.
Authentication
Authentication is where we link a session to a specific user in our system. This is generally handled by a login process where a user supplies credentials, those credentials are verified, and then we link a session to a specific user record in our system.
The user is in turn associated with privileges for fine grained access control via access control lists and access control entries (ACL and ACE). This is generally referred to as "Authorization". Most system always have both Authentication and Authorization. In some simple systems all authenticated users are equals in which case you won't have authorization past simple authentication. Further information on this is out of scope for this question, but consider reading about ACE/ACL.
A specific session can be flagged as representing an authenticated user in different ways.
Their session data stored server side could store their user id / some other flag that denotes that the use is authenticated as a specific user
Another user token could be send to the client just like a session id (which over unencrypted HTTP is just as unsafe as sending a session id unencrypted)
Either option is fine. It generally comes down to the technology you are working in and what they offer by default.
A client generally initiates the authentication process. This can be done by sending credentials to a specific url (e.g. yoursite.com/api/login). However if we want to be 'RESTful' we generally would referencing a resource by some noun and doing the action of 'create'. This could be done by requiring a POST of the credentials to yoursite.com/api/authenticatedSession/. Where the idea would be to create an authenticated session. Most sites just POST the credentials to /api/login or the like. This is a departure from "true" or "pure" RESTful ideals, but most people find this a simpler concept rather than thinking of it as "creating an authenticated session".
Encryption
HTTPS is used to encrypt HTTP traffic between a client and server. On a system that relies on authenticated and unauthenticated users, all traffic that relies on a user being authenticated needs to be encrypted via HTTPS; there is no way around this.
The reason for this is that if you authenticate a user, share a secret with them (their session id, etc) and then begin to parade that secret in plain HTTP their session can be hijacked by man-in-the-middle attacks. A hacker will wait for for the traffic to go through an observed network and steal the secret (since its plain text over HTTP) and then initiate a connection to your server pretending to be the original client.
One way people combat this is by associating the requests remote IP address to an authenticated session. This is ineffective alone as any hacker will be able to spoof their requests remote IP address in their fake requests and then observe the responses your sever is sending back. Most would argue that this is not even worth implementing unless you are tracking historical data and using it to identify a specific user's login patterns (like Google does).
If you need to split up your site between HTTP and HTTPS sections, it is imperative that the HTTP traffic does not send or receive the session id or any token used to manage the authentication status of a user. It is also important that you do not send sensitive application data within non-HTTPs requests/responses.
The only way to secure data within web applications/APIs is to encrypt your traffic.
Your Topics One By One
Basic-Http-Auth
Authentication: YES
Session Management: NO
Encryption: NO
This is a method for authenticating by web resource only. Basic authentication authenticates uses by resource identified by URL. This was most popularly implemented by Apache HTTP Web Server with the use of .htaccess based directory/location authentication. Credentials have to be sent with each request; clients generally handled this transparently for users.
Basic authentication can be used by other systems as a mode of authentication. However, the systems that utilize Basic-Http-Auth are providing authentication and session management, not the Basic-Http-Auth itself.
This is not session management.
This is not encryption; content and credentials are nearly 100% plain text
This does not secure the contents of the application's HTTP request/responses.
Digest-Auth
Authentication: YES
Session Management: NO
Encryption: NO
This is exactly the same as Basic-Http-Auth with the addition of some simple MD5 digesting. This digesting should not be relied upon instead of using encryption.
This is not session management.
This is not encryption; the digest is easily broken
This does not secure the contents of the application's HTTP request/responses.
OAuth
Authentication: YES
Session Management: NO
Encryption: NO
OAuth just lets you have an external service validate credentials. After that it is up to you to manage/work with the result of authentication request to your OAuth provider.
This is not session management.
This is not encryption; your sites traffic is still plain text. The authentication process will be secure due to HTTPS restrictions, but your application is still vulnerable.
This does not secure the contents of the application's HTTP request/responses.
Gangster Handshake / Custom HTTP header
Authentication: YES, potentially
Session Management: YES, potentially
Encryption: NO
"Custom HTTP header" is a type of "Gangster Handshakes"; as such I will use the same section to discuss them. The only difference is that a "Custom HTTP header" is specifying where the hanshake (session id, token, user authentication toke, etc) will be stored (i.e. in a HTTP header).
It is important to note that these do not specify how authentication will be handled, nor do they specify how session management will be handled. They essentially describe how and where session ids/authentication tokens will be stored.
Authentication would need to be handled by your application or via a third party (e.g. OAuth). Session management will still need to be implemented as well. The interesting thing is you can choose the merge the two if you wish.
This is not encryption; your sites traffic is still plain text. The authentication process will be secure due to HTTPS restrictions if you use OAuth, but your application is still vulnerable.
This does not secure the contents of the application's HTTP request/responses.
What You Need To Do
...I highly suggest you make sure that you understand that a robust web application that is secure needs the following:
Encryption (HTTPS is pretty much your only choice)
Session Management
Authentication / Authorization
Authorization relies upon Authentication. Authentication relies upon Session Management and Encryption makes sure the session isn't hijacked and that the credentials are not intercepted.
Flask-Login
I think you should look into flask-login as a way to avoid re-implementing the wheel. I have personally never used it (I use pyramid for web applications in python). However, I have seen it mentioned before in web application/python boards. It handles both authentication and session management. Throw your web api/application through HTTPS and you have all three (Encryption, Session Management, and User Authentication).
If you do not / can not use flask-login, be prepared to write your own, but do research first on how to create secure authentication mechanisms.
If at all possible, if you do not understand how to write an authentication procedure please do not attempt it without first learning how hackers use pattern based attacks, timing attacks, etc.
Please Encrypt Your Traffic
...move past the idea that you can avoid using HTTPS with some "clever" token use. Move past the idea that you should avoid using HTTPS/encryption because "its slow", process intensive, etc. It is process intensive because it is an encryption algorithm. The need to ensure the safety of your user's data and your applications data should always be your highest priority. You do not want to go through the horror of notifying your users that their data was compromised.
The https it is slower, but not a not.
Only the handshaking is slower. For us the biggest problem it is to upkeep the key pair on server-mobiles side and the rights.
We have implemented a message digest too. The problem it is: is hard to set up the php-android-ios version properly. After this is done ( a parameter need to changes what is suggesting Google at first results only at android side) the problem will be with low-end devices: to much CPU usage, slow on decrypt-encrypt process, a lot slower than https, especially when you need to transform 10kb String(can take several minutes).
If I don't transfer Nasa data to Hamas, than I would go with a very simple encryption over simple HTTP: like invert the bits or so...
Go with HTTPS. It's (marginally) slower, but the security you get from it for the relatively short investment time (purchasing the SSL cert and just changing your URLs from http to https) is worth it. Without HTTPS, you run the risk of your users' sessions getting hijacked on unsecured public networks, which is extremely easy for someone to do.
We're developing a JSON REST API in Rails to be consumed by an Android application, which we are also developing. Is there any way to secure the API such that it can only be used by our specific Android application?
The API is read-only, and does not involve any kind of user-related or otherwise sensitive information. But to the extent that is reasonable we'd like to prevent abuse and restrict its use to only our app.
I could easily add an authentication token to the API and distribute it with the app, but:
We'd probably have to move the API over to SSL, if we use BASIC auth.
It's probably trivial for a determined person to open up the Android APK binary and uncover the auth token anyway.
The situation seems analogous to a café posting their WiFi password on the shop counter- you have to give the secret out to everyone who wants to use your service, so it almost seems pointless to have it in the first place.
What's the most reasonable approach to take?
Wanting to secure a probably public undocumented API so it can only be accessed by one application, means you want to stop people from using your API who are determinate of using your API.
Meaning people who would try everything possible to use your API.
If this is not the case adding a Auth token won't be trivial but at least a big stepping stone for people who stumble upon your API. And not a very bad idea to implement this.
Because this authentication isn't user based but application based and you don't want authentication to rely on user input. The request must be purely done so by the application.
Meaning you will have to do so anyway(adding hardcoded token). Only you make it very very difficult for a determined person to uncover the access and request tokens and the methods.
It depends on the situation, but I would go for the SSL and hardcoded token.
Some extra security:
Release an access token to the application which only need to send a
request token periodically. Meaning less chance people intercept the
hardcoded request token, but a session based access token which
expires. Maybe just do this once for every application install.
Encode this request token before sending it through the air. Meaning
people have to decompile your app.
Obfuscate code (make it more difficult to decompile).
Suppose you have a mobile application (Windows Phone or Android) that connects yo your back-end using SOAP.
For making it easy, let's say that we have a Web Service implemented in C#. The server exposes the following method:
[WebMethod]
public string SayHallo() { return "Hallo Client"; }
From the server perspective, you can't tell if the caller is your mobile application or a developer trying to debug your web service or a hacker trying to reverse engineer/exploit your back-end.
How can one identify that the origin of the web service call is THE application? as anyone with the WSDL can invoke the WS.
I know I can implement some standard security measures to the web service like:
Implement HTTPS on the server so messages travel encrypted and the danger of eavesdropping is reduced.
Sign the requests on the client-side using a digest/hashing algorithm, validate the signature in the server and reject the messages that have not been signed correctly.
Write custom headers in the HTTP request. Anyways headers can be simulated.
However, any well experienced hacker or a developer who knows the signing algorithm, could still generate a well signed, well, formatted message. Or a really good hacker could disassemble the application and get access to the hidden know-how of my "top secret" communications protocol.
Any ideas how to make the SayHallo() method to answer ONLY to request made from my mobile application?
We are running in the context of a mobile application, with hardware access, there could be something that can be done exploiting the hardware capabilities.
If someone wonders, I'm thinking on how to make a mobile app secure enough for sensitive applications like banking, for example.
Thanks for your ideas.
What you are describing is bi-directional authentication. It can only be done by storing a signed public key (certificate) on boths sides of the communication. Meaning that each app would need to authenticate your server with your servers public key and the server would need to authenticate each instance of your app. The app's public key would need to be produced and stored on the server at the deployment time with each instance of your app. Think of this as 2 way HTTPS, in general the only authentication that needs to be done is one direction, with the browser authenticating the server with a trusted signing key. In your case this would need to be done on both sides. Normally you would have a service like VeriSign sign each instance of a public key, this can get quite spendy with multiple deployments of an app. In your case you could just create an in house signing application using something like OPENSSL to sign your app every time it is distributed. This does not mean that someone still could not hack your code and extract the signing key on the app side. In general any code can be hacked, it's just a question of how hard can you make it before they give up? If you were to go the custom hardware route, there are things such as crypto chips and TMP's that can serve as a key sotre and make it harder for people to gain access to the private keys on the device.
A quick google search turned up the following:
http://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication
If you are thinking about using rewards points, and are really worried about someone gaming the system from the outside a better solution is to have each person make an account that is stored securely on the server and their points are saved and tallied there. This centralizes all the data and allows you complete control over it with out worrying about a malicious app reporting non-existent points. (this is how banks work)
If you want to verify that a user is both mobile and who they say they are then the best way is to leverage the network. Send a push notification with the hashed key that you want the user to use via:
APN for iOS
something like urban airship for windows phone
GCM for Android.
In general, the model looks like:
Server authenticates itself to the many clients with a certified public key (this is the whole Public Key Infrastructure, Certificate Authorities, etc)
Each client identifies itself to the server via some other authentication system (in 99.9% of cases, this is a password)
So if you're wondering how this sort of thing works in the case of banking apps, etc that's basically how it breaks down: (1) Client and server establish a secure channel such as a shared secret key, using the server's public key, (2) Client authenticates via this secure channel using some other mechanism.
Your question specifically, however, seems more aimed at the app authenticating itself (i.e., any request from your app is authentic) with the thought that if only your app can be authenticated, and your app is well-behaved, then everything should be safe. This has a few implications:
This implies that every user of your app is trusted. In security terms, they are part of your "trusted computing base".
Attempting to achieve this sort of goal WITHOUT considering the user/user's computing platform as trusted is essentially the goal of DRM; and while it's good enough to save money for music publishers, it's nowhere close to good enough for something really sensitive.
In general:
The problem that you're specifically looking at is VERY hard to solve, if you're looking for very strong security properties.
You likely don't need to solve that problem.
If you give us some more context, we might be able to give you more specific advice.
In addition to the answers already given, how about using a login type scheme with the unique id of the phone and a password? Get the user to register with your "back-end" and every time a transaction has to be made with the back-end, require the password or have an option to automatically log in.
You can use the following way to secure and to track your requests to server.
You can force the mobile or web clients to send you a Custom Headers of the device type when accessing your webservice through REST methods
Use basic http authentication by forcing each client to have their own username and passwords provided by you as a authorized webservice provider..
If you need more advanced protection you can use OAuth 2.0 to secure your webservice.
Since your originating app is going to be Android or Windows Phone apps, either one of them will be relatively easy for the wanna be hacker to debug. in any case you're going to be running the code on a machine that you have no control over so no ssl tricks or checking signing will solve your fundamental problem.
the only way you can combat threat from it is to NOT TRUST THE CLIENT. verify that the input coming from the clients is valid before acting on it if you're making a game - that it's accompanied by a valid security token etc.
in essence build your service so that it doesn't matter if the user is using an unofficial client.