Message Boards Message Boards

13
|
22054 Views
|
6 Replies
|
26 Total Likes
View groups...
Share
Share this post:

Single-Origin Authentication for Cloud APIs

Posted 10 years ago

While watching the Wolfram Language in the Cloud presentation, the subject of authentication came up. While the Programming Cloud supposedly does support OAuth for APIs, that seems a little over-the-top if you're just accessing it from one app. While application auth tokens are coming in the future, I developed a simple solution and thought I'd share it.

I have this incredibly useful and worthwhile Instant API:

api = APIFunction[{"text" -> "String", "auth" -> "String"},
   If[#auth == "MySuperSecretAndSecureAccessKey", 
     Return["You said: " <> #text], Return["Access denied!"]] &];

If I go to https://www.wolframcloud.com/objects/43fcc0c4-d4d1-4bc8-952b-e33360dc830b?text=Hi!&auth=MySuperSecretAndSecureAccessKey my text is echoed back to me. And if I use an incorrect key, it refuses to cooperate.

Foolproof, right?

Wrong.

If I eliminate the arguments from the URL, I get this error page: API Web Error Report

And inside the JSON object-

Traceback

-this traceback. Which is nice, except for the fact that it has my key.

So how do we fix this?

Many websites require username-password authentication. It is standard practice not to store the password in plaintext, but to calculate a hash and check logins against it.

I can get the hash of a string in the Wolfram Language with Hash[]:

In[1]:= Hash["MySuperSecretAndSecureAccessKey"]
Out[1]= 5806601739209730667

I can modify my function to use that hash, like so:

api = APIFunction[{"text" -> "String", "auth" -> "String"},
   If[Hash[#auth] == 5806601739209730667, 
     Return["You said: " <> #text], Return["Access denied!"]] &];

The API still works, and no modifications to the parameters are required. If I invoke the name error, all the recipient gets is my hash, which is almost completely useless.

Error report with hash authentication

Enjoy your newly secured Cloud API!

POSTED BY: Jesse Friedman
6 Replies

Interesting, but now I believe that PermissionsKey is the best way to do that.

obj= CloudDeploy[APIFunction[{"n"->Integer},#n^2&],Permissions->{PermissionsKey["thekey"]->"Execute"}]
URLExecute[obj, {"n" -> 123, "_key" -> "thekey"}]

Tutorial: https://reference.wolfram.com/language/workflow/DeployAnAPIThatUsesAPermissionsKey.html

POSTED BY: Rodrigo Murta

Cryptographic hash functions are designed to be irreversible, or at least extremely hard to reverse. For all intents and purposes, with a good hash algorithm it is virtually impossible to calculate an input that hashes to a desired output. However, some hash functions such as MD5 have been compromised, and are now considered insecure, due to the relative simplicity of finding hash "collisions", multiple inputs that hash to the same output.

POSTED BY: Jesse Friedman

But would not that expose the secret key in the hash?

POSTED BY: Hristo Vrigazov

Very interesting stuff here. I bet you could create some simple formulas for dynamic salt keys that would be too hard to guess. Maybe something like today's date squared minus yesterday's date. As long as both sides know the simple dynamic salt key generator formula, it would good enough to stop all but NSA abuse. lol

POSTED BY: David Johnston
POSTED BY: David Reiss
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract