Skip to content

Add allowPrivateKey config option #525

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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