Using your own Auth0

I have configured 8base to use my own Auth0 account using an authentication profile and using the React SDK (8base starter app) I have my own Auth0 account coming up. However, when I create a user using the Auth0 signup flow on my react app, no users appear in 8base. 8base users created through the admin also do not show up in Auth0.

Am I missing something? The docs only mention setting up the authentication profile.

Hey @spyqsklar ! Great question.

Can you please let me know several things.

  1. Did you use the CLI to generate the react app or was it one you found on GitHub?
  2. Are you using the react-sdk auth component?

Just so you understand how the auth flow works, when a user authenticates via Auth0, the returned idToken will work as a bearer token for the 8base API - for a configured authentication profile. Using that token, the client application can send an authenticated request to 8base and a) check if the user exists, or b) create the user record if they don’t.

Does that make sense?

Here is some code I wrote in another application that hopefully details it well:

  // imported auth module is the client
  async handleAuthentication({ commit }) {
    const authResult = await auth.getAuthorizedData();
    /**
     * Auth headers for communicating with the 8base API.
     */
    const context = {
      headers: { 
        authorization: `Bearer ${authResult.idToken}` 
      }
    };
    /**
     * Check if user exists in 8base.
     */
    try {
      await graphqlClient.query({
        query: gql.CURRENT_USER_QUERY,
        context
      });
    }
    /**
     * If user doesn't exist, an error will be
     * thrown, which then the new user can be
     * created using the authResult values.
     */
    catch {
      await graphqlClient.mutate({
        mutation: gql.USER_SIGN_UP_MUTATION,
        variables: {
          user: { email: authResult.email },
          authProfileId: process.env.VUE_APP_AUTH_PROFILE_ID
        },
        context
      });
    }
    /* commit the auth data to state */
    commit("authenticated", authResult);
  }
};

Happy to help you work through it as soon as I know more about the app!

1 Like

Thanks for the help @sebastian.scholl.

I cloned the react quick start project from the docs - https://github.com/8base/app-example

So, if I understand correctly, when creating a new user I need to give the mutation a user (email), the authProfileId from my config, and whatever fields I may have marked as required - correct?

That’s it! Check out this file, where the call back happens: https://github.com/8base/app-example/blob/master/client/src/routes/auth/routes/callback/index.js

Here are the queries I used in my code, as well.

import gql from "graphql-tag";
/**
 * Query the current users details.
 */
export const CURRENT_USER_QUERY = gql`
  query {
    user {
      id
      email
    }
  }
`;
/**
 * Sign up a new user mutation.
 */
export const USER_SIGN_UP_MUTATION = gql`
  mutation UserSignUp($user: UserCreateInput!, $authProfileId: ID) {
    userSignUpWithToken(user: $user, authProfileId: $authProfileId) {
      id
      email
    }
  }
`;

Thanks @sebastian.scholl. I’m still getting an error, although perhaps it is not directly unrelated.

After creating the new user using the mutation above, I get the following error in the js console:

asyncToGenerator.js:6 Uncaught (in promise) {error: "invalid_token", errorDescription: "statedoes not match."}

This happens after the mutation completes. Any attempt to re-route after this sends me back to the auth0 flow. If instead I refresh the page at this point, everything works as normal.

I’ve tried to figure out what is going on. I assume it has to do with setting the token in authState and a response coming back with a different token, but I can’t find where that is happening if that is the case.

Thanks again for help.
Spyq

Hey @spyqsklar, here’s what my auth callback handler looks like:

const completeAuth = async (authClient, client) => {
  const {
    idToken,
    email,
    firstName,
    lastName
  } = await authClient.getAuthorizedData();

  await authClient.setState({ token: idToken });

  const context = {
    headers: {
      authorization: `Bearer ${idToken}`
    }
  };

  try {
    await client.query({ query: CURRENT_USER, context });
  } catch (error) {
    await client.mutate({
      mutation: SIGN_UP_USER,
      variables: {
        user: { email, firstName, lastName },
        authProfileId: process.env.REACT_APP_8BASE_AUTH_PROFILE_ID
      },
      context
    });
  }
};

Normally that error you are receiving is because the OAuth workflow and the state of your app have gotten out of sync. Generally, for example, if your CRA hotreloads from a code-change, you’ll need to hard refresh the application or restart the OAuth workflow.

1 Like

Thanks for sharing a code example @rmacy. I moved my auth.setState call to before the mutation and now routing is working normally. I’m still getting the same error in the console, but the app appears to be working as expected nevertheless. Here is my component if you have any ideas:

`   const CallbackContainer = compose(`
      withApollo,
      withAuth
    )(({ auth, client, history }) => {
      useEffect(() => {
        const processAuthorizationResult = async () => {
          const { idToken, email } = await auth.getAuthorizedData();
          const context = { headers: { authorization: `Bearer ${idToken}` } };

          await auth.setAuthState({ token: idToken })

         // Check if user exists, if not it'll return an error
         await client.query({
          query: CURRENT_USER_QUERY,
          context,
        })
         // If user is not found - sign them up
          .catch(() => client.mutate({
            mutation: USER_SIGN_UP_MUTATION,
            variables: {
              user: { email },
              authProfileId: AUTH_PROFILE_ID,
            },
            context,
          }));

          history.replace('/')

        }
        processAuthorizationResult();
      })
      return <Loader stretch />

    })
