Token Update

How to update or revoke tokens for authenticated users

The token that is issued in a connection token event1 helps services to determine what resources the connection should have access to. But sometimes a user’s access may change as they are granted new, or denied previous, permissions. Or maybe the user is kicked out, and should have their access revoked all together.

In order to update or revoke tokens, the RES protocol provides a way to identify tokens, and request for them to be updated. Let’s learn how to do this.

Token ID

In Chapter 7 - Access Control, we learned how to issue an access token for a connection, using a connection token event1. The event body has two properties:

  • token - access token for the connection.
  • tid - optional token ID used to update/revoke a token.

By setting the tid, token ID, property to a value that identifies the user, such as the user ID or username, we can later update or revoke that token.

In code we can set a token like this:

nats.publish("conn." + cid + ".token", JSON.stringify({
	"token": {
		"userId": 42,
		"role": "guest"
	},
	"tid": "42"
}));

Note

If the service uses a numeric user ID (eg. 42), the tid value must be the string representation of that ID (eg. "42").

Updating or revoking a token

Whenever a service wants to update one or more tokens, it can send a system token reset event2 where it includes a list of all the affected token IDs. This will trigger Resgate(s) to send auth requests3 for all connections with a matching token ID.

Subject

The subject of the event is:

system.tokenReset

Event message

The event message is a JSON object containing the following properties:

  • tids - an array of token ID (tid) strings.
  • subject - a NATS subject to which Resgate(s) should send their auth requests3.

Tip

The NATS subject doesn’t have to follow the naming pattern of an actual auth request handler.
In the example below, instead of:

auth.authservice.logout

the subject could be any valid NATS subject:

clearMyToken

Example

Revoking the token for user 42 could look like this:

// Auth request handler for clearing/revoking tokens.
nats.subscribe('auth.authservice.logout', (msg, reply) => {
	// Parse out the connection ID (cid).
	let { cid } = JSON.parse(msg);
	// Clear the token for this connection.
	nats.publish("conn." + cid + ".token", JSON.stringify({
		"token": null
	}));
	// Send successful response.
	// Resgate discards results from system.tokenReset auth requests.
	nats.publish(reply, JSON.stringify({
		"result": null
	}));
});

// Send system.tokenReset event to update/clear the token of user 42
nats.publish("system.tokenReset", JSON.stringify({
	"tids": [ "42" ],
	"subject": "auth.authservice.logout"
}));

Tip

The auth request also contains all the other info, such as header and token, which may be used for creating a new token, instead of clearing it:

let { cid, header, token } = JSON.parse(msg);