Rails XML API design practices - ruby-on-rails

I'm building an XML-based webservice in Rails to serve as the backend for an iPhone app, and I'm wondering how I can best achieve an auth scheme that will let me use both GET and POST requests -- i.e. one that doesn't require auth sent in the body of an XML payload.
The wrinkle here is that I'm not using regular HTTP auth. Instead, I'm creating a SHA1 digest of the iPhone's hardware ID (concatenated w/ a "secret" string pre-digest) along with the unhashed ID. I validate it on the server by attempting to re-create the digest w/ the hardware ID from the request and matching it against the hashed hardware ID from the request.
My question is this: should I create my service so that every action on every resource expects a payload of POSTed XML containing the security context in a common XML structure, or is there a better way to do it?
In other words, I'd like to use GET for things like /show, /index, etc. But as my app currently stands, I can't do that, since I need to send an XML payload containing the security context.
Perhaps there's a good way to achieve effectively the same thing with headers a la Google's web API's?
Every security context looks like this:
<request-wrapper>
<security-context>
<username>joefoo</username>
<hardware-id>AE7D128BCA9206E59901</hardware-id>
<hashed-hardware-id>cfd7983850301f97f6fdc26b553d1b6170f18bde</hashed-hardware-id>
</security-context>
...
(remainder of request payload)
...
</request-wrapper>
This is my first XML service in Rails, so I'd appreciate any general practice advice in this vein as well.
Thanks!

Your authentication scheme is subject to replay attacks if the "secret string" stays the same over the lifetime of the device.
Additionally, the "secret key" (if it is embedded in your application) can be dumped via strings (or other tool) breaking your scheme entirely.
I would instead use an asymmetric key to setup a one-time secret key, and then use it to hash a counter or something. If you need the hardware id for some reason, hash it plus the counter. This is basically a dumbed down SSL implementation, so you might as well just do that frankly (generating your own certificate, and doing the rare mutual authentication; but still...).
Remember, inventing your own security scheme is almost always a bad idea.

I'm thinking that it might be best to simply use custom headers for this and then access them in my controller filters w/ things like:
request.headers['username']
request.headers['hardware-id']
request.headers['hashedhardware-id']
Any thoughts on whether this is a good/bad idea?

How about creating an SHA1 digest of the entire XML request, instead of just the hardware-id? That way you're making replay attacks a lot harder. Sure, without a timestamp and (possibly) a nonce to make each request unique, a hacker could still replay the exact same request multiple times (maybe using up account credits or whatever), but at least they couldn't take the digest from an existing request and change the request details to make it do whatever they wanted.
Suggested steps:
Take your XML (without any hashed-hardware-id in it) and turn it into a byte array.
Create an SHA1 digest of the XML byte array.
Base-64 encode the XML byte array and the SHA1 digest byte array (separately).
Send the base-64-encoded XML as one request parameter, and the base-64-encoded signature as the other, either using GET or POST.

Related

