Search code examples
access-tokenstronglooploopback

Link AccessToken to a user in Loopback


I wanted to add a custom attribute (expireAt) to the access token for it to be used by MongoDB to automatically remove the expired access token when expired.

Adding the custom attribute while creating the access token using AccessToken model is working well:

const ttl = 600;

const expireAt = new Date();
expireAt.setSeconds(expireAt.getSeconds() + ttl);

const token = await AccessToken.create({ ttl, expireAt });

However, when I want to create an access token for a user, I can't add the custom attribute exprieAt when creating the token, so I have create first, and then update it:

const ttl = 600;

const expireAt = new Date();
expireAt.setSeconds(expireAt.getSeconds() + ttl);

// Create the access token for the user
const token = await user.createAccessToken(options);
// Update token to set the custom date and time to expire
token.expireAt = expireAt;
token.save();

// Return the token together with the user data
return Object.assign({}, token.toJSON(), { user });

Is there a way I can create the token for a user with the custom attribute (either using instance method or model method is fine), without doing two steps - create and update?


Solution

  • So it seems that AccessToken model has the relationship set up with the user via userId attribute (ref: https://github.com/strongloop/loopback/blob/master/common/models/access-token.json#L27).

    {
      "name": "AccessToken",
      "properties": {
        "id": {
          "type": "string",
          "id": true
        },
        "ttl": {
          "type": "number",
          "ttl": true,
          "default": 1209600,
          "description": "time to live in seconds (2 weeks by default)"
        },
        "scopes": {
          "type": ["string"],
          "description": "Array of scopes granted to this access token."
        },
        "created": {
          "type": "Date",
          "defaultFn": "now"
        }
      },
      "relations": {
        "user": {
          "type": "belongsTo",
          "model": "User",
          "foreignKey": "userId"
        }
      },
      "acls": [
        {
          "principalType": "ROLE",
          "principalId": "$everyone",
          "permission": "DENY"
        }
      ]
    }
    

    To link the token to the user, we only need to pass in the value userId:

    AccessToken.create({ ttl, expireAt, userId });