diff --git a/lib/jwt/AccessToken.d.ts b/lib/jwt/AccessToken.d.ts index 1de3563276..00987dbd2a 100644 --- a/lib/jwt/AccessToken.d.ts +++ b/lib/jwt/AccessToken.d.ts @@ -158,6 +158,10 @@ declare namespace AccessToken { * Time from epoch in seconds for not before value */ nbf?: number; + /** + * The region value associated with this account + */ + region?: string; } } diff --git a/lib/jwt/AccessToken.js b/lib/jwt/AccessToken.js index cf1e99e974..b1fadb52fa 100644 --- a/lib/jwt/AccessToken.js +++ b/lib/jwt/AccessToken.js @@ -208,6 +208,7 @@ _.extend(VoiceGrant.prototype, { * @param {number} [options.ttl=3600] - Time to live in seconds * @param {string} [options.identity] - The identity of the first person * @param {number} [options.nbf] - Time from epoch in seconds for not before value + * @param {string} [options.region] - The region value associated with this account */ function AccessToken(accountSid, keySid, secret, options) { if (!accountSid) { throw new Error('accountSid is required'); } @@ -221,6 +222,7 @@ function AccessToken(accountSid, keySid, secret, options) { this.ttl = options.ttl || 3600; this.identity = options.identity; this.nbf = options.nbf; + this.region = options.region; this.grants = []; } @@ -264,11 +266,17 @@ _.extend(AccessToken.prototype, { }; if (_.isNumber(this.nbf)) { payload.nbf = this.nbf; } + var header = { + cty: 'twilio-fpa;v=1', + typ: 'JWT' + }; + + if (this.region && _.isString(this.region)) { + header.twr = this.region; + } + return jwt.sign(payload, this.secret, { - header: { - cty: 'twilio-fpa;v=1', - typ: 'JWT' - }, + header: header, algorithm: algorithm, issuer: this.keySid, subject: this.accountSid, diff --git a/spec/unit/jwt/AccessToken.spec.js b/spec/unit/jwt/AccessToken.spec.js index 3c46328b04..5a0ae5aaa6 100644 --- a/spec/unit/jwt/AccessToken.spec.js +++ b/spec/unit/jwt/AccessToken.spec.js @@ -35,6 +35,27 @@ describe('AccessToken', function() { }); describe('generate', function() { + + describe('home region', function() { + var secret = 'aTBl1PhJnykIjWll4TOiXKtD1ugxiz6f'; + + it('should add twr header when region is provided', function() { + var token = new twilio.jwt.AccessToken(accountSid, keySid, secret, {region: 'foo'}); + var decoded = jwt.decode(token.toJwt(), {complete: true}); + + expect(decoded.header.twr).toBe('foo'); + }); + + ['', undefined, null, {}, 1, 0].forEach(function(value) { + it('should not add twr header if region is ' + value, function() { + var token = new twilio.jwt.AccessToken(accountSid, keySid, secret, {region: value}); + var decoded = jwt.decode(token.toJwt(), {complete: true}); + + expect(decoded.header.twr).toBe(undefined); + }); + }); + }); + it('should generate the correct headers', function() { var token = new twilio.jwt.AccessToken(accountSid, keySid, 'aTBl1PhJnykIjWll4TOiXKtD1ugxiz6f'); var decoded = jwt.decode(token.toJwt(), {complete: true}); @@ -46,7 +67,7 @@ describe('AccessToken', function() { }); }); - it('should accept different algorithsm', function() { + it('should accept different algorithms', function() { var validateAlg = function(alg) { var token = new twilio.jwt.AccessToken(accountSid, keySid, 'secret'); var decoded = jwt.decode(token.toJwt(alg), {