Production Grade Auth Part I
Last updated
Was this helpful?
Last updated
Was this helpful?
As we discussed in the , we are not going to handle actual authentication ourselves.
We'll delegate this to a 3rd party called . They have a free tier which allows 7000 users and two login providers. It will be enough for our needs. Another very good option is
There is a very good, and complete tutorial ; we'll be adapting it to work for our case.1
First thing you'll do is for a free account. This gives you access to:
After signing up, you will have to create to represent your app. So, in your dashboard, click on the Applications section on the vertical menu and then click on Create Application.
Choose a name for your application, select "Single Page Web App", and press create.
Heading to the Settings tab, search for the Allowed Callback URLs field and insert http://localhost:3000/callback
.
With this value in place, you can click on the Save Changes button and leave this page open.
We'll also add:
Move the back
and run :
Then open auth.js
:
Replace the previous content of auth.js with :
This constant is actually an Express middleware that will validate ID tokens. Note that, to make it work, you will have to fill the <AUTH0_CLIENT_ID>
const with the value presented in the Client ID
field of your Auth0 Application. Also, you will have to fill the <AUTH0_DOMAIN>
const with the value presented in the Domain
field (e.g. bk-tmp.auth0.com
).
note: We will extract those values later so they're not present in the code that you put in a public repo. But for now, it's ok to write them directly in the code. Just don't put those values in a public repo.
note: The other methods in auth.js
are not useful anymore. The logging in and logging out will happen directly between React and Auth0. Our server's job remains to simply check if the user is authenticated, nothing more.
We're going to need a few things:
A piece of code to handle all the Auth0 stuff
A way for our app to know if the user is logged in or not
A way for the user to log in (the equivalent of our previous log in form)
First, move to the front
and install auth0-js.
Then let's create the piece of code. Create a new file, auth.js
in front/src
:
Of course, similarly to the previous time, we'll have to fill AUTH0_DOMAIN
and AUTH0_CLIENT_ID
.
Now, let's use this instead of our custom authentication system.
First, import it in App.js
:
then replace:
note: it's still useful to have those methods; for example, you might want to pop a toast saying "login successful". But we're trying to keep the amount of methods manageable, so for now, remove them.
You can also go ahead and remove the onLoginSubmit
, login
, and the logout
methods, as well as the nick
and token
keys in state
. Auth0
is now handling this, we only have to display the results. Also, you can remove all references to makeUrl({ token: this.state.token})
.
However, we will replace this with Auth0's token
. Instead of sending it in GET
parameters, Auth0 uses a specific header. Everywhere you need to authenticate, you can send:
For example, the getPersonalPageData
url fetching becomes:
This is no different than sending the token like we used to, it's just better to keep it in another part of the request so it doesn't show everywhere all the time.
Finally, let's add a new route, /callback
, and a handler for it:
note: if the app re-renders, it may call login
repeatedly. So with the isLogging
property, we ensure subsequent calls will be cancelled
And you should be ready to go!
We still have a little problem: the logout
button doesn't seem to work. The reason is that, when the button is clicked, the user is logged out, but the state of the App doesn't change, thus, our view doesn't change.
Simple fix:
We simply force the state to change by passing an empty object. It's hacky, but does the trick (there are cleaner methods of doing that, but this will suffice for now).
Congradulation, we have implemented Auth0 a third party user authentification. If you haven't done it before remove the old methods in back/src/auth.js
.
You also have to remove previous route in back/src/index.js
.
app.get('/login', authenticateUser)
And
app.get('/logout', logout)
Don't forget to cleanup the import to avoid warnings
import { authenticateUser, logout, isLoggedIn } from './auth'
Become
import { isLoggedIn } from './auth'
Almost there!
Note if you get an EADDRINUSE
error when your server restarts, edit the start
script in your back/package.json
, and change it to:
The user
object returned by Auth0 looks like this:
We can count with relative certainty on the following three properties:
nickname
name
picture
First, we'll add , a library that helps secure express servers. (Later on, we'll use a different library, don't mistake them!)
: A middleware that validates a JSON Web Token (JWT) and set the req.user with its attributes.
: A library to retrieve RSA public keys from a JWKS (JSON Web Key Set) endpoint.
One problem
, your application forgets the user as soon as the browser is refreshed. Let's fix that in .