# How are things going with 2FA

**URL:** <https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407>\
**Category:** Parse Server 📡\
**Tags:** authentication\
**Created:** [February 4, 2022, 9:41am UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407 "2022-02-04T09:41:06Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Taylorsuk](https://community.parseplatform.org/user_avatar/community.parseplatform.org/taylorsuk/32/123_2.png) [@Taylorsuk](https://community.parseplatform.org/u/Taylorsuk)\
**Post date:** [February 4, 2022, 9:41am UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/1 "2022-02-04T09:41:06Z")

</div>

We’re in the process of researching 2FA, which is prefered to be done via build-in Parse Server functionality, than rolling our own solution.

There are a number of chats about this in GitHub issues (see resources below), with tasks and branches at various stages of completion, however, activity seems to stop in Sep 21.

I was wondering if I can use this thread to kick start the conversation around improving the AuthAdaptor and providing a recommended solution for the implementation of 2FA.

I look forward to hearing your thoughts and if we can get the PRs tested and merged to a release soon.

## Resources

**Two Factor Authentication**

> <https://github.com/parse-community/parse-server/issues/4024>
>
> I see no straightforward way to implement two-factor authentication (2FA) in Par…se Server. Ideally this would allow:
> 
> \- 2FA using one or more methods (Google authenticator, SMS, email)
> \- Device memory (with periodic expiration) so users don't necessarily need to enter the second factor all the time
> \- Any particular user to have 2FA enabled/disabled optionally
> 
> I initially started implementing this in my client-side code (PHP) for my Administrator users using Goole Authenticator, but then I realized anyone with the AppID and the Admin password can simply write their own code to get around it. Oops.
> 
> I then thought about storing a second factor, or possibly an IP whitelist, and rejecting any requests in beforeSave, beforeDelete, or beforeFind Cloud Code where the client did not provide the second factor, but that seems clunky. It is also difficult to rate-limit, since the malicious user would be able to log in and only be blocked at the point of accessing data. Further, I believe the second factor would need to be stored apart from the User object itself, since once logged in, the user can access its own data.
> 
> @flovilmart suggested using a 3rd party Auth adapter, for example Google, which could potentially work in my case since I only care about the extra security for certain users. However, I don't want to require Google login for everyone, which means native username/password login is still available. Checking triggers in Cloud Code for the particular users could be a workaround, but again, the user would be checked at the point of accessing data, not logging in. I also don't know if this solution would generalize to others' use cases.
> 
> One solution I see is to add a beforeLogin trigger in Cloud code. A routine in this trigger could check the second factor (stored with the user object) and reject the Login if it does not match or is not provided. This would also allow for IP whitelisting for certain users (reject login attempts from non-listed IPs) or any variety of custom authentication methods.
> 
> Another may be to have per-user control over the authentication method. For example, if a user can login with Google, the user can ONLY login with Google, and not username/password.
> 
> I am not familiar enough with how Parse Server handles logins to know if the beforeLogin trigger is feasible, or if some other 2FA system would be easier to implement.

**Improve AuthAdapter capabilities**

> <https://github.com/parse-community/parse-server/issues/7050>
>
> \*\*Is your feature request related to a problem? Please describe.\*\*
> No
> 
> \*\*Desc…ribe the solution you'd like\*\*
> We need to add some triggers , and improve AuthAdapter interface to support some special auth systems like MFA, WebAuthn
> 
> \*\*Describe alternatives you've considered\*\*
> No alternative currently, contributors need to inject code directly in Routers/Controllers may be we can avoid this.
> 
> \*\*Additional context\*\*
> The new interface should support with AuthAdapter pure implementation:
> 
> \- \[x\] MFA
> \- \[x\] WebAuthn
> 
> 
> MFA particularities:
> \- Store recovery keys somewhere (authData?)
> \- perform a check after a login (could be a classic login or other loginWith adapter)
> \- Need a public endpoint to receive/display recovery keys
> 
> @dblythy tell me if you see other things for MFA
> 
> WebAuthn:
> \- Need 2 public endpoints (assertion/attestation)
> \- Store multi public keys (can be done through authData)

---

<div class="post-metadata">

**Author:** ![Moumouls](https://community.parseplatform.org/user_avatar/community.parseplatform.org/moumouls/32/332_2.png) [@Moumouls](https://community.parseplatform.org/u/Moumouls)\
**Post date:** [February 5, 2022, 11:23am UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/2 "2022-02-05T11:23:15Z")

</div>

Hi @Taylorsuk,

You are right 2FA system and auth challenge feature are missing on parse server.  
I’ve worked a lot to improve the Auth Adapter interface to introduce 2FA and help developers to write their own AuthAdapters easily (validation, registration, challenge and many more)

The PR is fully ready here and should be shipped on Parse v5: [https://github.com/parse-community/parse-server/pull/7079](https://github.com/parse-community/parse-server/pull/7079)

I already use this PR on production for my company for over 1 year to:

- Support 2FA login (email + password + SMS OTP)
- Biometric authentification via Webauthn
- Fully custom auth pattern (a username + a field 1 + a field 2 + SMS OTP)

It works well !

Currently the feature wait a PR from @davimacedo ([https://github.com/parse-community/parse-server/pull/7079#issuecomment-990338449](https://github.com/parse-community/parse-server/pull/7079#issuecomment-990338449)) to add some warnings.

Here the example of the new Auth Adapter Interface applied to Webauthn: [https://github.com/parse-community/parse-server/pull/7079/files#diff-51ec90d71b4547d4642872376195afc01ee0a8ddc62d3647cfdbc4bfacb79d8d](https://github.com/parse-community/parse-server/pull/7079/files#diff-51ec90d71b4547d4642872376195afc01ee0a8ddc62d3647cfdbc4bfacb79d8d)

Here an example of an SMS OTP Auth Adapter (code is not complete):

```auto
export const OTPAuth = {
	policy: 'additional',

	async challenge(
		challengeData: boolean,
		authData: OtpAuthDataInput,
		options: any,
		req: any,
		user?: Parse.User,
	) {
		if (!user || !user.get('phone')) throw new Error('User not found')
		const otp = new OTP(user.id, user.get('phone'))
		await SMSAdapter.send(
			user.get('phone'),
			// Dependency injection strategy
			getOTPMessage(user.get('type'))(await otp.generate()),
		)
	},

	async validateSetUp(
		authData: CreateUpdateOtpAuthDataInput,
		options: any,
		req: AuthReq,
	) {
		return checkAuthorization(req)
	},

	async validateUpdate(
		authData: CreateUpdateOtpAuthDataInput,
		options: any,
		req: AuthReq,
	) {
		return checkAuthorization(req)
	},

	async validateLogin(
		authData: OtpAuthDataInput,
		options: any,
		req: AuthReq,
		user?: Parse.User,
	) {
        try {
            // As an additional auth system user should be already identified
            // with another default auth system
            if (!user?.id) return throwError()
            if (!user.get('phone')) return throwError()
            const otp = new OTP(user.id, user.get('phone'))
            await otp.check(authData.code)
            return { doNotSave: true }
        } catch (e: any) {
            // eslint-disable-next-line @typescript-eslint/no-throw-literal
            throw new Parse.Error(403, e.message)
        }
	},
}

```

@Taylorsuk all the magic happen with the `policy: 'additional'`.  
The architecture is pretty simple.

Here the client example of the 2FA (using GraphQL API).

First you need to `challenge` with `authData` or `username/passowrd` to obtain the SMS OTP. The `challenge` function will only success if provided `authData` or `username/password` are correct.

```auto
mutation loginChallenge {
	challenge(input: { challengeData: { otp: true }, username: "test@test.test", password: "aPassword"}) {
		clientMutationId
	}
}

```

Then the use will receive the OTP on his phone

In your client app you will juste need to call now login like with additional authData

```auto
mutation login {
	logIn(input: { usnername: "test@test.test", password: "aPassword", authData: { otp : "123765"} }) {
		viewer {
			sessionToken
			user {
				id
			}
		}
	}
}

```

---

<div class="post-metadata">

**Author:** ![Taylorsuk](https://community.parseplatform.org/user_avatar/community.parseplatform.org/taylorsuk/32/123_2.png) [@Taylorsuk](https://community.parseplatform.org/u/Taylorsuk)\
**Post date:** [February 9, 2022, 9:16am UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/3 "2022-02-09T09:16:32Z")

</div>

Hi @Moumouls, thanks for replying and providing such details. I am sorry it’s taken me a little time to respond.

Great work on your proposed changes to the AuthAdaptor and ability to use WebAuthn.

The example above looks to use SMS for the OTP, however, I wondered if there is an ability to use an authenticator (Google, Authy, 1Password etc). I am not completely sure on the implications of adding this MFA method to the mix, however, it seems to be a popular offering for 2FA around the web (noting that Stripe still uses SMS!).

Is there any plan to update the docs on how to do this? I think 2FA being supported and documented (with examples) capability of Parse, would be a huge plus. A quick scan over the code and commits, I’m still not 100% sure how I would implement this, however more than happy to offer some support in writing the docs if it can first be explained to me.

Once again, thanks for your awesome work and commitment to driving Parse forwards 👍.

---

<div class="post-metadata">

**Author:** ![Moumouls](https://community.parseplatform.org/user_avatar/community.parseplatform.org/moumouls/32/332_2.png) [@Moumouls](https://community.parseplatform.org/u/Moumouls)\
**Post date:** [February 9, 2022, 10:02am UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/4 "2022-02-09T10:02:05Z")

</div>

Hi @Taylorsuk i’m happy to confirm that an implementation of a TOTP MFA Adapter will for sure play well with the new auth architecture and it will be super easy to implement.

Since i managed to implement Webauthn, implementing TOTP should be also feasible.

Parse is not completely magic, for a complete TOTP user experience you will need to do some (tiny) work like displaying the private key MFA code (and also rescue keys) as QR code on your client app to allow your users to easily register the private key on Google authenticator or others TOTP managers app.

A QR code could be generated on the client app with some third party packages like: [https://www.npmjs.com/package/qrcode](https://www.npmjs.com/package/qrcode)

I’ll we need this kind of MFA TOTP adapter for my company so, i’ll work on it but i currently no have ETA (may be april/may 2022). Once it’s implemented some examples will be added.

Important note: the new auth architecture need some non breaking changes on SDKs, in the first instance i think only JS SDK, Rest API, GraphQL API will be compatible with these new features/adapters.

What SDK do you use ? @Taylorsuk

---

<div class="post-metadata">

**Author:** ![Taylorsuk](https://community.parseplatform.org/user_avatar/community.parseplatform.org/taylorsuk/32/123_2.png) [@Taylorsuk](https://community.parseplatform.org/u/Taylorsuk)\
**Post date:** [February 9, 2022, 10:43am UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/5 "2022-02-09T10:43:00Z")

</div>

Sounds awesome. Yeah, the client-side workflow is something to work with, however, it’s fairly trivial in the grand scheme of things.

Looking forward to seeing this progress and timelines are not a massive issue.

We’re using Rest.

---

<div class="post-metadata">

**Author:** ![reptilehaus](https://community.parseplatform.org/user_avatar/community.parseplatform.org/reptilehaus/32/1259_2.png) [@reptilehaus](https://community.parseplatform.org/u/reptilehaus)\
**Post date:** [August 24, 2022, 12:26pm UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/6 "2022-08-24T12:26:17Z")

</div>

Hey gents, been looking for this feature since forever, any updates on it being merged and available in parse ?

---

<div class="post-metadata">

**Author:** ![tayloruk](https://community.parseplatform.org/letter_avatar_proxy/v4/letter/t/51bf81/32.png) [@tayloruk](https://community.parseplatform.org/u/tayloruk)\
**Post date:** [August 24, 2022, 2:14pm UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/7 "2022-08-24T14:14:00Z")

</div>

We’ve not got around to trying it. I needed to see if there is going to be a recommended 2FA example to come out before we tackled it.

---

<div class="post-metadata">

**Author:** ![Taylorsuk](https://community.parseplatform.org/user_avatar/community.parseplatform.org/taylorsuk/32/123_2.png) [@Taylorsuk](https://community.parseplatform.org/u/Taylorsuk)\
**Post date:** [June 19, 2023, 9:23am UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/8 "2023-06-19T09:23:33Z")

</div>

Hi @Moumouls, I was just checking back on this topic to see if you’d managed to implement the TOTP approach mentioned above and if you have any examples to share?

---

<div class="post-metadata">

**Author:** ![Kone](https://community.parseplatform.org/letter_avatar_proxy/v4/letter/k/ce7236/32.png) [@Kone](https://community.parseplatform.org/u/Kone)\
**Post date:** [June 21, 2023, 9:41pm UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/9 "2023-06-21T21:41:59Z")

</div>

Here just to say that I would also love to have this implemented

---

<div class="post-metadata">

**Author:** ![Manuel](https://community.parseplatform.org/user_avatar/community.parseplatform.org/manuel/32/186_2.png) [@Manuel](https://community.parseplatform.org/u/Manuel)\
**Post date:** [June 21, 2023, 10:56pm UTC](https://community.parseplatform.org/t/how-are-things-going-with-2fa/2407/10 "2023-06-21T22:56:39Z")

</div>

There’s ~~an ongoing~~ a merged PR for TOTP

> <https://github.com/parse-community/parse-server/issues/8441>
>
> \### New Feature / Enhancement Checklist
> \<!--
> Check every following box \[x\]… before submitting your issue.
> Click the "Preview" tab for better readability.
> Thanks for contributing to Parse Platform!
> \--\>
> 
> \- \[x\] I am not disclosing a \[vulnerability\](https://github.com/parse-community/parse-server/blob/master/SECURITY.md).
> \- \[x\] I am not just asking a \[question\](https://github.com/parse-community/.github/blob/master/SUPPORT.md).
> \- \[x\] I have searched through \[existing issues\](https://github.com/parse-community/parse-server/issues?q=is%3Aissue).
> 
> \### Current Limitation
> 
> 
> Currently, there is no TOTP adapter.
> 
> \### Feature / Enhancement Description
> 
> 
> Create the TOTP adapter to be used with the new Auth logic
> 
> \### Example Use Case
> 
> 
> \### Alternatives / Workarounds
> 
> 
> \### 3rd Party References