Where should I store my API key in IOS app [duplicate]

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.
I'm thinking about a simple solution like:
let secret = "abc123"
But are there going to be any downfalls to this?
Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.
It will be broken almost immediately, but so will all the other solutions. So keep it simple.
The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.
It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.
By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).
There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.
Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.
There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.
(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)
While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.
Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.
Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.
In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.
It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.
I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters.
Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP.
In my opinion this is about as secure as using Environment variables in Ruby or similar.
PFConfig.getConfigInBackgroundWithBlock{
(config: PFConfig?, error: NSError?) -> Void in
if error == nil {
if let mySecret = config["mySecret"] as? String {
// myFunction(mySecret)
}
}

Swift protect hard coded string for privacy [duplicate]

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.
I'm thinking about a simple solution like:
let secret = "abc123"
But are there going to be any downfalls to this?
Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.
It will be broken almost immediately, but so will all the other solutions. So keep it simple.
The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.
It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.
By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).
There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.
Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.
There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.
(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)
While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.
Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.
Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.
In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.
It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.
I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters.
Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP.
In my opinion this is about as secure as using Environment variables in Ruby or similar.
PFConfig.getConfigInBackgroundWithBlock{
(config: PFConfig?, error: NSError?) -> Void in
if error == nil {
if let mySecret = config["mySecret"] as? String {
// myFunction(mySecret)
}
}

Restrict GET route in Rails 4 to app only

We have a JSON hash that the backend processes and serves to our frontend to calculate a map. The JSON hash is rendered from a GET request and is constantly being updated (not cached).
We need a way to lock down the route so that only the app itself can connect to it (stopping bots from pinging the URL to grab the hash). The frontend and backend are tied together in one Rails application (no separate services).
My issue is that ActionController::RequestForgeryProtection::ClassMethods does not support GET and ActionController::HttpAuthentication::Token is overkill since I need to restrict the JSON hash to the app (not to a specific user). Request.referrer can be spoofed so I hesitate in checking that.
I would appreciate any suggestions on how to reject outside GET requests to a Controller when it is not the app making the request.
Rails: 4.2.6
You won't be able to prevent arbitrary programs (ie: "user agents") from making HTTP requests against your server. You can, however, refuse to respond with useful content unless the user agent can prove that it's your app.
What you want to do is cryptographically sign your requests in your client app, then verify the signature on your server before responding. I don't know of any Ruby/Rails library to do precisely that (and I couldn't find any upon a cursory search), but it could be built from existing libraries. Here's a quick and dirty implementation concept:
Embed a secret key into the client app.
Whenever the client app makes a request, it:
Generates a UUID that will be used exactly once, ever. (A "nonce").
Generate a signiture by hashing the nonce with the secret key.
Pass the nonce and the signature with the request (probably as HTTP headers)
When the server receives a request, it generates a signature based on the incoming nonce and the secret key (which it already knows). If the signature matches, and the nonce has never been used before, then the server returns the content. If either of those conditions are not true, then the server can't guarantee that it's your client app making the request, and thus should respond with a failure.
Disclaimers:
This is entirely dependent on the security of the secret key embedded in the client app. If the key is hacked (and it will be, given enough effort on the part of the attacker), then this scheme falls apart.
If you use the same secret key for all client apps (and there's a good chance you'll need to, depending on your app architecture), then if one client app install gets hacked, you lose security on all of your installations.
This is just an illustration of the general principle, not a fully fledged secure implementation. I'm not a security expert and have not run through all of the potential attack vectors for this plan.
I also suggest reading up on how OAuth works. It solves a similar problem, and you may be able to adapt it for your purposes.

