Skip to content

Commit

Permalink
Add allowPrivateKey config option
Browse files Browse the repository at this point in the history
  • Loading branch information
benvinegar committed Mar 3, 2016
1 parent 40762d9 commit 184398e
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 11 deletions.
9 changes: 9 additions & 0 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,15 @@ Those configuration options are documented below:
onFailure
Callback to be invoked upon a failed request.

.. describe:: allowSecretKey

By default, Raven.js will throw an error if configured with a Sentry DSN that contains a secret key.
When using Raven.js with a web application accessed via a browser over the web, you should
only use your public DSN. But if you are using Raven.js in an environment like React Native or Electron,
where your application is running "natively" on a device and not accessed at a web address, you may need
to use your secret DSN string. To do so, set ``allowPrivateKey: true`` during configuration.


Putting it all together
-----------------------

Expand Down
29 changes: 18 additions & 11 deletions src/raven.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,6 @@ Raven.prototype = {
}
if (!dsn) return this;

var uri = this._parseDSN(dsn),
lastSlash = uri.path.lastIndexOf('/'),
path = uri.path.substr(1, lastSlash);

// merge in options
if (options) {
each(options, function(key, value){
Expand All @@ -113,6 +109,10 @@ Raven.prototype = {
});
}

var uri = this._parseDSN(dsn),
lastSlash = uri.path.lastIndexOf('/'),
path = uri.path.substr(1, lastSlash);

this._dsn = dsn;

// "Script error." is hard coded into browsers for errors that it can't read.
Expand All @@ -127,6 +127,7 @@ Raven.prototype = {
this._globalOptions.includePaths = joinRegExp(this._globalOptions.includePaths);

this._globalKey = uri.user;
this._globalSecret = uri.pass && uri.pass.substr(1);
this._globalProject = uri.path.substr(lastSlash + 1);

this._globalServer = this._getGlobalServer(uri);
Expand Down Expand Up @@ -725,8 +726,9 @@ Raven.prototype = {
throw new RavenConfigError('Invalid DSN: ' + str);
}

if (dsn.pass)
throw new RavenConfigError('Do not specify your private key in the DSN!');
if (dsn.pass && !this._globalOptions.allowSecretKey) {
throw new RavenConfigError('Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key');
}

return dsn;
},
Expand Down Expand Up @@ -990,14 +992,19 @@ Raven.prototype = {

if (!this.isSetup()) return;

var auth = {
sentry_version: '7',
sentry_client: 'raven-js/' + this.VERSION,
sentry_key: this._globalKey
};
if (this._globalSecret) {
auth.sentry_secret = this._globalSecret;
}

var url = this._globalEndpoint;
(globalOptions.transport || this._makeRequest).call(this, {
url: url,
auth: {
sentry_version: '7',
sentry_client: 'raven-js/' + this.VERSION,
sentry_key: this._globalKey
},
auth: auth,
data: data,
options: globalOptions,
onSuccess: function success() {
Expand Down
66 changes: 66 additions & 0 deletions test/raven.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,51 @@ describe('globals', function() {
assert.isFunction(opts.onError);
});

it('should pass sentry_secret as part of auth params if specified', function () {
this.sinon.stub(Raven, 'isSetup').returns(true);
this.sinon.stub(Raven, '_makeRequest');
this.sinon.stub(Raven, '_getHttpData').returns({
url: 'http://localhost/?a=b',
headers: {'User-Agent': 'lolbrowser'}
});

Raven._globalEndpoint = 'http://localhost/store/';
Raven._globalOptions = {
projectId: 2,
logger: 'javascript',
maxMessageLength: 100,
release: 'abc123'
};;
Raven._globalSecret = 'def'; // <-- secret

Raven._send({message: 'bar'});
var args = Raven._makeRequest.lastCall.args;
assert.equal(args.length, 1);
var opts = args[0];
assert.equal(opts.url, 'http://localhost/store/');
assert.deepEqual(opts.data, {
project: '2',
release: 'abc123',
logger: 'javascript',
platform: 'javascript',
request: {
url: 'http://localhost/?a=b',
headers: {
'User-Agent': 'lolbrowser'
}
},
event_id: 'abc123',
message: 'bar',
extra: {'session:duration': 100},
});
assert.deepEqual(opts.auth, {
sentry_client: 'raven-js/2.1.0',
sentry_key: 'abc',
sentry_secret: 'def',
sentry_version: '7'
});
});

it('should call globalOptions.transport if specified', function() {
this.sinon.stub(Raven, 'isSetup').returns(true);
this.sinon.stub(Raven, '_getHttpData').returns({
Expand Down Expand Up @@ -1528,12 +1573,33 @@ describe('Raven (public API)', function() {
assert.equal(Raven, Raven.config(SENTRY_DSN, {foo: 'bar'}), 'it should return Raven');

assert.equal(Raven._globalKey, 'abc');
assert.equal(Raven._globalSecret, '');
assert.equal(Raven._globalEndpoint, 'http://example.com:80/api/2/store/');
assert.equal(Raven._globalOptions.foo, 'bar');
assert.equal(Raven._globalProject, '2');
assert.isTrue(Raven.isSetup());
});

it('throw an Error if the DSN contains a private/secret key', function () {
assert.throws(function () {
Raven.config('http://abc:def@example.com:80/2');
}, Error);
});

it('will NOT throw an Error if the DSN contains a private/secret key AND allowSecretKey is true', function () {
assert.equal(
Raven,
Raven.config('http://abc:def@example.com:80/2', {allowSecretKey: true}),
'it should return Raven'
);

assert.equal(Raven._globalKey, 'abc');
assert.equal(Raven._globalSecret, 'def');
assert.equal(Raven._globalEndpoint, 'http://example.com:80/api/2/store/');
assert.equal(Raven._globalProject, '2');
assert.isTrue(Raven.isSetup());
});

it('should work with a protocol relative DSN', function() {
Raven.config('//abc@example.com/2');

Expand Down

0 comments on commit 184398e

Please sign in to comment.