Repository: auth0/auth0.js
Pull request #731 (2018-04-04 02:30:40)

Add transaction manager to passwordlessLogin and login
This fixes an issue that state/nonce were not being auto generated in popup mode.
fix https://github.com/auth0/auth0.js/issues/730

Neaox: Any updates as to when this might be released?
luisrudge: We still have a few outstanding issues we want in the next release. It's either tomorrow or next week.

Patch:
diff --git a/src/web-auth/index.js b/src/web-auth/index.js
index 51d649c..84a1362 100644
--- a/src/web-auth/index.js
+++ b/src/web-auth/index.js
@@ -628,13 +628,28 @@ WebAuth.prototype.signupAndAuthorize = function(options, cb) {
  * @param {crossOriginLoginCallback} cb Callback function called only when an authentication error, like invalid username or password, occurs. For other types of errors, there will be a redirect to the `redirectUri`.
  */
 WebAuth.prototype.login = function(options, cb) {
+  var params = objectHelper
+    .merge(this.baseOptions, [
+      'clientID',
+      'responseType',
+      'redirectUri',
+      'scope',
+      'audience',
+      '_csrf',
+      'state',
+      '_intstate',
+      'nonce'
+    ])
+    .with(options);
+  params = this.transactionManager.process(params);
+
   var isHostedLoginPage = windowHelper.getWindow().location.host === this.baseOptions.domain;
   if (isHostedLoginPage) {
-    options.connection = options.realm;
-    delete options.realm;
-    this._universalLogin.login(options, cb);
+    params.connection = params.realm;
+    delete params.realm;
+    this._universalLogin.login(params, cb);
   } else {
-    this.crossOriginAuthentication.login(options, cb);
+    this.crossOriginAuthentication.login(params, cb);
   }
 };
 
@@ -651,18 +666,33 @@ WebAuth.prototype.login = function(options, cb) {
  * @param {crossOriginLoginCallback} cb Callback function called only when an authentication error, like invalid username or password, occurs. For other types of errors, there will be a redirect to the `redirectUri`.
  */
 WebAuth.prototype.passwordlessLogin = function(options, cb) {
+  var params = objectHelper
+    .merge(this.baseOptions, [
+      'clientID',
+      'responseType',
+      'redirectUri',
+      'scope',
+      'audience',
+      '_csrf',
+      'state',
+      '_intstate',
+      'nonce'
+    ])
+    .with(options);
+  params = this.transactionManager.process(params);
+
   var isHostedLoginPage = windowHelper.getWindow().location.host === this.baseOptions.domain;
   if (isHostedLoginPage) {
-    this.passwordlessVerify(options, cb);
+    this.passwordlessVerify(params, cb);
   } else {
     var crossOriginOptions = objectHelper.extend(
       {
         credentialType: 'http://auth0.com/oauth/grant-type/passwordless/otp',
-        realm: options.connection,
-        username: options.email || options.phoneNumber,
-        otp: options.verificationCode
+        realm: params.connection,
+        username: params.email || params.phoneNumber,
+        otp: params.verificationCode
       },
-      objectHelper.blacklist(options, ['connection', 'email', 'phoneNumber', 'verificationCode'])
+      objectHelper.blacklist(params, ['connection', 'email', 'phoneNumber', 'verificationCode'])
     );
     this.crossOriginAuthentication.login(crossOriginOptions, cb);
   }


Test patch:
diff --git a/test/web-auth/web-auth.test.js b/test/web-auth/web-auth.test.js
index 3e5f398..e76c57e 100644
--- a/test/web-auth/web-auth.test.js
+++ b/test/web-auth/web-auth.test.js
@@ -1753,7 +1753,7 @@ describe('auth0.WebAuth', function() {
         domain: 'me.auth0.com',
         clientID: '...',
         redirectUri: 'http://page.com/callback',
-        responseType: 'code',
+        responseType: 'id_token',
         _sendTelemetry: false
       });
     });
@@ -1782,7 +1782,12 @@ describe('auth0.WebAuth', function() {
           credentialType: 'http://auth0.com/oauth/grant-type/passwordless/otp',
           realm: 'sms',
           username: '+55165134',
-          otp: '123456'
+          otp: '123456',
+          clientID: '...',
+          responseType: 'id_token',
+          redirectUri: 'http://page.com/callback',
+          state: 'randomState',
+          nonce: 'randomNonce'
         };
         stub(CrossOriginAuthentication.prototype, 'login', function(options, cb) {
           expect(options).to.be.eql(expectedOptions);
@@ -1806,7 +1811,12 @@ describe('auth0.WebAuth', function() {
           credentialType: 'http://auth0.com/oauth/grant-type/passwordless/otp',
           realm: 'email',
           username: 'the@email.com',
-          otp: '123456'
+          otp: '123456',
+          clientID: '...',
+          responseType: 'id_token',
+          redirectUri: 'http://page.com/callback',
+          state: 'randomState',
+          nonce: 'randomNonce'
         };
         stub(CrossOriginAuthentication.prototype, 'login', function(options, cb) {
           expect(options).to.be.eql(expectedOptions);
@@ -1842,9 +1852,14 @@ describe('auth0.WebAuth', function() {
       });
       it('should call `webauth.passwordlessVerify` with phoneNumber', function(done) {
         var expectedOptions = {
+          clientID: '...',
+          responseType: 'id_token',
+          redirectUri: 'http://page.com/callback',
           connection: 'sms',
           phoneNumber: '+55165134',
-          verificationCode: '123456'
+          verificationCode: '123456',
+          state: 'randomState',
+          nonce: 'randomNonce'
         };
         stub(this.auth0, 'passwordlessVerify', function(options, cb) {
           expect(options).to.be.eql(expectedOptions);
@@ -1865,9 +1880,14 @@ describe('auth0.WebAuth', function() {
       });
       it('should call `webauth.passwordlessVerify` with email', function(done) {
         var expectedOptions = {
+          clientID: '...',
+          responseType: 'id_token',
+          redirectUri: 'http://page.com/callback',
           connection: 'email',
           email: 'the@email.com',
-          verificationCode: '123456'
+          verificationCode: '123456',
+          state: 'randomState',
+          nonce: 'randomNonce'
         };
         stub(this.auth0, 'passwordlessVerify', function(options, cb) {
           expect(options).to.be.eql(expectedOptions);
@@ -2157,7 +2177,13 @@ describe('auth0.WebAuth', function() {
       });
 
       it('should call CrossOriginAuthentication.login', function(done) {
-        var expectedOptions = { foo: 'bar' };
+        var expectedOptions = {
+          clientID: '...',
+          responseType: 'token',
+          redirectUri: 'http://page.com/callback',
+          foo: 'bar',
+          state: 'randomState'
+        };
         stub(CrossOriginAuthentication.prototype, 'login', function(options, cb) {
           expect(options).to.be.eql(expectedOptions);
           expect(cb()).to.be('cb');
@@ -2191,7 +2217,13 @@ describe('auth0.WebAuth', function() {
         windowHelper.getWindow.restore();
       });
       it('calls _hostedPages.login mapping the connection parameter', function(done) {
-        var expectedOptions = { connection: 'bar' };
+        var expectedOptions = {
+          clientID: '...',
+          responseType: 'token',
+          redirectUri: 'http://page.com/callback',
+          state: 'randomState',
+          connection: 'bar'
+        };
         stub(HostedPages.prototype, 'login', function(options, cb) {
           expect(options).to.be.eql(expectedOptions);
           expect(cb()).to.be('cb');