Get Token meta data from within a client which was signed into by that token?

Using q.Identity() one can get the logged in instance document ref in a signed in fauna client. However, I want to store metadata on the Token, as described in https://docs.fauna.com/fauna/current/api/fql/functions/tokens

Now, since I do not use Login(), but rather a UDF, I can add metadata like so:

Create(
  Tokens(), 
  {
    instance: Ref(Collection("Books"), "234"), 
    data: {
      createdBy: Ref(Collection("Users"), "345")
    }
  }
)

I would get the secret from this call and use it to open a fauna js client:
const client = new faunadb.Client({secret: 'the-secret'})

Now, running a query with this client, I can use q.Identity() to return Ref(Collection("Books"), "234").
But how can I access data.createdBy from within the query?

I would like to avoid using q.Select(["data", "createdBy"], q.KeyFromSecret('the-secret')) since that makes it more tedious to use in my JS helper functions.

So - how should I access Token meta data from within the JS fauna client which is signed in with that Token?

(A solution for this is also necessary to access meta data within ABAC)

1 Like

Hey @aorsten,

Currently not possible, but…

at this point we do not have a CurrentToken() kind of function so there is no way to do that.

… it’s already in our backlog, and …

I have pondered about the same thing and actually also asked to implement something like that. There were already ideas on the table, I’ll add your request to the ticket. I was also tempted to add data on my token (since it’s also document anyway) and use that in my ABAC roles or UDF functionality. Being able to do that would be great.

… there is a workaround

That said, it’s definitely not impossible to have something similar but it’s a bit cumbersome.
You can make a collection ‘tokens’ instead and make sure that if you create a new token, you always first create a new document and then create a token for that document.

In my use case, I wanted to have a difference between ‘refresh’ and ‘access’ tokens and hoped to put a type on the token. Instead I implemented a ‘session’ collection on which I create a document and a token when I want to retrieve a refresh token.

function CreateRefreshToken(accountRef) {
  return Let(
    {
      session_refresh: Create(Collection('account_sessions'), {
        data: {
          account: accountRef,
          used: false
        }
      })
    },
    {
      token: Create(Tokens(), {
        instance: Select(['ref'], Var('session_refresh')),
        // 8 hours is a good time for refresh tokens.
        ttl: TimeAdd(Now(), 8, 'hour'),
        data: {
          // We do not do anything with the type, it's just for readability in case we retrieve a token later on
          type: 'refresh'
        }
      }),
      session_refresh_doc: Var('session_refresh')
    }
  )
}

As you can see, this document refers to the ‘account’ which is the actual identity that I will authenticate. Of course, this makes your roles slightly more complex since you have to follow that indirection. My Identity() will be the session document and I’ll get the account via a Get. It’s probably clearer when I show you how an account_session looks like:

Refresh tokens in my case are created on the account_sessions and in my roles/UDFs I follow the account ref of that session back to the account.
Access tokens are created on accounts.

I know this is a cumbersome workaround, as I mentioned, I asked this feature myself and will add your request to the ticket :slight_smile:. I do hope this helps already in the meantime :slight_smile:

1 Like