Defining Access Token Abilities & DTO
In this lesson, we'll finish up our preparation work by creating a data transfer object (DTO) for our access tokens. Then, we'll define what our token abilities will be within our application's API.
- Author
- Tom Gobich
- Published
- Apr 21
- Duration
- 9m 54s

Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.
Adocasts
Burlington, KY
Get the Code
Download or explore the source code for this lesson on GitHub
Transcript
Defining Access Token Abilities & DTO
-
Now, because the front end portion of this web application
-
is using inertia, we're using DTOs to describe the shape
-
of our Lucid models.
-
So over here on the left-hand side,
-
you'll see a number of different DTOs
-
for each one of the models used inside of this application.
-
Now we're not directly using a model for our access tokens,
-
but we're still gonna wanna use a DTO
-
to describe the shape of an access token
-
whenever it comes to listing them
-
inside of that web application.
-
So real quick, let's go ahead and right-click our DTOs
-
and create a new file here.
-
And we can call this access_token.ts.
-
We can export default class, access_token.dto,
-
and have this extend the base DTO helper
-
from the attacast.com DTO package.
-
Then let's declare that this class will have an ID,
-
and the type of that will be number for us,
-
but the access_token package also supports strings
-
or big ints for this as well.
-
Then we'll declare the type column,
-
which will be of type string.
-
Let's declare the name of the token.
-
That too will be a string.
-
Then we have the token itself,
-
which will be an optional string.
-
The abilities of the token.
-
So we'll have abilities there,
-
and that will be a string array.
-
When the token was last used, so last_used_at,
-
that'll be an optional string.
-
It'll come through as a lux and date time,
-
but we'll want to convert that to a string
-
for the conversion over to our front end.
-
And we also have the expiry date for that as expires_at,
-
that'll be an optional string.
-
And then we have the timestamps of created_at,
-
which is a string.
-
And then we also have updated_at, which is also a string.
-
Then we get ourselves a constructor going
-
that will accept in an access_token of type access_token,
-
which comes from the AdonisJS auth_access_tokens package.
-
And then inside of this constructor,
-
we'll call super since it extends,
-
and then we can fill each one of these out.
-
So I'm going to get multi cursors going
-
by doing option, command and up arrow here,
-
and then option, right arrow to jump over whole words.
-
And I'm just gonna select these property names,
-
and then we can jump back down into our constructor
-
and paste them in,
-
get them all at the same indentation level.
-
And then we can do multi cursors again,
-
option, command, up arrow, prefix it with this,
-
option, right arrow to jump over the whole word,
-
equals access_token.
-
And then paste the property names back in.
-
For the most part, they'll match one to one.
-
We do have a few outliers here.
-
The ID is not called ID, but rather identifier.
-
Next, the token is not actually called token,
-
but rather value.
-
And then this is optional as well.
-
It's only going to be populated
-
whenever we create the access token.
-
So whenever we list out our access tokens,
-
this is not gonna be here.
-
So this is a way for us to show the user
-
what their access token is one time,
-
allow them to copy it to their clipboard
-
and then make use of it wherever they need.
-
And then furthermore,
-
anytime that we list out the access tokens from there,
-
this will be omitted.
-
So in order to get the underlying value of the token,
-
we want to call release there.
-
We need to call release
-
because the token itself is wrapped in a secret helper,
-
which is going to ensure that this token value
-
doesn't accidentally leak without our explicit knowledge.
-
So by releasing that value,
-
we're unwrapping the secret to get the actual value there.
-
Then we have some property name, red squigglies.
-
These are all because these are lux and date times
-
and we need to convert them to strings.
-
So we'll do question mark dot two ISO string,
-
like so for those.
-
And then our name red squiggly, it looks like,
-
oh, this is actually nullable.
-
So we'll do string or null for the name there
-
to make that happy.
-
Okay, cool.
-
So we have our access token DTO set up
-
and ready to go.
-
We'll make use of that here in the next couple of lessons.
-
While we're here setting things up though,
-
let's also set up our tokens abilities,
-
which we've mentioned throughout both the migration
-
as well as this DTO here.
-
So token abilities are the ability of the token itself.
-
We saw this whenever we walked through
-
what we would be building,
-
I think it was in the first lesson.
-
So we'll be able to select whether or not
-
the token should be able to read, create, update, or delete.
-
You can expand upon the abilities from there,
-
but you shouldn't conflate them or confuse them
-
with actual role-based authorization checks.
-
They are abilities that the token's meant
-
to be able to do within our application.
-
So when we get a request
-
with an authenticated organization,
-
we'll be able to check the abilities
-
to see whether or not that token is meant
-
to be able to read, create, update, or delete.
-
So we can normalize our naming for those
-
by defining an enum for them.
-
So within our enums, let's right click new file,
-
and we'll call this token_actions.ts.
-
Within here, we'll define an enum called token_actions,
-
and we'll have a key for read,
-
which will equal the string of read.
-
We'll do another for create, one more for updates,
-
and then a last one for delete.
-
Then we can go ahead and export default token actions.
-
And I missed my comma.
-
There we go, now I got my commas added.
-
And we can set up a quick action
-
to check against these authorizations as well.
-
So we have this abilities action folder
-
where we're using get abilities
-
for our web-based authorization checks
-
to see whether or not the user's able
-
to perform certain actions based off of their role
-
within an organization.
-
So add another ability specific to our access token.
-
So let's right click this new file,
-
and we'll call this authorize_token.ts,
-
and we'll export default class authorize token,
-
and we'll have a static action method
-
that takes in an organization as well as an action.
-
And let's define a type up here at the top
-
called params of type organization,
-
which will be our organization model,
-
and then an action, which will be of type token actions,
-
which we've just defined in enum four.
-
Jump back down to our action method
-
and give that our params type.
-
Inside of this action, we'll want to check and see
-
whether or not the organization's currently used access token
-
has the ability to perform whatever the action is
-
that we're passing in here.
-
So read, update, create, and delete.
-
We can do that with an if check.
-
So if not organization,
-
now, as we've seen alluded to
-
by the type of our API authentication guard,
-
our organization's going to have
-
a current access token property appended onto it.
-
And as a reminder, that's done by our tokens guard
-
within our API auth configuration.
-
However, the model doesn't currently have that property
-
defined as a type.
-
So if we try to use that property,
-
so current access token,
-
TypeScript's not going to know that it's there and available
-
despite that provider adding the value onto the model.
-
So we need to let TypeScript know about that as well.
-
So we can go ahead and jump into our organization model
-
real quick and add it on.
-
So we'll declare current access token
-
as an optional access token type,
-
which comes from the AdonisJS auth access tokens package.
-
This access tokens type
-
is not the direct access token itself,
-
but rather a class that allows us to directly work
-
with the current access token for the request.
-
So if we take a look at that class itself,
-
it's going to have a couple of methods
-
that are static on it,
-
but then it's also going to have instance level methods
-
like the token identifier, the tokenable ID value,
-
which would contain the token itself,
-
the name of the token, type hash created at,
-
and all of that fun stuff, as well as the abilities.
-
And then a couple of methods here
-
that allows us to work with the token,
-
like checking whether or not the token
-
has a particular ability, whether it denies an ability.
-
We can authorize an ability for the access token,
-
check whether or not it's expired,
-
verify the validity of it,
-
and then obviously convert it to JSON.
-
So that is everything that's on that access token class
-
for us to make use of.
-
So we'll give that a save and we can close that file out
-
and jump back now to our authorized tokens,
-
where we're going to want to check and see
-
whether or not this access token
-
allows the action ability being passed into this method.
-
If the token then has the action ability
-
that we're passing into the allows method
-
within the abilities array of the token itself,
-
then it will allow this to move onward.
-
If it doesn't,
-
that's where we're going to want to throw an exception.
-
And we can throw our forbidden exception
-
with the string, the provided token does not have permission
-
to add the action name in, in this organization.
-
So that would read something like,
-
the provided token does not have permission
-
to read in this organization,
-
update, create, delete, whatever the action is there.
-
And then this is a custom exception
-
that we added into the previous series
-
with a status code of 403.
-
So by throwing the exception there,
-
we are forbidding the action
-
and stopping the request from continuing onward.
-
And we can give ourselves a little bit of a nicer API
-
to work with here as well
-
by adding specific methods to individual actions.
-
So for example, we could add a read method
-
that just takes in the organization
-
and then returns this action
-
and then passes that organization in
-
and then the action name of token actions.read.
-
And then we can copy that, paste it in three more times.
-
So two and three, renaming one to create,
-
the other to update,
-
and the last one to delete or destroy.
-
And we also want to update the actions
-
for their method name there as well.
-
So update and then delete.
-
So as we build out our API controllers,
-
we're going to be able to use this class
-
to then authorize whether or not that token
-
has the ability to perform an action
-
against the current access token populated
-
and used for the request.
-
Introduction
-
API Authentication
-
2.0Configuring Access Token Auth on top of Session AuthLesson 2.010m 50s
-
2.1Separation of API & Web Auth Guard ConcernsLesson 2.19m 17s
-
2.2Defining Access Token Abilities & DTOLesson 2.29m 54s
-
2.3Creating Access Tokens Part 1: AdonisJSLesson 2.310m 19s
-
2.4Creating Access Tokens Part 2: Inertia/VueLesson 2.412m 44s
-
Opaque Access Tokens (OAT) vs JSON Web Tokens (JWT)Lesson 2.53m 57s
-
Listing an Organization's Access TokensLesson 2.68m 3s
-
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!