Confused about how authentication works in 8base

I’ve successfully “logged in” with callback URL through the auth0.js client, but where/how do I use the access token? Do you pass the user access token in the request header like you do for API tokens?

So far I’ve just been using an API token to prototype because it’s easy. Even if I use 8base auth, I’d still like to understand how it works. Auth in general is very confusing.

1 Like

@mike_ekim1024 hello!

You’re right. A Id token from auth0 should passed into Authentication header like as an API token.

Hey @mike_ekim1024! I’ve been working on a graph to show auth. I attached it here. Can you help me make it better?

Does it help explain anything?
Would it have helped you understand the auth flow had you had it originally?

Yes, that does help a bit Sebastian. I think the key is using idToken vs accessToken, and now it’s clear how 8base interacts with auth0 and the client. A few more questions though: the difference between authentication with redirect, and being able to put the login form on your own page (which it sounds like is in the diagram), and using social sign-on vs email/passord.

I think I’m getting somewhere now. My queries are returning data now that I send Bearer idToken. I needed to add “id_token” to responseType, and use idToken instead of accessToken. I don’t know what the difference is. I know you have an auth library, but I really want to understand how it works, or else it just feels like magic.

As an amateur magician I’m offended by your derogatory mention of magic and… joking!

Do you think this graph should be updated to show those different flows? Or that another graph would help you “dive deeper”.

Essentially, all scenarios are working similarly. If you use email/password mutation, it goes to the auth-provider and an idToken is returned. If you use a hosted login page, you’re on a secure login page that communicates with the auth provider and redirects you back to your application with the access token specified in the URL fragment.

When using a social sign on provider, the same thing is happening. It’s a hosted login page where the sign on provider will redirect the user back to the application with a url fragment containing the idToken.

What’s probably confusing is the differences between 8base Authentication Profiles, Auth Providers, and Single-Sign-On.

Authentication profiles are how 8base allows you to create different authentication settings. For example, on Authentication Profile A you may allow users open-to-all/self-sign up and get the “Guest” role, whereas on Authentication Profile B you might only allow users with an "@company.com" email domain and assign them an “Employee” role.

Auth Providers securely store user’s authentication credentials and issue idTokens upon authentication that can be verified when used. Certain ones (like Auth0) make it really easy to connect social-logins.

Single Sign-on/Social Logins lets users use existing login information from a provider like Facebook, GitHub or Google so the user can sign into a third-party website instead of creating a new account (username/password) specifically for that website. This just simplifies registrations and logins for end users. An 8base Authentication Profile can have multiple single sign-on methods configured, allowing users to sign up using one of their existing social accounts OR email/password.

An accessToken (on Auth0) is non-user specific – just like an 8base API token – and commonly used to authenticate machine to machine communication, whereas the idToken is associated with an individual authenticated user. In regards to 8base, generating and API Token is the equivalent of using an accessToken, therefore we wouldn’t support an accessToken.

2 Likes

This is good stuff! Maybe represent email/social as 1.a and 1.b? They aren’t that different, but do use different API. The isometric does look cool, but a little hard to read without tilting your head :slight_smile:

So for every request, 8base contacts auth0? Is there any caching that happens, or any predictive fetching so that the auth and data can be fetched in parallel? For production, I’ll be researching latency, security, and that kind of stuff.

2 Likes

Re: Id Tokens vs Access Tokens, am I understanding this correctly?

Auth0 (for example) can provide a) id tokens (for authentication - yes, this is joe@example.com) and b) auth tokens with scope (for authorization to certain assets - yes, joe@example.com is authorized to access guest stuff but not admin stuff).

But 8base handles it’s own authorization to all its graphql-accessible goodies. "joe@example.com has Admin access" is defined in 8base, not Auth0.

So, a) 8base only needs authentication (not authorization) from Auth0 (or AWS Cognito or whichever provider) and b) 8base does not issue it’s own access tokens so: c) 100% of protected graphql queries, mutations and subscriptions made from your app to 8base require the Auth0-generated (or whichever provider) id token (not access token) in the graphql call’s auth header. 8base then checks, on its end, whether that authenticated user is authorized to access the assets requested.

Or do I have something wrong? Thanks.

Yup, there is no use of the access tokens in 8base. 8base’s authorization is fully handled by our own roles and permissions engine. We have no way of reading/using the access tokens as you might configure them in Auth0

Thanks Sebastian. And re: what 8base needs from Auth0 to authenticate: 8base simply needs the Auth0-generated idtToken in all of the app’s graphql queries/mutations/subscriptions via header’s Authorization: Bearer ${idToken} yes?

No 8Base SDK (auth or otherwise) is needed as long as we get the idToken from Auth0 and pass it to 8base via header auth yes?

Thanks.

Here is the code for the 8base-js-sdk where we interface with the Auth0-js NPM package for handling auth: https://github.com/8base/js-sdk/blob/master/packages/auth/src/Auth0Strategy.ts

You still need to create an Authentication Profile in 8base. However, this should help you understand how 8base interfaces with Auth0 so that you could recreate it on your own if needed.

Sebastian, is there any documentation that describes what 8base needs after you get auth’ed from an auth provider like Auth0?

I’ve run into lots of issues with 8base SDKs so I’ve looked to Auth0 sdks instead. So I have Auth0 working fine using their nextjs-auth0 sdk and no 8base sdk. Sign in, callback, Auth0 idtoken in session via Nextjs server side rendering… all working fine.

