Prisma 1 Forum

Schema Extensions for integrating with Auth0

Hi,
FYI, please refer to https://github.com/graphcool-examples/functions/tree/master/authentication/auth0-authentication
In this tutorial,
1: Please provide me with the detailed use cases for the token returned from “authenticateAuth0User” mutation
2: If I follow this tutorial, how to get currently logged in user? Does the special query, query {user {id}} will be working?
or do I need get the graphcool user id from token?
3: In this tutorial, Authentication flow in app, 6: 'Your app stores the token and uses it in its Authorization header for all further requests to Graphcool’
With this quotation, what does this mean? please provide me with some use cases

Hey Thomas, thanks a lot for your questions!

When calling authenticateAuth0User in the example, we can distinguish a few different cases:

  • Case 1: the passed in Auth0 tokens were not valid

    • as the input is invalid, you’ll receive an error message and nothing else happens.
  • Case 2a: the passed in tokens are valid, and no according user exists yet in Graphcool

    • a new user according to the passed in tokens will be created, a new Graphcool token for that user is created will be returned.
  • Case 2b: the passed in tokens are valid and such a user already exists in Graphcool

    • a new Graphcool token is generated for the existing user and returned.

A Graphcool token obtained from 2a or 2b can be used to authenticate as that user against the Graphcool API. You need to set the Authorization header of HTTP requests to Bearer <token>.

About the user query you mentioned, it will work for now. However, we’ll probably discontinue this query further down the road, but you can easily build your own version of that using Schema Extensions. Here’s an example: https://github.com/graphcool-examples/graphcool-examples/blob/master/instagram/code/authenticatedEmailUser.js

Alternatively, you can also just parse the obtained token on the client, because it embeds the user id.

I hope that gave you a better idea of how custom authentication using Schema Extension works :slight_smile:

Here are some more questions for this topic

  • Do I need to use only User system type for integrating with auth0?
    If I already have ‘Member’ type, cannot I use this type for authentication&authorization?
  • How to distinguish authenticated user for Graphcool permission system?

That’s a great question :slight_smile:

It is possible to use any type for authentication and authorization, but using the User type currently has two differences

  • the user query is only generated for User. If you use Member you need to build your own member query, or parse the member id from the token, as I mentioned above.
  • for permission queries, the variable injected that corresponds to the Authorization header is always called $user_id, no matter to which type it belongs to. So in your case, it is called $user_id, but you need to use it together with SomeMemberExists. Because there is no way to know the type to which $user_id belongs to in a permission query, I would recommend to use only one type for authentication & authorization.

I gave an overview of the special characteristics of User here: Using a custom User type for authentication.

Could you please provide me with some solution for parsing graphcool token and get graphcool user id?

With this quotation, I will appreciate if you could provide some realistic example

Have a look here: https://jwt.io/ There are different libraries available that allow you to parse a JWT.

Did you see the next sentence?

You need to set the Authorization header of HTTP requests to Bearer .

You can find examples for doing that in our examples repository: https://github.com/graphcool-examples
In web clients, you can persist and read the authentication token from localStorage, whereas on React Native, you can use AsyncStorage instead.

My question is what Graphcool api this graphcool token will be used for?
With this example, isn’t this token only for endpoint “/authenticate”?
Which case will this graphcool token be used?

Ah gotcha! You can use this token to authenticate to the Simple/Relay API, as well as the Subscriptions API. If a valid token is included in the Authorization header, the request is considered to be “authenticated” for the permission system.

I’ve created “authenticatedUser” query using schema extensions
Here are things that I have done:
- I have created “authenticatedUser” schema extension as inline function
- SDL:

type AuthenticatedUserPayload {
  id: ID  
}

extend type Query {
  authenticatedUser: AuthenticatedUserPayload!
}

Inline code:

const fromEvent = require('graphcool-lib').fromEvent

function getUser(api, userId) {
    return api.request(`
        query {
            User(auth0UserId: "${userId}") {
                id
            }
        }
    `)
    .then(userQueryResult => {
        console.log(userQueryResult)
        return userQueryResult.User
    })
    .catch(error => {
        // Log error but don't expose to caller
        console.log(error)
        return { error: `An unexpected error occured` }
    })
}

module.exports = function authenticatedUser(event) {
  
  if (!event.context.auth || !event.context.auth.nodeId) {
    return {data: {id: null}}
  }
  
  const userId = event.context.auth.nodeId
  const graphcool = fromEvent(event)
  const api = graphcool.api('simple/v1')
  
  return getUser(api, userId)
    .then(user => {
        if (!user) {
            return { error: `No user with id: ${userId}` }
        }
        return { data: user }
    })
    .catch(error => {
        // Log error but don't expose to caller
        console.log(error)
        return { error: `An unexpected error occured` }
    })  
}

My question is:
1): Will it be working correctly for getting authenticated user on the client side?
2): Please provide me with details of event.context.auth
3): How can I debug this inline code?

Hey Thomas,

I just reformatted your post by surrounding the code snippets with triple backticks `, so it’s easier to read.

  1. The code will not work because of your query:
query {
  User(auth0UserId: "${userId}") {
      id
  }
}

you are passing in the userId but checking for the user’s auth0UserId. This is the correct query:

query {
  User(id: "${userId}") {
      id
  }
}

You can compare to the loggedInUser resolver function in this example: https://github.com/graphcool/modules/tree/master/authentication/email-password

You ca try it out yourself by doing an authenticated request that queries the authenticatedUser query.

  1. You can have a look into event.context.auth by doing console.log(event) in your function. We will soon publish more documentation about the available information in the function context.

  2. You can use console.log statements in your code and invoke the function from the Playground, then check the function logs. Using the new CLI, you can use the command graphcool logs to directly hook into the function log stream instead, which gets you feedback quicker. It’s currently in an open beta, check here for more: Feedback: Framework Preview

Hi,
Could you please check the token issue for auth0-authentication example?
https://github.com/graphcool-examples/functions/tree/master/authentication/auth0-authentication
The issue is:
When I execute authenticateAuth0User mutation for the first time, the returned token is not including userId info
You could confirm this at jwt.io, userId: "undefined"
When I execute this function for the second time, that is, User type already have appropriate user record, the token is including correct userId

I will appreciate if you could check and answer in a short time

I haven’t encountered this problem before :thinking: Could you try checking the code and submit a PR once you figured it out? :slight_smile:

The functions repository is a collection of function examples by the community, maybe someone else encountered this before?

So you mean this is correct issue?
Originally, Grahpcool’s generateAuthToken function need to include the correct userId info?

I’m not quite following. Here’s what I mean:

  • When I was testing the Auth0 example you referred to, I did not observe the issue you are experiencing now. Maybe it only happens if a certain condition is met or you made some adjustments to the code that caused this.
  • I’d appreciate your help in finding out what’s wrong - unfortunatly I can’t reproduce the problem, but I hope that by finding it out and submitting a PR, you can help other community members from running into this problems themselves.
  • about generateAuthToken, you can use it to even generate a token for non-existing types. The only guarantee you have by using this function, is that the token it generates is valid in a sense that the signature is correct. It doesn’t guarantee that a node of specified type and id exists.