Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom auth method and login component (for Firebase Auth) #546

Closed
ivawzh opened this issue Aug 13, 2020 · 3 comments
Closed

Custom auth method and login component (for Firebase Auth) #546

ivawzh opened this issue Aug 13, 2020 · 3 comments

Comments

@ivawzh
Copy link

ivawzh commented Aug 13, 2020

Describe the problem feature solves

Hi, thank heaps for this awesome OSS.

I am trying to implement Firebase Auth with Admin Bro ExpressJs.

Is this already a supported feature? If yes, can you please share with me some links or clues to the implementation?

Describe the solution you'd like

Ideally, I would like a landing login page with FirebaseUI component. And then on the server-side, it statelessly decodes the auth token from either cookie or JWT header.

Currently, I can see Admin Bro supports overiding components:

export declare type OverridableComponent = 'LoggedIn' | 'NoRecords' | 'SidebarResourceSection' | 'SidebarFooter';

But it doesn't support overriding Login Page.

Describe alternatives you've considered

I am familiar with ExpressJS. It should be quite easy to implement something like

  app.all('*', decodeAuthTokenOrRedirectToLoginPage)

  function decodeAuthTokenOrRedirectToLoginPage() {
    ... 
    const claims = await firebase-admin.admin.auth().verifyIdToken(idToken)
    ...
  }

But I am not sure what is the best way to integrate with Admin Bro's existing component bundle and auth workflow.

Acceptance criteria

  1. Firebase Auth login page
  2. Cookie support, so that doesn't require re-login on every fresh request.
  3. Redirect to login page when users are not logged in.

Thanks in advanced =D

@ivawzh ivawzh changed the title Custom auth method and login comopnent (Firebase Auth) Custom auth method and login component (for Firebase Auth) Aug 13, 2020
@wojtek-krysiak
Copy link
Contributor

Hi, it is not supported out of the box.

What you have to do is:

  1. write your routes which will handle:
  • login page
  • token authentication.
  • middleware which will check it redirect to login when there is no user.
  1. Write the current user to the session (which you will obtain from the firebase)
  2. and use regular buildRouter function to add all the AdminBro routes to express

for points 1 and 2 take a look at how buildAuthenticatedRouted does that.

If you want to style the login page in the way how AdminBro looks - take a look at @admin-bro/design-system - you can use it there, but you will have to set up an entire SSR on your own (you can take a look at https://www.youtube.com/watch?v=SLzMxdyuAIA for a reference of how to do this with parcel bundler)

Leaving this task open - because we should allow changing login page in the easier way.

@ivawzh
Copy link
Author

ivawzh commented Sep 9, 2020

Hey @wojtek-krysiak , I have just tried it a bit more. I don't think it's possible to wire Firebase Auth at the moment.

As currently from buildAuthenticatedRouter(admin: Admin, auth: { authenticate: (email: string, password: string) => unknown } , authenticate is hardcoded to require email and password on https://github.com/SoftwareBrothers/admin-bro-expressjs/blob/507c6ca99d3bd8c20f29b47eeb8a7cbf82b560a9/plugin.js#L198.

The limitation of auth control is sadly stopping us from migrating to Admin Bros...

@wojtek-krysiak
Copy link
Contributor

wojtek-krysiak commented Sep 9, 2020

we use it (firebase) in SoftwareBrothers with one of our clients.

don't use buildAuthenticatedRouter() - you have to write your own implementation. You can take a look at the source code (it is super simple: https://github.com/SoftwareBrothers/admin-bro-expressjs/blob/master/plugin.js#L141)

Example: this is how your firebaseRouter() function should look like (modified buildAuthenticatedRouter)


const router = express.Router()

router.use(session()) // with your session options

router.get('/login', () => {
  // here you have to render login page with firebase UI
})

router.post('/login', () => {
  // here you have to take firebase token, validate it and store to the `req.session.adminUser`. It has to be of type: https://adminbro.com/AdminBro.html#CurrentAdmin so you can have avatar, etc.
// and then redirect to /admin (assuming that this is your admin path)
})

// this is copied from authenticatedRouerCode
router.use('(req, res, next) => {
    if (AdminBro.Router.assets.find(asset => req.originalUrl.match(asset.path))) {
     // all static assets are available by default
      next()
    } else if (req.session.adminUser) {
      next()
    } else {
      // in the original there is a `redirectTo` property - I skipped this to simplify the example.
      // It causes to redirect to last visited page, when logged out after timeout - check out the code
      // of buildAuthenticatedRouter
      req.session.save((err) => {
        if (err) {
          next(err)
        }
        res.redirect(admin.options.loginPath)
      })
    }
  })

router.get(logoutPath, async (req, res) => {
    req.session.destroy(() => {
      res.redirect(admin.options.loginPath)
    })
  })

// and finally you add adminbro to this router
return buildRouter(admin, router) // you can add formidableOptions if any as a 3rd argument

PS: in case of problems let me know on slack - will be faster there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants