Is it possible go combine several auth providers?

I’d like to combine several auth providers. For example dbAuth and Auth0.
How can I do that if it’s possible at all?

Yes you can! :slight_smile:

For decoding the token you can pass an array of auth decoders when creating the graphql handler.

For the web side you have to export your own version of AuthProvider and useAuth that has logic for checking with the correct auth provider.

What’s your specific use case? Why do you want to use two providers? With a little more details I can be more specific in my suggestions for you :slight_smile:

1 Like

Thanks for the answer.
I want to make sure that if client decides to add some additional auhtentification option I’ll be able to do that without too much hussle.
At the moment I’m trying to explore what redwood is capable of.

Would be very thankful if provide me with some example of using more that one auth providers including dbAuth?

Unfortunately I don’t have time to build out an example right now. But happy to answer specific questions if you try it out on your own :slightly_smiling_face:

1 Like

The backend side is clear enough for me.
Regarding the frontend side. I can wrap the app with muitiple auth providers. But I can’t understand how can I combine sevaral useAuth hooks into one hook that will return correct auth props depending what type of authentification is currently selected.

useAuth hook can be used in many places in real app so all the related logic should’nt be exposed.
I tried several approaches but non of them have worked Yet.

How do you select auth type? Can you store this choice somewhere (maybe in a context) where your custom useAuth implementation can read it?

I’m storing auth type variable in redux.
But the main blocker for me right now is that RedwoodAppoloProvider is designed for only one useAuth hook and I don’t see a good way to pass multiple useAuth hooks.

Last time I used redux was five years ago… But here’s some untested code I just typed out that hopefully can give you some ideas

// web/src/auth.ts
import auth0 from '@redwoodjs/auth-auth0-web'
import dbAuth from '@redwoodjs/auth-dbauth-web'

const dbAuthClient = dbAuth.createDbAuthClient()

const { AuthProvider as DbAuthProvider, useAuth as useDbAuth } = dbAuth.createAuth(dbAuthClient)
const { AuthProvider as Auth0AuthProvider, useAuth as useAuth0Auth } = auth0.createAuth()

export const useAuth = () => {
  // get authType from redux
  const authType = useSelector(selectAuthType)

  if (authType === 'auth0') {
    return useAuth0Auth()
  } else if (authType === 'dbAuth') {
    return useDbAuth()
  }

  throw new Error('Unsupported auth type: ' + authType)
}

So basically you create your own useAuth hook that you can pass to Apollo Client.

Hi - i’m trying to do this as well. no state managers involved. I want to do this to allow both Azure AD authenticated users from my companies AD - but also to allow an external user sign up /login without having to be added as a guest to our AD.

Here is the web side I’ve got started for my auth.js -

import { PublicClientApplication } from '@azure/msal-browser'

import { createAuth as createAzureAuth } from '@redwoodjs/auth-azure-active-directory-web'
import {
  createDbAuthClient,
  createAuth as createDbAuth,
} from '@redwoodjs/auth-dbauth-web'
import WebAuthnClient from '@redwoodjs/auth-dbauth-web/webAuthn'

/**
 * Creates a new instance of the authentication client for database authentication.
 * @type {Object}
 */
const dbAuthClient = createDbAuthClient({ webAuthn: new WebAuthnClient() })

/**
 * Creates a new instance of the authentication client for Azure Active Directory authentication.
 * @type {Object}
 */
const azureActiveDirectoryClient = new PublicClientApplication({
  auth: {
    clientId: process.env.AZURE_ACTIVE_DIRECTORY_CLIENT_ID || '',
    authority: process.env.AZURE_ACTIVE_DIRECTORY_AUTHORITY,
    redirectUri: process.env.AZURE_ACTIVE_DIRECTORY_REDIRECT_URI,
    postLogoutRedirectUri:
      process.env.AZURE_ACTIVE_DIRECTORY_LOGOUT_REDIRECT_URI,
  },
})

/**
 * The authentication provider for database authentication.
 * @type {Object}
 */
const { AuthProvider: DBAuthProvider, useAuth: useDbAuth } =
  createDbAuth(dbAuthClient)

/**
 * The authentication provider for Azure Active Directory authentication.
 * @type {Object}
 */
const {
  AuthProvider: AzureActiveDirectoryAuthProvider,
  useAuth: useAzureActiveDirectoryAuth,
} = createAzureAuth(azureActiveDirectoryClient)

export {
  DBAuthProvider,
  AzureActiveDirectoryAuthProvider,
  useDbAuth,
  useAzureActiveDirectoryAuth,
}

i’m not sure what exactly to do on api side yet. I’ll continue studying - any assistance much appreciated! thanks.

This is exciting! Made any progress yet?
I’m too busy at the moment to try to implement this for you, but if you try it and have specific questions I’m happy to take a look. Especially if you have a github repo with clear reproduction instructions I can just fork and run :slightly_smiling_face:

1 Like