In iOS, how can I store a secret "key" that will allow me to communicate with my server?

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.
I'm thinking about a simple solution like:
let secret = "abc123"
But are there going to be any downfalls to this?
Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.
It will be broken almost immediately, but so will all the other solutions. So keep it simple.
The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.
It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.
By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).
There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.
Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.
There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.
(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)
While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.
Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.
Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.
In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.
It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.
I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters.
Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP.
In my opinion this is about as secure as using Environment variables in Ruby or similar.
PFConfig.getConfigInBackgroundWithBlock{
(config: PFConfig?, error: NSError?) -> Void in
if error == nil {
if let mySecret = config["mySecret"] as? String {
// myFunction(mySecret)
}
}

Implementing a 2 Legged OAuth Provider

I'm trying to find my way around the OAuth spec, its requirements and any implementations I can find and, so far, it really seems like more trouble than its worth because I'm having trouble finding a single resource that pulls it all together. Or maybe it's just that I'm looking for something more specialized than most tutorials.
I have a set of existing APIs--some in Java, some in PHP--that I now need to secure and, for a number of reasons, OAuth seems like the right way to go. Unfortunately, my inability to track down the right resources to help me get a provider up and running is challenging that theory. Since most of this will be system-to-system API usage, I'll need to implement a 2-legged provider. With that in mind...
Does anyone know of any good tutorials for implementing a 2-legged OAuth provider with PHP?
Given that I have securable APIs in 2 languages, do I need to implement a provider in both or is there a way to create the provider as a "front controller" that I can funnel all requests through?
When securing PHP services, for example, do I have to secure each API individually by including the requisite provider resources on each?
Thanks for your help.
Rob, not sure where you landed on this but wanted to add my 2 cents in case anyone else ran across this question.
I more or less had the same question a few months ago and hearing about "OAuth" for the better part of a year. I was developing a REST API I needed to secure so I started reading about OAuth... and then my eyes started to roll backwards in my head.
I probably gave it a good solid day or 2 of skimming and reading until I decided, much like you, that OAuth was confusing garbage and just gave up on it.
So then I started researching ways to secure APIs in general and started to get a better grasp on ways to do that. The most popular way seemed to be sending requests to the API along with a checksum of the entire message (encoded with a secret that only you and the server know) that the server can use to decide if the message had been tampered with on it's way from the client, like so:
Client sends /user.json/123?showFriends=true&showStats=true&checksum=kjDSiuas98SD987ad
Server gets all that, looks up user "123" in database, loads his secret key and then (using the same method the client used) re-calculates it's OWN checksum given the request arguments.
If the server's generated checksum and the client's sent checksum match up, the request is OK and executed, if not, it is considered tampered with and rejected.
The checksum is called an HMAC and if you want a good example of this, it is what Amazon Web Services uses (they call the argument 'signature' not 'checksum' though).
So given that one of the key components of this to work is that the client and server have to generate the HMAC in the same fashion (otherwise they won't match), there have to be rules on HOW to combine all the arguments... then I suddenly understood all that "natural byte-ordering of parameters" crap from OAuth... it was just defining the rules for how to generate the signature because it needed to.
Another point is that every param you include in the HMAC generation is a value that then can't be tampered with when you send the request.
So if you just encode the URI stem as the signature, for example:
/user.json == askJdla9/kjdas+Askj2l8add
then the only thing in your message that cannot be tampered with is the URI, all of the arguments can be tampered with because they aren't part of the "checksum" value that the server will re-calculate.
Alternatively, even if you include EVERY param in the calculation, you still run the risk of "replay attacks" where a malicious middle man or evesdropped can intercept an API call and just keep resending it to the server over and over again.
You can fix that by adding a timestamp (always use UTC) in the HMAC calculation as well.
REMINDER: Since the server needs to calculate the same HMAC, you have to send along any value you use in the calculation EXCEPT YOUR SECRET KEY (OAuth calls it a consumer_secret I think). So if you add timestamp, make sure you send a timestamp param along with your request.
If you want to make the API secure from replay attacks, you can use a nonce value (it's a 1-time use value the server generates, gives to the client, the client uses it in the HMAC, sends back the request, the server confirms and then marks that nonce value as "used" in the DB and never lets another request use it again).
NOTE: 'nonce' are a really exact way to solve the "replay attack" problem -- timestamps are great, but because computers don't always have in-sync timestamp values, you have to allow an acceptable window on the server side of how "old" a request might be (say 10 mins, 30 mins, 1hr.... Amazon uses 15mins) before we accept or reject it. In this scenario your API is technically vulnerable during the entire window of time.
I think nonce values are great, but should only need to be used in APIs that are critical they keep their integrity. In my API, I didn't need it, but it would be trivial to add later if users demanded it... I would literally just need to add a "nonce" table in my DB, expose a new API to clients like:
/nonce.json
and then when they send that back to me in the HMAC calculation, I would need to check the DB to make sure it had never been used before and once used, mark it as such in the DB so if a request EVER came in again with that same nonce I would reject it.
Summary
Anyway, to make a long story short, everything I just described is basically what is known as "2-legged OAuth". There isn't that added step of flowing to the authority (Twitter, Facebook, Google, whatever) to authorize the client, that step is removed and instead the server implicitly trusts the client IF the HMAC's they are sending match up. That means the client has the right secret_key and is signing it's messages with it, so the server trusts it.
If you start looking around online, this seems to be the preferred method for securing API methods now-adays, or something like it. Amazon almost exactly uses this method except they use a slightly different combination method for their parameters before signing the whole thing to generate the HMAC.
If you are interested I wrote up this entire journey and thought-process as I was learning it. That might help provide a guided thinking tour of this process.
I would take a step back and think about what a properly authenticated client is going to be sending you.
Can you store the keys and credentials in a common database which is accessible from both sets of services, and just implement the OAuth provider in one language? When the user sends in a request to a service (PHP or Java) you then check against the common store. When the user is setting up the OAuth client then you do all of that through either a PHP or Java app (your preference), and store the credentials in the common DB.
There are some Oauth providers written in other languages that you might want to take a look at:
PHP - http://term.ie/oauth/example/ (see bottom of page)
Ruby - http://github.com/mojodna/sample-oauth-provider
.NET http://blog.bittercoder.com/PermaLink,guid,0d080a15-b412-48cf-b0d4-e842b25e3813.aspx

Resources