Skip to content

Commit 17e62be

Browse files
committed
Add allowPrivateKey config option
1 parent 40762d9 commit 17e62be

File tree

3 files changed

+94
-11
lines changed

3 files changed

+94
-11
lines changed

docs/config.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,15 @@ Those configuration options are documented below:
215215
onFailure
216216
Callback to be invoked upon a failed request.
217217

218+
.. describe:: allowPrivateKey
219+
220+
By default, Raven.js will throw an error if configured with a Sentry DSN that contains a private key.
221+
When using Raven.js with a web application accessed via a browser over the web, you should
222+
only use your public DSN. But if you are using Raven.js in an environment like React Native or Electron,
223+
where your application is running "natively" on a device and not accessed at a web address, you may need
224+
to use your private DSN string. To do so, set ``allowPrivateKey: true`` during configuration.
225+
226+
218227
Putting it all together
219228
-----------------------
220229

src/raven.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,6 @@ Raven.prototype = {
9797
}
9898
if (!dsn) return this;
9999

100-
var uri = this._parseDSN(dsn),
101-
lastSlash = uri.path.lastIndexOf('/'),
102-
path = uri.path.substr(1, lastSlash);
103-
104100
// merge in options
105101
if (options) {
106102
each(options, function(key, value){
@@ -113,6 +109,10 @@ Raven.prototype = {
113109
});
114110
}
115111

112+
var uri = this._parseDSN(dsn),
113+
lastSlash = uri.path.lastIndexOf('/'),
114+
path = uri.path.substr(1, lastSlash);
115+
116116
this._dsn = dsn;
117117

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

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

132133
this._globalServer = this._getGlobalServer(uri);
@@ -725,8 +726,10 @@ Raven.prototype = {
725726
throw new RavenConfigError('Invalid DSN: ' + str);
726727
}
727728

728-
if (dsn.pass)
729-
throw new RavenConfigError('Do not specify your private key in the DSN!');
729+
if (dsn.pass && !this._globalOptions.allowPrivateKey) {
730+
console.dir(this._globalOptions.allowPrivateKey)
731+
throw new RavenConfigError('Do not specify your private key in the DSN. See: http://bit.ly/raven-private-key');
732+
}
730733

731734
return dsn;
732735
},
@@ -990,14 +993,19 @@ Raven.prototype = {
990993

991994
if (!this.isSetup()) return;
992995

996+
var auth = {
997+
sentry_version: '7',
998+
sentry_client: 'raven-js/' + this.VERSION,
999+
sentry_key: this._globalKey
1000+
};
1001+
if (this._globalSecret) {
1002+
auth.sentry_secret = this._globalSecret;
1003+
}
1004+
9931005
var url = this._globalEndpoint;
9941006
(globalOptions.transport || this._makeRequest).call(this, {
9951007
url: url,
996-
auth: {
997-
sentry_version: '7',
998-
sentry_client: 'raven-js/' + this.VERSION,
999-
sentry_key: this._globalKey
1000-
},
1008+
auth: auth,
10011009
data: data,
10021010
options: globalOptions,
10031011
onSuccess: function success() {

test/raven.test.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,51 @@ describe('globals', function() {
10471047
assert.isFunction(opts.onError);
10481048
});
10491049

1050+
it('should pass sentry_secret as part of auth params if specified', function () {
1051+
this.sinon.stub(Raven, 'isSetup').returns(true);
1052+
this.sinon.stub(Raven, '_makeRequest');
1053+
this.sinon.stub(Raven, '_getHttpData').returns({
1054+
url: 'http://localhost/?a=b',
1055+
headers: {'User-Agent': 'lolbrowser'}
1056+
});
1057+
1058+
Raven._globalEndpoint = 'http://localhost/store/';
1059+
Raven._globalOptions = {
1060+
projectId: 2,
1061+
logger: 'javascript',
1062+
maxMessageLength: 100,
1063+
release: 'abc123'
1064+
};;
1065+
Raven._globalSecret = 'def'; // <-- secret
1066+
1067+
Raven._send({message: 'bar'});
1068+
var args = Raven._makeRequest.lastCall.args;
1069+
assert.equal(args.length, 1);
1070+
var opts = args[0];
1071+
assert.equal(opts.url, 'http://localhost/store/');
1072+
assert.deepEqual(opts.data, {
1073+
project: '2',
1074+
release: 'abc123',
1075+
logger: 'javascript',
1076+
platform: 'javascript',
1077+
request: {
1078+
url: 'http://localhost/?a=b',
1079+
headers: {
1080+
'User-Agent': 'lolbrowser'
1081+
}
1082+
},
1083+
event_id: 'abc123',
1084+
message: 'bar',
1085+
extra: {'session:duration': 100},
1086+
});
1087+
assert.deepEqual(opts.auth, {
1088+
sentry_client: 'raven-js/2.1.0',
1089+
sentry_key: 'abc',
1090+
sentry_secret: 'def',
1091+
sentry_version: '7'
1092+
});
1093+
});
1094+
10501095
it('should call globalOptions.transport if specified', function() {
10511096
this.sinon.stub(Raven, 'isSetup').returns(true);
10521097
this.sinon.stub(Raven, '_getHttpData').returns({
@@ -1528,12 +1573,33 @@ describe('Raven (public API)', function() {
15281573
assert.equal(Raven, Raven.config(SENTRY_DSN, {foo: 'bar'}), 'it should return Raven');
15291574

15301575
assert.equal(Raven._globalKey, 'abc');
1576+
assert.equal(Raven._globalSecret, '');
15311577
assert.equal(Raven._globalEndpoint, 'http://example.com:80/api/2/store/');
15321578
assert.equal(Raven._globalOptions.foo, 'bar');
15331579
assert.equal(Raven._globalProject, '2');
15341580
assert.isTrue(Raven.isSetup());
15351581
});
15361582

1583+
it('throw an Error if the DSN contains a private/secret key', function () {
1584+
assert.throws(function () {
1585+
Raven.config('http://abc:[email protected]:80/2');
1586+
}, Error);
1587+
});
1588+
1589+
it('will NOT throw an Error if the DSN contains a private/secret key AND allowPrivateKey is true', function () {
1590+
assert.equal(
1591+
Raven,
1592+
Raven.config('http://abc:[email protected]:80/2', {allowPrivateKey: true}),
1593+
'it should return Raven'
1594+
);
1595+
1596+
assert.equal(Raven._globalKey, 'abc');
1597+
assert.equal(Raven._globalSecret, 'def');
1598+
assert.equal(Raven._globalEndpoint, 'http://example.com:80/api/2/store/');
1599+
assert.equal(Raven._globalProject, '2');
1600+
assert.isTrue(Raven.isSetup());
1601+
});
1602+
15371603
it('should work with a protocol relative DSN', function() {
15381604
Raven.config('//[email protected]/2');
15391605

0 commit comments

Comments
 (0)