RocketChat / RocketChat/Rocket.Chat
2fa prevents oauth custom login
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 46.1k
- Forks
- 13.9k
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 130
Description
Description:
If both custom oauth and 2fa (email) are enabled a user logging in will go through the oauth flow and be emailed an authentication code, but no input screen will be presented to use the 2fa code. They will not be able to login.
Steps to reproduce:
- Enable and configure custom oauth in Settings / OAuth / Add Custom OAuth
- Enable 2fa in Settings / Accounts / Two Factor Authentication
- Open a new browser window and authenticate via the custom oauth path
Expected behavior:
User authenticates via OAuth and is then shown a 2fa screen to input the code they are emailed
Actual behavior:
The user authenticates via OAuth, and the 2fa code is emailed to them, but no screen is presented to input the code.


Server Setup Information:
- Version of Rocket.Chat Server: 3.13.1
- Operating System: Ubuntu 20.04
- Deployment Method: tar
- Number of Running Instances: 1
- DB Replicaset Oplog: n/a
- NodeJS Version: v12.18.4
- MongoDB Version: 4.4.5
Client Setup Information
- Desktop App or Browser Version: Firefox 87
- Operating System: Ubuntu 20.04
Relevant logs:
The following exception is generated in the rocketchat logs:
I20210412-12:25:34.124(1) Failed login detected - Username[unknown] ClientAddress[192.168.122.1] ForwardedFor[-] XRealIp[-] UserAgent[Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0]
I20210412-12:25:34.125(1) Exception while invoking method login Error: TOTP Required [totp-required]
at checkCodeForUser (app/2fa/server/code/index.ts:186:9)
at app/2fa/server/loginHandler.js:30:2
at callbacks.runItem (app/callbacks/lib/callbacks.js:111:70)
at Object.callbacks.runItem (app/metrics/server/callbacksMetrics.js:24:20)
at app/callbacks/lib/callbacks.js:39:35
at app/callbacks/lib/callbacks.js:45:45
at callbacks.run (app/callbacks/lib/callbacks.js:127:9)
at Object.callbacks.run (app/metrics/server/callbacksMetrics.js:14:17)
at app/authentication/server/startup/index.js:346:20
at packages/callback-hook/hook.js:131:22
at packages/accounts-base/accounts_server.js:191:15
at Hook.each (packages/callback-hook/hook.js:109:15)
at AccountsServer._validateLogin (packages/accounts-base/accounts_server.js:188:29)
at AccountsServer._attemptLogin (packages/accounts-base/accounts_server.js:377:10)
at MethodInvocation.methods.login (packages/accounts-base/accounts_server.js:559:23)
at maybeAuditArgumentChecks (packages/ddp-server/livedata_server.js:1771:12)
at packages/ddp-server/livedata_server.js:1689:15
at Meteor.EnvironmentVariable.EVp.withValue (packages/meteor.js:1234:12)
at packages/ddp-server/livedata_server.js:1687:36
at new Promise (<anonymous>)
at Server.applyAsync (packages/ddp-server/livedata_server.js:1686:12)
at Server.apply (packages/ddp-server/livedata_server.js:1625:26)
at Server.call (packages/ddp-server/livedata_server.js:1607:17)
at Object.post (app/api/server/v1/misc.js:263:26)
at app/api/server/api.js:394:82
at Meteor.EnvironmentVariable.EVp.withValue (packages/meteor.js:1234:12)
at Object._internalRouteActionHandler [as action] (app/api/server/api.js:394:39)
at Route.share.Route.Route._callEndpoint (packages/nimble_restivus/lib/route.coffee:150:32)
at packages/nimble_restivus/lib/route.coffee:59:33
at packages/simple_json-routes.js:98:9 => awaited here:
at Promise.await (/var/lib/rocket.chat/bundle/programs/server/npm/node_modules/meteor/promise/node_modules/meteor-promise/promise_server.js:60:12)
at Server.apply (packages/ddp-server/livedata_server.js:1638:22)
at Server.call (packages/ddp-server/livedata_server.js:1607:17)
at Object.post (app/api/server/v1/misc.js:263:26)
at app/api/server/api.js:394:82
at Meteor.EnvironmentVariable.EVp.withValue (packages/meteor.js:1234:12)
at Object._internalRouteActionHandler [as action] (app/api/server/api.js:394:39)
at Route.share.Route.Route._callEndpoint (packages/nimble_restivus/lib/route.coffee:150:32)
at packages/nimble_restivus/lib/route.coffee:59:33
at packages/simple_json-routes.js:98:9
Workarounds
- Disabling 2fa will allow the user to login as expected with OAuth.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with app/2fa/server/code/index.ts and app/2fa/server/loginHandler.js, then trace the login flow from app/authentication/server/startup/index.js. Reproduce the issue with custom OAuth and email 2FA enabled, following the TOTP Required log path. Done means OAuth users are shown a screen to enter the emailed 2FA code and can complete login.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- authentication, backend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100