1 Like

try updating to the latest version of react-apollo & @8base/react-sdk – here’s an update I made to the auth guide for the react-sdk: https://github.com/rmacy/Documentation/blob/patch-1/development-tools/sdk/auth/react-auth.md

1 Like

Is there a post, project or doc with this full info provided clearly? I’m able to find bits and pieces here and there but not a full, (basic?) user auth process from:

Sign up via Auth0 (via hosted for example) -> If user exists in 8base, sign in, else create 8base user + recommendations for state, cookie, local storage etc local persistence?

(Suggestion: it looks like the 8base single Authentication Doc page should be broken down into complete subsection pages - including the above info. “Auth0 authentication process with Auth0 hosted login.” page and “Auth0 authentication process with self-hosted login” page and “OpenId authentication process” page… etc. Might be more clear?)

Also, to be clear: the 8base Auth (based on Auth0) is no longer offered correct?

Thanks in advance.

1 Like

Hello @hello - right now we’re revamping the “8base Authentication” so that it is implemented using Cognito rather than Auth0. It’s going to come back soon.

Regarding auth related documentation / tutorials - what would you like to see? From your description, it sounds like you want example apps or tutorials on how to setup authentication - maybe even specific to a certain framework.

Or, are you saying that the Auth documentation is unclear and needs to be more detailed on how auth works?

Hey thanks for the reply Sebastian.

Update: Yeah, I think the #1 need is for solid starter apps devs can build on top of with confidence. Current React starter relies on two core libraries that are deprecated (see below). It also may use insecure JWT storage in localstorage? The thousands of package vulnerabilities that devs have to update also erodes confidence a bit.

My guess is that you all are waiting to finalize your new Amazon Cognito integration before revisiting starter apps. Makes sense.

I think the #2 improvement could be organizing and collecting more info in the Auth docs. @8base/react-sdk vs @8base-react/auth confusion (see below) is one example. Overview info about various popular frameworks (see Nextjs below) could also help, I think.

For anyone looking for a single resource for 8base React-related Auth info, from what I can see:

React Auth Examples

  1. 8base React Starter App (and a Vue version too)
    Login via hosted Auth0 login/sign up. Starter app either finds that 8base user if they exist or creates a new 8base user on 8base if not. Note: This app relies on 2 deprecated libraries: apollo-react and recompose. Apollo suggests using @apollo/client instead. And the developer of recompose suggests using React’s native hooks instead. @apollo/client uses React hooks such as useQuery, useMutation, useSubscribe.

  2. Not just Auth (Cognito), but full app
    Uses @8base/Auth + @8base-react/app-provider (not the latest React SDK?) + @8base-react/auth + react-apollo + react-router-dom + @8base/boost. Wraps 8base Auth in an AppProvider at the app root.

  3. Simple Auth0 example using the login/signup hosted on Auth0
    Simple. If I understand correctly, it doesn’t go to the next step to do the 8base GraphQL user query or mutation to compare that Auth0 user and compare her to 8base users and either log them in or create a new 8base user.

  4. Create self-hosted login/sign up via 8base GraphQL mutations which talks machine-to-machine with Auth0.

Docs

  • Authentication (May be nice if there was better info for main approaches such as:)
    — Page with more info for Hosted Auth0
    — Page with more info for Self-hosted Auth0
    — Page with more info for Cognito (new 8base provider, so it’s coming soon, I’m sure)
    — Page with more info for OpenID Connect
    – Page for Sign-on Providers
    – Pages for different, popular frameworks might help too (see Nextjs below).

Docs Note: OpenId and Sign-on Providers sections seem to get a little confusing? “Configuring the OpenID Settings” and “getToken Resolver” are both part of Sign-on Providers (the most recent parent H3?) and not OpenId section?

Related SDKs & modules

  • @8base/Auth Basic 8base auth
  • Update 3 @8base/react-sdk (Github) but not @8base-react/auth (no Github README. Is this npm info to be trusted? Not sure. Seems to be different than the app example above.) (used in example 1 above)? Auth helpers for React apps. Still requires @8base/Auth. Docs mention deprecated react-apollo dependency but don’t mention how it applies to that sample code. Throws errors in Nextjs.
  • @8base-react/app-provider

Docs Note: Tracking down the above requires Google, not Docs menu.

React Nextjs

Notes: for any server-side rendering folks (like Nextjs), some things to consider:

  • I’m not sure any 8base native SDKs work especially well with Nextjs? (Have folks experienced different?) You might consider trying Nextjs official Apollo examples for graphql api connections and Auth0’s @auth0/auth0-react or their new, experimental @auth0/nextjs-auth0
  • If you do use 8base SDKs and you run into errors, consider using ‘next/dynamic’ for importing some of those SDKs client-side-only as the SDKs use “window.” which = server side rendering errors.
  • Consider how you might use Nextjs’s native next/router vs the react-router-dom that @8base-react favors?