Skip to content

Commit

Permalink
Deprecate old security options in favor of new CORS support
Browse files Browse the repository at this point in the history
  • Loading branch information
dcramer committed May 1, 2012
1 parent f23a501 commit 9041ebf
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 461 deletions.
47 changes: 4 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,10 @@
This is an experimental JavaScript client for the [Sentry][1] realtime event
logging and aggregation platform.

The full and minified distribution files include code from two other
open-source projects:

* base64_encode from [php.js][2] (included in the minified distribution)
* crypto-sha1-hmac from [Crypto-JS][3] (included in minified distribution)

The stacktrace generation was inspired by the [javascript-stacktrace][4]
project, and includes heavily modified portions of that project's code.

[1]: http://getsentry.com/
[2]: http://phpjs.org/
[3]: http://code.google.com/p/crypto-js/
[4]: https://github.com/eriwen/javascript-stacktrace


Expand All @@ -40,18 +32,12 @@ minified distribution file from the 'dist' directory:
Configure the client like this:

Raven.config({
"secretKey": "77ec8c99a8854256aa68ccb91dd9119d",
"publicKey": "e89652ec30b94d9db6ea6f28580ab499",
"servers": ["http://your.sentryserver.com/api/store/"],
"projectId": 1,
"logger": "yoursite.errors.javascript"
});

**secretKey** - If you're using project auth, this should be the desired user's
secret key. Otherwise, this should be the global superuser key. If you are
using the `signatureUrl` option below, then you should omit this from your
config.

**publicKey** - This is only needed if you're using project auth, and it should
be the desired user's public key.

Expand Down Expand Up @@ -93,36 +79,11 @@ those cases it will simply do nothing.

## Security

The `Raven.config` method above is insecure because it reveals the secretKey.

### Server-side Signing

One way to work around this is to send the message to the server for signing.
Use the `signatureUrl` configuration option to provide a url to use to obtain a
signature. Raven.js will send a POST request to the url containing a "message",
with the base64 encoded message, and a "timestamp". The server-side code should
then use the secret key to sign the request using a SHA1-signed HMAC.

To generate the HMAC signature, take the following example (in Python):

hmac.new(SENTRY_KEY, '%s %s' % (timestamp, message), hashlib.sha1).hexdigest()

The response should be a JSON string containing a "signature" key with the
generated signature:

{"signature": "4799ab65ff3052aa8768987d918014c6d40f75d0"}

### Simple Obfuscation

If you would just like to obfuscate this somewhat, you can pass the options to
the `config` method as a base64 encoded JSON string:

Raven.config("eyJzZWNyZXRLZXkiOiAiNzdlYzhjOTlhODg1NDI1NmFhNjhjY2I5MWRkOTExOWQiLCAicHVibGljS2V5IjogImU4OTY1MmVjMzBiOTRkOWRiNmVhNmYyODU4MGFiNDk5IiwgInNlcnZlcnMiOiBbImh0dHA6Ly95b3VyLnNlbnRyeXNlcnZlci5jb20vYXBpL3N0b3JlLyJdLCAicHJvamVjdElkIjogMSwgImxvZ2dlciI6ICJ5b3Vyc2l0ZS5lcnJvcnMuamF2YXNjcmlwdCJ9");

This is still insecure, but it is less obvious than calling it with plain text
options.
Raven requires you to set up the CORS headers within Sentry. These headers should include
the base URI of which you plan to send events from.

More security options will be forthcoming.
For example, if you are using raven-js on http://example.com, you should list <code>http://example.com</code>
in your origins configuration. If you only wanted to allow events from /foo, set the value to <code>http://example.com/foo</code>.

## Support

Expand Down
18 changes: 5 additions & 13 deletions src/raven.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
//
// Requires:
// * Either jQuery (>1.5) or Zepto.js.
// * base64_encode/decode from php.js (included in the vendor folder)
// * crypto-sha1-hmac from Crypto-JS (included in the vendor folder)

(function(){
// Save a reference to the global object (`window` in the browser, `global`
Expand All @@ -22,9 +20,6 @@
// jQuery, Zepto, or Ender owns the `$` variable.
var $ = root.jQuery || root.Zepto || root.ender;

// php.js owns $P, for base64 encoding
var $P = new PHP_JS();

Raven.loaded = false;
Raven.options = {
secretKey: undefined, // The global key if not using project auth
Expand All @@ -41,9 +36,6 @@
Raven.funcNameRE = /function\s*([\w\-$]+)?\s*\(/i;

Raven.config = function(config) {
if (typeof(config) === "string") {
config = JSON.parse($P.base64_decode(config));
}
$.each(config, function(i, option) {
self.options[i] = option;
});
Expand Down Expand Up @@ -84,20 +76,20 @@
callback(data.signature);
});
} else {
var signature = Crypto.HMAC(Crypto.SHA1, timestamp + " " + message,
self.options.secretKey);
callback(signature);
callback();
}
};

Raven.getAuthHeader = function(signature, timestamp) {
var header = "Sentry sentry_version=2.0, ";
header += "sentry_timestamp=" + timestamp + ", ";
header += "sentry_signature=" + signature + ", ";
header += "sentry_client=raven-js/" + self.VERSION;
if (self.options.publicKey) {
header += ", sentry_key=" + self.options.publicKey;
}
if (signature) {
header += ", sentry_signature=" + signature;
}
return header;
};

Expand Down Expand Up @@ -346,7 +338,7 @@
}

timestamp = timestamp || (new Date()).getTime();
encoded_msg = $P.base64_encode(JSON.stringify(data));
encoded_msg = JSON.stringify(data);
self.getSignature(encoded_msg, timestamp, function(signature) {
$.each(self.options.servers, function (i, server) {
$.ajax({
Expand Down
Loading

0 comments on commit 9041ebf

Please sign in to comment.