Passwordless authentication with Magic.link and GraphQL question

There is an example of a todo app using passwordless authentication using magic.link service.

I have tried to recreate the example using GraphQL with a schema like this:

type User {
   email: String! @unique
   todos: [Todo] @relation
}

type Todo {
   title: String!
   completed: Boolean!
   user: User!
}

How do I create a collection with permissions using the GraphQL schema similar to the FQL example?

Everything works fine in the playground with the default authorization key, but when I replace the key issued with Tokens() I get “Invalid authorization header.” error.

What kind of security roles do I need to create for this usecase?

Hi @ciocan and welcome!

you can create a role this way:

CreateRole({
  name: "user_todo",
  membership: {
    resource: Collection("User")
  },
  privileges: [
    { resource: Collection("User"), 
      actions: 
        { 
          read: Query(Lambda("ref", Equals(Var("ref"),Identity()))),
          write: Query(Lambda(["oldData", "newData", "ref"],Equals(Identity(),Var("ref"))))
        } 
    },
    {
      resource: Collection("Todo"),
      actions: {
        read:   Query(Lambda("todoRef", Let({todo: Get(Var("todoRef")),userRef: Select( ["data", "user"], Var("todo"))},Equals(Var("userRef"), Identity())))),
        write:  Query(Lambda(["oldData", "newData"],And(Equals(Identity(),Select(["data", "user"], Var("oldData"))),Equals(Select(["data", "user"], Var("oldData")),Select(["data", "user"], Var("newData")))))),
        delete: Query(Lambda("todoRef", Let({todo: Get(Var("todoRef")),userRef: Select( ["data", "user"], Var("todo"))},Equals(Var("userRef"), Identity()))))
        
      }
    }
  ]
})

This role is applied to all documents in User collection (your users), and allows the users authenticated with Login() function to:

  • read and write it’s own document in user collection (e.g. update password)
  • read/write/delete their own todo documents

This is a very simple role you can implement as per your needs.

Let me know if it is what you are looking for.

Luigi

this works only when using the Login() function.

Because the flow uses passwordless authentication, the token is created like this:

Create(Tokens(), { instance: Ref(Collection("User"), "281177222889341447") })

How to setup roles for this?

Hi @ciocan,

It works the same since Login() creates an entry in the Tokens() collection as you are doing.

Please, give a try and let me know if this works.

Luigi

Hi Luigi,

Something must be missing. After I created the role, I did the following:

Create(Tokens(), { instance: Ref(Collection("User"), "281177222889341447") })

{
  ref: Ref(Ref("tokens"), "281363047855948295"),
  ts: 1604587562405000,
  instance: Ref(Collection("User"), "281177222889341447"),
  secret: "xxx"
}

>> Time elapsed: 207ms

Then, in the GraphQL playground, I set the authorisation token as the secret created above then query the user with the same id.

Hi @ciocan,

please contact me in private.

Luigi