SoftwareBrothers / adminjs

AdminJS is an admin panel for apps written in node.js

Home Page:https://adminjs.co

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature]: 2FA on login?

ivictbor opened this issue · comments

Description

Hey guys, do you have ideas how to quickly implement 2FA (Google Authenticator/Authy) 6-digits code on regular login?

We see there is no such feature out of the box, but interesting whether you have some hooks or interceptors to implement custom step in login form.

Suggested Solution

Alternatives

No response

Additional Context

No response

https://www.npmjs.com/package/speakeasy does this help? @ivictbor

Thanks a lot, yes, this package looks nice, my cocern is more how to injext a page with a 2FA code after adminjs login page, is there facility to inject custom components on login?

You need to override the login component

https://docs.adminjs.co/ui-customization/writing-your-own-components
componentLoader.override('Login', './Login/index')

Then you have to create your own login provider

 const baseRouter = AdminJSKoa.buildAuthenticatedRouter(admin, adminJSApp, {
    provider: adminJSAuthProvider,
...

Something like this

interface AuthPayload extends DefaultAuthenticatePayload {
  OTPToken: string
}

class AuthProvider extends BaseAuthProvider {
  protected readonly authenticate = async (payload: AuthPayload, context: Koa.ParameterizedContext) => {
    const { email, password, OTPToken } = payload

   
    const res = getUserLogic(email, password, OTPToken)

    if (!res) return null
    const { user } = res
    if (user.role !== USER_ROLES.ADMIN) throw new ForbiddenError()

    return {
      email: user.email,
      title: `${user.first_name} ${user.last_name}`,
      role: user.role,
      }
    } as CurrentAdmin
  }

  constructor({}) {
    super()
  }

  override async handleLogin(opts: LoginHandlerOptions, context: any) {
    const { data = {} } = opts
    const { email, password, OTPToken } = data

    return this.authenticate({ email, password, OTPToken }, context)
  }
}

export const adminJSAuthProvider = new AuthProvider({
  componentLoader
})

This should get you on the right path, AdminJS is not very well documented. But in general you can override most components and parts of it's logic. So there is a lot to gain by poking around the source code when you want to change something.