Update: On April 16th 2021, Slash GraphQL was officially renamed Dgraph Cloud. All other information below still applies.
The last in a 4-part series by community author Anthony Master.
Continuing in our series as the fourth and final part we will discuss how to bring authentication into our Dgraph GraphQL endpoint with a custom mutation. So far we should have the following:
@auth
directives.What we need to add to get the final product:
So back in your schema, let’s begin this with creating the type “AuthResponse” that will transport the responses from our script back to the user. Remembering back to our script we wrote in Part 3, we are returned an object with four properties: token, username, expires, and possibly admin. We can take these properties and create the type. By appending the @remote
directive onto the type, Dgraph will not generate any queries or mutations for this type. This is what we are wanting since the data from this type is not actually being stored in the Dgraph database.
type AuthResponse @remote {
token: String
username: String
expires: DateTime
admin: String
}
This type is all good and dandy, but right now it does nothing. Literally nothing at all besides take up space in our schema. To use this type we will need to define our Mutation. Now this is a little tricky because normally Dgraph handles all the work (yes literally, all the work!) in building Queries and Mutations.
Normally by now anyone who has experience with GraphQL and may be new to Dgraph would be used to spending days/weeks/months writing resolvers that point to Queries and Mutations. This will bring back some of those memories, but this time we will do it with only 9 lines of code. We are going to write a Mutation in the schema that will auto generate a resolver based on the parameters that we give it in the schema.
Now to someone who may be newer to GraphQL, let me direct your attention to the fact that we are going to create a Mutation type in our Schema. This single Mutation type will hold all of the custom Mutations that we write. There can only be a single Mutation type and a single Query type.
We will create the Authenticate Mutation which requires a username and a pass, and then use the @custom
directive to tell Dgraph how to resolve this Mutation. We will provide the url to our function we created before, pass the method as POST, pass the JSON body with the username and pass.
type Mutation {
Authenticate(username: String!, pass: String!): AuthResponse @custom(http: {
url: "https://yourdomain.com/functions/authenticate" # wherever you deployed your function to.
method: "POST"
body: "{ username: $username, pass: $pass }"
secretHeaders: ["Content-type"]
})
}
If you noticed in that Mutation @custom
directive, we also passed a secretHeaders property. This is a lesser known property and late documented feature. But you can pass a header defined in the schema to this http request. We are passing the following “Content-type” header.
# Dgraph.Secret Content-type "application/json"
Save this schema and that concludes our lesson. Well I will give you the example of how to use it. To authenticate a user and generate a JWT, all you have to do now, is to use the following mutation:
mutation Login($username: String!, $pass: String!) {
Authenticate(username: $username, pass: $pass){
token
username
expires
admin
}
}
I hope that this series helps you understand how to Authenticate User, generate JWTs, and build a schema that can support group ACL.
Huge thanks from Dgraph to Anthony for coming forward to write some great blogs. If you are using Slash GraphQL or Dgraph and would like to write a community post, reach out to Michael, Zhenni or Apoorv in our discuss community