⏰ Chapters
- Creating Our AdonisJS 6 Project
- Creating Our Vue 3 Project
- Opening Our Projects
- Setting Up Our AdonisJS 6 Project
- Creating Our Auth Controller & Validator
- Defining Our Register & Login Validators
- Registering A User
- User Access Tokens Provider
- Logging In A User
- Logging Out A User
- Getting An Authenticated Users Details
- Defining Our Auth Routes
- Creating A Register Page & Form
- Creating A Login Page & Form
- Defining Register & Login Page Routes
- Creating An Auth Pinia Store
- Creating An API Helper Function
- Authenticating A User In Our Pinia Store
- Auth Store Login & Register Methods
- Auth Store Logout Method
- Auth Store Get User Details
- Register & Login A User On Form Submit
- Auth User Details & Logout Form
- Testing Our Authentication Flow
AdonisJS 6 Access Token Authentication in 20 Minutes
In this lesson, we'll cover how to implement access token authentication, using opaque tokens, in AdonisJS 6. We'll also take a look at what this would look like on the frontend via a Vue 3 app using Pinia
- Author
- Tom Gobich
- Published
- May 21
- Duration
- 20m 8s
![Tom Gobich](/img/1/profile/avatar_1703713552864.jpg)
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
Transcript
AdonisJS 6 Access Token Authentication in 20 Minutes
-
(upbeat music)
-
When you can't use cookies,
-
that's when access tokens become a great option
-
for authentication.
-
To get ourselves started,
-
let's go ahead and make a directory.
-
So make dir, as we're gonna have two separate projects,
-
our backend and then a separate frontend.
-
We'll call this folder access token authentication,
-
and let's go ahead and CD into that folder.
-
Once we're in here, we can go ahead and npm init,
-
AdonisJS at latest,
-
our new AdonisJS project that we'll call our backend.
-
We'll be using this project as an API,
-
so we'll select the API starter kit,
-
and we'll be using access tokens for authentication here.
-
Again, if you do have cookies available,
-
session authentication is gonna be
-
much more straightforward,
-
but we'll move forward with access token here today.
-
I use Postgres for my database,
-
but feel free to select whichever one's applicable to you,
-
and let's have a go ahead and install our dependencies.
-
While it's doing that,
-
I'm gonna create a brand new tab,
-
and within our same access token authentication folder,
-
let's create a brand new frontend app.
-
For this, I'll be using Vue.
-
So we'll npm create Vue at latest,
-
and I'll call this the frontend.
-
Go ahead and run that.
-
I'm gonna pass on TypeScript for now, as well as JSX.
-
We'll go ahead and add Vue router and Pina.
-
I'll skip Vitus.
-
We won't be doing any testing here today.
-
Skip ESLint and the dev tools for right now.
-
Feel free to select any of those
-
applicable to your use case though.
-
Go ahead and cd into our frontend here,
-
and run npm install.
-
We now have our frontend set up,
-
so I'm gonna clear out of that and boot it up.
-
So npm run dev,
-
and let's jump back over to our AdonisJS tab.
-
Looks like our project created successfully here.
-
So let's go ahead and cd into our backend.
-
We're gonna need to migrate before we start this up.
-
So let's go ahead and get both of these projects open
-
within our text editor.
-
This blue tinted one here, I'm gonna use as our frontend.
-
So hit File, Open Folder,
-
dime in the code,
-
jump into our access token authentication,
-
and I'll select frontend for this blue one.
-
Cool, so here we have our Vue app.
-
Now I'll jump over to our normal looking Visual Studio code
-
that we usually use, File, Open Folder,
-
and for this one, we'll open up our backend,
-
which will be our AdonisJS project.
-
As you can see, we have missing environment variables
-
to take care of, so we'll go ahead and jump
-
into our .env file and take care of that.
-
All we need to worry about for right now
-
is our db_password and db_database.
-
I have a test database that I'd like to reuse,
-
but do apply your applicable database name there
-
or create a new one if you need to.
-
Then we'll enter in our Postgres user's password.
-
Mine just happens to be password.
-
Okay, with that set up,
-
the API and access token starter kit
-
that we used for AdonisJS has us set up
-
with a create_users table that will define our users
-
with a full name, email, password,
-
as well as an ID and created_at,
-
as well as an access_tokens table
-
that has an ID, a tokenable ID,
-
that will relate back to our users,
-
type name, hash, abilities, created_at,
-
updated_at, last_used, and expires.
-
Abilities here are optional,
-
and you can specify them
-
whenever you're creating your token.
-
We're gonna be ignoring them here today
-
as we're just covering the basics of Auth.
-
But do note that they exist
-
and the documentation covers the difference
-
between these abilities and bouncer abilities.
-
We can jump back into our terminal
-
and within our backend, we can run node as migration run.
-
Now, since I am reusing a database
-
that already has stuff applied within it,
-
I'm gonna go ahead and have AdonisJS remove everything
-
that I have preexisting inside of this database
-
and then run my migrations by using migration fresh.
-
And as you can see, that dropped any tables
-
that I had within this database
-
and just migrated forward.
-
Again, if you're working with a brand new database,
-
you just need to run migration run.
-
Cool, so next let's go ahead
-
and create ourselves an Auth controller.
-
So node ace make controller, call this Auth,
-
keep it singular with hyphen S,
-
and we'll add a register, login, logout, in me methods
-
within this controller.
-
And then while we're here,
-
let's go ahead and make a validator as well.
-
So node ace make validator,
-
and we'll just call this Auth.
-
All right, now we're ready to dive into our app
-
and let's go ahead and do our validator first.
-
So we'll dive into here
-
and we're gonna want one validator for registration
-
and one for login.
-
So export const our register validator
-
equals vine compile vine object.
-
We will have an email property
-
of type vine string email,
-
and we can have it normalize that email as well,
-
just using default normalizations.
-
And we also want this to be unique.
-
So we'll have async DB with a callback function,
-
do const match equals await DB from users,
-
select just the ID where email is,
-
and let's grab the value as well.
-
This is the value that the user is trying to register with,
-
pass that into there.
-
And we just care about whether or not we have any results.
-
So we'll just check for the first
-
and return an inverse or match.
-
So if we do have a match,
-
we'll wanna return false here
-
as our unique validation has failed.
-
And if we don't have a match,
-
then we wanna return true
-
as our unique validation is approved.
-
And then we're gonna have a password field here as well.
-
Now we're gonna want the same password validation
-
between both our register and our login validator.
-
So we can define that in one spot,
-
just above both of these as const password
-
or password role equals vine string.
-
And let's just apply a min length of eight for now.
-
Cool, so we can scroll down a little bit here
-
and let's export const login validator equals vine,
-
compile vine object.
-
We'll have our email, vine string email,
-
and we'll go ahead and normalize that there too.
-
We don't wanna check for uniqueness here
-
because this is during our login.
-
So the user already exists inside of the database.
-
And then we just need to add in our password.
-
We'll give that a save, that'll auto format.
-
If you have limp fix on save applied.
-
And now we're ready to dive into our controllers,
-
auth controller.
-
So we'll start with our registration
-
and we're gonna need our request
-
and we'll grab our const data
-
from await request dot validate using our register validator
-
and then we'll need to create a user with that data.
-
So const user equals await user,
-
hit tab to auto import that and pass in our validated data.
-
Once we have that user,
-
then we just need to create a new access token for them
-
and return that token back as a response for this request.
-
So we can just return user dot access tokens
-
dot create and pass in the user.
-
If you're using abilities here,
-
you can specify those as the second argument.
-
By default, this will look something like this
-
to allow all abilities.
-
And then we have additional options as the third argument.
-
By default, these access tokens will not expire.
-
So if you do want them to expire,
-
you can specify an expires in.
-
If you want it to be long live, but still have an expiration,
-
you might set this to something like five years,
-
which I believe is the default duration
-
for the remember me tokens for session authentication,
-
or you could set it to something like 30 days as well,
-
whatever your heart desires there.
-
For us, we're just gonna roll with the defaults.
-
So we'll take both of those off
-
and leave it at just create.
-
Now, if you're wondering where this access tokens comes from,
-
if we take a look at our user model,
-
we do have this with Authfinder,
-
the exact same that we have within session authentication
-
that we can use to check whether or not the user
-
has provided a correct email and password
-
that'll come into play whenever we cover login.
-
But if we scroll down a little bit further here,
-
we're gonna see a static access tokens property
-
that comes from dbAccessTokensProvider for the model,
-
and it provides in our user.
-
This access tokens provider is what provides
-
the actual access token property onto our user,
-
and it's a static property as well.
-
So if we take a look at what we have available on that,
-
so user.accessTokens here,
-
we can get all of the user's tokens.
-
We can create a token, delete a token,
-
find the specific token,
-
and verify the validity of a token as well.
-
So via that API,
-
working with tokens within AdonisJS
-
is rather straightforward.
-
Cool, let's scroll down a little bit
-
and take care of our login next.
-
This is actually gonna look relatively similar.
-
So we'll just have a request,
-
and then we just need to grab our email and password
-
from our await request validate using our login validator.
-
Now, rather than creating user,
-
we just need to verify
-
whether or not the email and password's correct.
-
So we'll do const user equals,
-
and that's where that AuthFinder mixing comes into play
-
that we just saw on our user model.
-
We can await user dot,
-
and that with AuthFinder mixing
-
provides a verify credentials method
-
on our user as a static method.
-
We pass in the UID, which is our email,
-
the user's unique identifier,
-
and then their password.
-
That AuthFinder mixing's also going
-
to hash the user's password.
-
During the creation step,
-
it adds a before save hook on there
-
to check for the password change.
-
And if it finds a mutated password,
-
it will automatically hash it
-
and secure it inside of our database.
-
So that's taken care of automatically as well.
-
And now that we have our user,
-
just like we did with our register,
-
we just need to create an access token
-
to log this user in.
-
So we'll return user dot access tokens, create.
-
You have the same options available here.
-
We're just going to stick with passing
-
our user in for now.
-
And there we go.
-
There's our login.
-
We'll scroll down a little bit
-
and we'll take care of our logout.
-
So we have our auth, await, user, access tokens.
-
And here we'll want to use the delete
-
to delete an access token,
-
essentially logging them out,
-
passing the authenticated user,
-
which we can get via const user equals auth user.
-
And we'll do an exclamation point there
-
to assert that a user is actually authenticated.
-
And we'll ensure that by adding a middleware
-
whenever we define this route.
-
And then we'll provide our user in there.
-
And then we can get the user's current access token
-
via user dot current access token.
-
And then we just need to provide
-
that access tokens identifier as such.
-
And that will delete out that user's access token
-
via its identifier.
-
In turn, essentially logging the user out
-
as that access token will no longer exist
-
inside of our database and can no longer be used
-
to match against an authenticated user.
-
Then we just need to return something here.
-
We'll just do message success.
-
And then lastly, we have our me.
-
We're going to want this method to work
-
whether or not a user's authenticated or not.
-
So we'll just do a silent auth check.
-
This will check the default guard for an authenticated user.
-
And if it's found, then it will populate that auth user.
-
Within our logout, we're going to use a middleware
-
to make that happen automatically.
-
But within our me, we'll manually make that check
-
because we will not have a middleware for this one.
-
And then we'll return user
-
and use that newly populated auth dot user.
-
If the user's logged in,
-
this will be populated with that user's details.
-
And if they're not, our user will not be popular.
-
Cool, so let's go define these routes.
-
Scroll down.
-
We'll have a router dot post slash register
-
using our auth controller.
-
Register method is auth register.
-
We'll have a router dot post slash login.
-
Again, using our auth controller,
-
the login method is auth login.
-
And then we'll have a router dot delete,
-
or you can do a post here as well, slash logout.
-
Auth controller logout is auth logout.
-
Now, the reason I'm using delete here
-
is because we are actually deleting a token
-
out of our database whenever we do logout.
-
So in turn, it is a literal deletion,
-
but that is completely up to you.
-
And then we'll do router dot get slash me
-
using our auth controller.
-
The me method is auth dot me.
-
Now, in terms of our middleware,
-
all we want to do is apply a middleware to log out.
-
Use middleware dot and verify that a user is authenticated
-
in order for them to successfully be able to log out.
-
And this middleware is also what populates
-
that auth user for us.
-
Remember, we're manually checking for an auth user
-
in our me using auth dot check.
-
This middleware will do something similar,
-
but it will also throw an error
-
if a user's not actually authenticated.
-
Cool, so we should now have our backend,
-
our AdonisJS side all set up.
-
So let's dive back into our terminal and boot this up.
-
So npm run dev.
-
We can also hide this text editor back away
-
and jump into our frontend text editor now.
-
The first thing that we're going to want to do
-
is create a new page for registration.
-
So we'll create a new file within here.
-
You can put these inside of a new folder called auth.
-
Now, we're just going to keep everything flat
-
for this lesson.
-
So we'll do register and we'll stick with the view
-
naming convention that they have going on so far.
-
We'll have a template with a form at submit prevent,
-
and we'll call this method submit.
-
Whenever we get to it, we'll have a label,
-
span, our email field,
-
and then we'll have an input type email,
-
vmodel form email,
-
and then let's give this a copy and a paste,
-
switch this from email to password.
-
Type will be password there as well.
-
And our vmodel will now be form.password.
-
Lastly, to end out our form,
-
we're going to have a button type submit
-
with text of register.
-
Cool, now we need to create those.
-
So we'll do script setup.
-
Let's go ahead and import ref from view,
-
and we'll import use router from view router.
-
Let's go ahead and grab our router equals use router,
-
and let's const form equals ref
-
and stub our form with an email and password property.
-
Then we need our async function called submit
-
to do register user.
-
And then once that user is registered,
-
we'll go ahead and push the user to the homepage.
-
Give that a save.
-
Let's give all of this here a copy
-
and create a new view for our login.
-
So login view.view, go ahead and paste those contents in,
-
switch our register text to login, scroll on up,
-
and our to do is the only thing here that changes.
-
Instead of registering user,
-
we just want to log in that user.
-
And then let's go define the routes for them.
-
So we'll jump into our router, index,
-
scroll down a little bit.
-
We'll leave everything as is that currently exists.
-
Define a new path for slash register,
-
apply the name of register,
-
and specify our component there too.
-
And then we'll do this exact same thing
-
for login, just like so.
-
Now there's many different approaches
-
that you could take whenever it comes
-
to actually authenticating your user on the front end.
-
For us here today, I think creating a singular store
-
that houses all of our authentication logic
-
probably gonna be the most straightforward,
-
easy to reference for us.
-
So let's go and create a new store, new file.
-
We'll call this auth.js.
-
Go and create that.
-
We'll import ref as well as unref from view,
-
and we'll import define store from Panea.
-
Export const use auth store equals define store auth,
-
and go ahead and create that.
-
Inside of here, we'll have a const user is ref,
-
and we'll default this to null.
-
And then we'll have a const token,
-
which will be our access token equals ref.
-
And we'll attempt to grab the default value
-
for this from our local storage.
-
Get item, and we'll call that token.
-
Depending on what environment it is
-
that you're working with,
-
you'll need to determine how you wanna store your token.
-
Since we're rolling with the assumption
-
that we don't have cookies available,
-
which if we did, we would just use session authentication,
-
then local storage is an alternative option
-
for us here on the front end
-
to store our token here long-term.
-
And it also makes our token available across tabs
-
if the user tries to open up a new tab
-
with our application open.
-
Cool, let's go and create a helper function now.
-
So async function, we'll call this API.
-
We'll just kind of wrap fetch here a little bit.
-
So we'll have a method URL
-
and a payload defaulted to an empty object.
-
Const response equals await fetch HTTP slash slash,
-
and point this to our AdonisJS server at 3333,
-
and then whatever URL we specify.
-
Then for the config for our request,
-
we wanna pass in our method,
-
specify our headers,
-
that the content type will be application JSON,
-
and then we'll do authorization, provide an error,
-
and then you could unwrap the token there
-
as Codium is suggesting,
-
or we could just reach for token.value
-
to get the actual value of the token there too.
-
And it's this authorization header with the bearer
-
and then the actual token value
-
that's in charge of authenticating our user
-
for each request.
-
Whenever we send a request out to our AdonisJS server,
-
AdonisJS will then check for this bearer token,
-
check it against our access tokens for the user,
-
find the user that way,
-
and that is essentially
-
how this access token authentication works.
-
So if we don't provide this authorization header
-
with our bearer token,
-
you're never gonna be authenticated.
-
But if you do provide it,
-
then it will attempt to find the token for a user
-
and then use that user to authenticate the request.
-
Then we'll have our body.
-
Since we can't specify bodies on get requests,
-
we'll wanna do a ternary check here.
-
So method does not equal get,
-
then we can go ahead and JSON stringify our payload.
-
Otherwise we'll just set that to null.
-
And then lastly, we'll return response JSON.
-
You'll wanna take some extra consideration here
-
for error handling.
-
We're not gonna worry about that in particular here today
-
because there's a wide array of different front ends
-
that you may be using.
-
And our goal here today
-
is just to cover the basics of authentication.
-
Cool.
-
So next let's go ahead and create a function
-
to actually authenticate a user.
-
We'll take in the result of our API request.
-
And then we wanna set the token.value
-
that we have as our ref at the top of the store
-
equal to the result.token.
-
This result is what the result will actually be
-
during our register and login responses.
-
And then we'll go ahead and set this to our local storage,
-
set item token as token.value there as well.
-
Next up, we can go ahead and take care
-
of our login and register method.
-
So async function, login.
-
We'll accept in the payload from the form
-
const result equals await.
-
We'll use our API helper,
-
do a post request to slash login and provide in our payload.
-
And then we just want to authenticate the user
-
with that result.
-
Next up, we'll do our register.
-
It's gonna look relatively similar.
-
We'll have a const result from a post request
-
out to slash register with that payload.
-
And then we just want to authenticate
-
the user there as well.
-
Logout and me are gonna be a little bit different.
-
So async function logout.
-
We don't need to accept anything in for this,
-
but we do need to delete our token.
-
So we'll do await API, send out a delete request
-
or post request if that's how you defined it to slash logout.
-
And then once that succeeded,
-
we'll set our actual token store value to null,
-
our user value to null,
-
and then we'll go ahead and delete that local storage item.
-
So remove item.
-
Lastly, we have our me.
-
So we'll do async function me.
-
We'll do a const result equals await API,
-
a get request to slash me.
-
Once we get that result,
-
we'll want to set that as our user's value.
-
And then we can also return back that value there as well.
-
Lastly, to make all of these accessible,
-
we can return user login, register, logout, and me.
-
We'll keep our helpers and our actual token
-
just as internal properties and methods for our store here.
-
Cool, so now we're ready to start bringing these up.
-
So let's jump into our register view.
-
We have our to-do right here.
-
What we're gonna want to do is grab our auth store.
-
So we can do this right above our router.
-
So const auth equals use auth store.
-
And then in place of our to-do here,
-
we can now do await auth, call our register method,
-
and provide our form in.
-
Oh, we forgot to make use of unref.
-
Let's go jump into our auth store again and do that.
-
So we'll scroll up to our API helper,
-
and we're gonna be passing the ref of our payload in.
-
You could also do form.value,
-
but I like how just passing the form in looks.
-
So we can wrap our payload here in unref
-
to remove the ref reference
-
and just get access to the underlying payload data.
-
Okay, let's jump back into our register view.
-
So that should be good now.
-
The alternative that I was talking about,
-
if you don't want to use unref,
-
is just to do form.value there.
-
Okay, now we just need to do the exact same thing
-
in our login.
-
So import our auth store.
-
So const auth equals use auth store.
-
And then for our to-do, await auth login
-
and provide in our form.
-
Since we have everything pushing back to our home
-
after we log in a register,
-
we'll make our home kind of the designator
-
of whether or not we're logged in.
-
So we'll import use router from uRouter.
-
Const auth equals use auth store.
-
So now we can do auth.user,
-
just like we are within our AdonisJS server
-
to get access to our auth user.
-
Const router equals use router.
-
We can go ahead and try to populate the authenticated user
-
by doing auth.me.
-
I'm gonna leave that without an await,
-
just so that we don't have to worry about suspense.
-
And we'll just add an if to check
-
whether or not it's populated inside of the template.
-
And then we'll also want to add in a logout function.
-
So we'll do async function, logout, await, auth,
-
and then call our logout method.
-
And then we can do router.push
-
and push the user to the login page.
-
For our template, we'll replace this welcome component
-
with a div bif auth.user, div belse, no user found.
-
Inside of our auth user bif,
-
we can go ahead and do, say, a span
-
that says something like welcome auth user email.
-
And then underneath that span,
-
we're gonna want a form at submit prevent
-
that calls our logout method
-
that allows this authenticated user to logout.
-
And then we can just do a button that type submit
-
with logout in there.
-
Cool, so if we give that a save,
-
we should already have the server running.
-
Go ahead and jump into your browser.
-
Let's go to localhost.
-
Oh, forgot to note what port this is running on here.
-
So we'll jump back over to our view, 5173.
-
So colon 5173, there we go.
-
And okay, it looks like we do have something
-
for our auth user, but we shouldn't
-
because we haven't logged in yet.
-
So let's jump back into our front-end text editor.
-
And I bet this is going wrong within our auth store.
-
We scroll down to our me method.
-
We're just plopping result directly into our user
-
where this should be result.user.
-
There we go.
-
So with that saved, actually, while we're also in here,
-
let's jump into our app.view where we have our router links
-
and let's add an additional router link to our login
-
and our register page there as well.
-
Jump back into our browser, give this a refresh.
-
And there we go.
-
So now we see no user found.
-
We don't have a user registered yet.
-
So we'll need to register a user first
-
before we can try logging in.
-
Do [email protected] and give them some password there.
-
Hit register.
-
And there we go.
-
So now we're redirected back to our homepage
-
where we get our [email protected] welcome message.
-
If we refresh, that user is still authenticated.
-
And if we give this a copy,
-
since we're storing this inside of local storage
-
and open this up inside of a different browser tab,
-
we are still authenticated in both of these tabs now.
-
Awesome.
-
We can go ahead and log out,
-
which directs us back to our login page
-
where we can do [email protected], password, and login.
-
And that works too.
-
Furthermore, if we dive into our inspect,
-
take a look at our console for the network requests.
-
I have XHR enabled down there for that.
-
Give this page a refresh.
-
We can see our me goes out.
-
If we take a look at that,
-
specifically the headers, scroll down a little bit,
-
we'll see our request headers
-
where we have our authorization
-
and our bearer and our token value being sent up.
-
Again, that's what AdonisJS is using
-
to match against a user and consider them authenticated,
-
which in turn allows AdonisJS to find that user
-
and return its details back in our response.
-
It's serializing the password as null,
-
so that's being omitted altogether
-
from the response as well for security purposes.
-
And there you go.
-
There's the gist of access token authentication
-
with AdonisJS.
-
And in this case, we used Vue for our front end.
-
1.0AdonisJS Authentication in 15 Minutes16m 7s
-
2.0How To Do Multi Model Authentication with AdonisJS and Lucid ORM18m 29s
-
3.0AdonisJS User Role Authentication in 15 Minutes15m 43s
-
4.0AdonisJS 5 API & Nuxt 3 SSR Authentication in 15 Minutes13m 58s
-
5.0AdonisJS 6 Session Authentication in 15 Minutes15m 18s
-
6.0AdonisJS 6 Access Token Authentication in 20 Minutes20m 8s
-
7.0Three Approaches for Organizing your AdonisJS Business Logic Operations28m 8s
-
8.0How To Make A Simple AdonisJS 6 Package25m 24s
Join The Discussion! (10 Comments)
Please sign in or sign up for free to join in on the dicussion.
guy-aloni
Thank you very much for the clear and detailed explanation!
I wonder whether should be a good idea to add token expiration protection in front-end level, or rely on 409 server response in order to delete the token.
Please sign in or sign up for free to reply
tomgobich
The expiry time should be included with the initial token, so you could store it as well on your client and check it every once in a while to see if time is running up. I would rely on the server though for actually discerning whether it's expired or not.
Please sign in or sign up for free to reply
shahriar
Awesome Tutorial! Thank you.
Just one thing: I get this error:
```
Property 'currentAccessToken' does not exist on type 'never'
```
Please sign in or sign up for free to reply
tomgobich
Thanks Shahriar!
I would say to try restarting your text editor, sometimes it fails to pick up type changes. Apart from that, make sure your auth is configured correctly and double-check to make sure
accessTokens
is on your user model:If you're still having issues, please share a link to the repo or a repoduction and I can see if anything stands out!
Please sign in or sign up for free to reply
guy-aloni
Another question - how do you combine an access-token authentication with social authentication?
https://docs.adonisjs.com/guides/authentication/social-authentication
Please sign in or sign up for free to reply
tomgobich
Social Auth with AdonisJS forms the connection between AdonisJS and the 3rd party service and gives you the tools to discern who a user is. You can then use that info to create a user inside your application. From there, auth is done normally inside AdonisJS.
Please sign in or sign up for free to reply
nnakwe-anslem
Hi. Thank you for the detailed explanation.
I have been having trouble returning a value for the token after login. I keep getting the error message "Cannot save access token. The result '[0]' of insert query is unexpected" even though the token gets saved to the database. I'm not sure what I could be doing wrong.
You can check out the login method here:
https://github.com/ansman58/properties-backend/blob/main/app/controllers/auth.ts
Please sign in or sign up for free to reply
tomgobich
Hi Nnakwe!
Thank you for providing a repo! My best guess, after an initial look, is that you're probably running into an error at line 176 here:
https://github.com/adonisjs/auth/blob/develop/modules/access_tokens_guard/token_providers/db.ts#L176
I don't have MySQL installed currently to be able to test it out though. When I get some free time I can give it a go. You may want to try debugging
result
at line 175 to see exactly what you're getting back. Line 175 is where it's inserting your token and returning back the inserted id. Since you said it's inserting okay, my best guess is thereturning('id')
isn't returning as expected for MySQL or your specific MySQL version.Could potentially be
Something specific to MySQL/MySQL2
The specific MySQL version you have installed on your machine
A bug in KnexJS
A bug in AdonisJS at line 176.
Please sign in or sign up for free to reply
nnakwe-anslem
Thanks for pointing me to the source code. I have taken a look and the problem seems to be with the `returning('id')`, as you correctly pointed out. Is there any configuration I need to apply to MySQL in my codebase to enable the
returning
clause? I don't think it is fully supported in MySQL.EDIT: Switched to postgres and it now works fine. It's A bug in AdonisJS at line 176 when using MySQL.
Please sign in or sign up for free to reply
tomgobich
Looks like there's a previously reported issue with the same, I didn't look though the closed issues last time I checked so I missed it:
https://github.com/adonisjs/auth/issues/241
Sounds like it could potentially be related to how the UUID is defined as the issue creator reported switching that resolved his issue.
If you'd prefer using MySQL, it may be worth looking into and, if it is related, potentially providing your reproduction repository within that issue.
Please sign in or sign up for free to reply