I still need to authenticate with 8base. Send 8base the Auth0 idtoken? and my 8base Auth Profile? and client ID and get back… what? An 8base idtoken?

And then pass that 8base idtoken to every 8base graphql query/mutation/subscription I make? Or do I need to send the Auth0 idtoken, 8base auth profile and client id for every graphql query/mutation I make?

How off base am I? Ha. Thanks.

Hey @hello - That’s great that you have auth working fully with the Auth0 libraries.

Create an Authentication Profile in 8base that uses your Auth0 credentials (helpful: https://www.8base.com/8base-academy/setting-up-auth0-as-an-8base-authentication-provider).

Then, whenever Auth0 issues you an id_token make sure that you include it as the authorization header in all your API calls to 8base.

Example:

fetch("8BASE_WORKSPACE_API_ENDPOINT", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${idToken}`,
  },
  body: JSON.stringify({ query: "{ user { id } }" }),
})

8base will NOT issue you any type of token. So you don’t need to doing any type of authentication with 8base. You just need to supply the valid token that was issued by an auth provider THAT has been registered as an Authentication Provider in your workspace.

And YES, every API request you make should have the id_token included in the header!

Thanks a lot Sebastian. Yeah, I have all that it seems:

  • An Auth Profile in 8 base with the various Auth0 credentials and a 8base role (Guest) assigned to it
  • An example user with that Guest role
  • Graphql query to 8base with the Auth0 idtoken in the auth header as bearer token

but I’m doing something wrong because 8base response says:

message: 'User is absent',
locations: [ [Object] ],
path: [ 'user' ],
code: 'UserNotFoundError',
details: { user: 'User is absent' }

Hmm…

By the way, for anyone seeing this: so the process is something like this:

  1. Your app gets idToken from auth provider like Auth0 (via their SDK for example)
  2. Send that Auth0 idToken via auth header bearer token via all graphql queries/mutations/subscriptions to 8base
  3. 8base sees the https://YourAccount.Auth0.com etc info in the token and matches that to the auth profile you set up in 8base and also sees the you@example.com user in the token and sees if that person exists in your 8base users and checks to see if the roles of that auth profile and that user jives…

Yeah?

Actually the missing ingredients may be somehow passing the 8base client id and domain (secure.8base.com) to 8base, yeah?

From 8base auth profile page:

In order to successfully connect your front-end application to your 8base authentication settings, you’ll need to copy and paste the Client ID and Domain in to your code. Make sure that this is done correctly, if not, your authentication settings will not be reflected in your application.

If the non-8base sdk process is used above, how does myapp provide this info to 8base with each of those graphql queries/mutations/subscriptions?

Is 8base client id and domain info sent via the header alongside the idtoken?

Hey @hello - in order to keep helping you at this point I’d need to see your code. Please create a public repo that your comfortable sharing or paste in the relevant code samples to a detailed comment. Thanks.

Hi Sebastian, thanks much. You can have a look here - and specifically the non-Apollo, simple fetch + Auth0 test which produces a “User is absent” error. Note that the only credentials used are basic Auth0 info + the 8base endpoint. The response:

  {
    "data": {
      "user": null
    },
    "errors": [
      {
        "message": "User is absent",
        "locations": [
          {
            "line": 1,
            "column": 3
          }
        ],
        "path": [
          "user"
        ],
        "code": "UserNotFoundError",
        "details": {
          "user": "User is absent"
        }
      }
    ]
  }

The same error results via all types of 8base queries, not just queries trying to access the user, including queries for publicly available data.

I’m sure it’s something simple that’s missing. If you wanted to reproduce:

  1. Add your Auth0 details and 8base API endpoint to an .env.local version of env.remote
  2. Sign In via the link in the nav.
  3. Visit the 8base SSR + Fetch + Auth0 page via the nav.

Thanks!

Is there a definitive list of credentials 8base requires for auth or more info on its error messages?

// Test an auth connection to 8base
const rawResponse = await fetch(config.EIGHTBASE_API_ENDPOINT, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${idToken}`,
  },
  body: JSON.stringify({ query: "{ user { id } }" })
})

This test query above with:

  • a valid Auth0 id token
  • the 8base API endpoint
  • validated Auth0 user with same email as manual-created 8base user

will = a “User is absent” error (see previous post) from 8base.

Thanks much.

Hey there - this means that the user you’re attempting to query as (the email address stored in the idToken’s payload) doesn’t exist in your 8base user’s table (no user record with that email address).

Thanks Sebastian, but I am seeing the same user / email in both Auth0 and in 8base, so it seems there is some other requirement?

In 8base I see that this user is:

  • within System Tables > Users as well as User Management > App Users
  • active
  • assigned to Guest role
  • “is 8 base user = false” (I assume this is just for 8base manager access? But can’t edit that field via data or api explorers.)

And I’m also looking inside the Auth0 JW idtoken to make sure that user email is properly contained within, which it is.

@hello and I’m assuming that you are including the token as an Authorization: Bearer {idToken}.

Couple of other ideas:

  1. Does any role allow the user to see themselves? i.e. maybe an “AppUser” role that let’s the user Read their own record?
  2. Are you sure your querying the correct workspace API endpoint, or the right CI/CD environment?