- 1.Understand the flow of typical authentication processes and how they use JWTs and cookies
- 2.Understand how to implement secure authentication with Auth0
Authentication is both simple and complex. The high-level concept of authenticating a user, then saving that user's authentic "badge" in their browser for subsequent requests is simple. But the lower-level concepts of how to authenticate and how to save that badge in the browser can be complex.
At Rocket Academy we will focus on the higher-level concepts of authentication, and let students dig deeper into the lower-level concepts themselves if time permits and students are interested. We will use Auth0 to implement authentication in our API servers, the industry standard for plug-and-play authentication libraries, comparable to Firebase Auth but with friendlier docs.
What is auth0?
At a fundamental level, all authentication involves 3 steps.
- 1.User enters auth info such as username and password
- 3.If auth info verified, backend sends user's browser a cookie that contains proof of authentication, typically either a JSON web token (JWT) or a session ID that cannot be forged. Browsers store cookies and send them to relevant websites, thereby proving authentication.
Authentication can be challenging because it involves many moving parts. Our server application must store auth info such as passwords and secret keys securely. Our cryptographic algorithm and proof of authentication must be industry-standard. Any bugs in logic or implementation can result in costly hacks.
This is why Rocket recommends we use a plug-and-play, industry-standard auth solution such as Auth0, and only write our own lower-level authentication logic when there is a strong business need and we have experts to test the robustness of our implementation.
Luckily for us, companies such as Auth0 and Firebase have developed plug-and-play auth solutions that are both secure and easy to use. We will use Auth0 for backend authentication because Auth0 has clearer documentation for this use case.
- 1.Create Auth0 account if we haven't already
- 1.Yes, we will be the one coding
- 2.No, we do not need advanced settings
- 2.Create Application
- 1.Choose Single Page Web Application
- 2.Choose React
We should then be directed to a quickstart page like the following, populated with our app's specific domains and IDs. No need to implement anything for now, but read through to understand the high-level process.
- 1.Note application domain and client ID in Application Settings in the Auth0 dashboard. We will need to include these in our app to communicate with Auth0.
- 2.Configure callback and logout URLs to allow redirects back to our apps after logging in or out with Auth0
- 3.Configure allowed web origins to allow auth tokens (JWTs that serve as proof of authentication) to automatically refresh periodically after users have logged in to prevent auto-logout when auth tokens expire
Auth0Providerhigher-order component to enable Auth0 in our apps. Note
Auth0Provideruses React context underneath.
- 5.Add login to app with
useAuth0React hook. Login is as simple as calling the function, letting users login in Auth0's interface, then redirecting back to our app.
- 6.Ditto with the
logoutfunction also from the
returnTo: window.location.origintells Auth0 to redirect to the root URL of the current browser window after logging out.
- 7.Retrieve logged-in user profile information through the
userproperty of the
usercontains properties such as
That's all there is to logging in and out with Auth0 in our frontend! Let's now learn how to send that auth info to our backends for our users to access our backends securely.
Now that we've enabled login in our React apps, we need to learn how to pass an access token from Auth0 to our backends to verify authentication.
- 1.Our frontends authenticate with our backends via an access token that we retrieve from Auth0 on our frontends, send to our backends in a request, and verify using an Auth0 library on our backends.
- 2.To retrieve this access token on our frontends, we need to pass additional
scopeprops to the
audienceis an identifier for our API server that we set in Auth0. This is typically the URL of our API server.
scopeis a property we define in Auth0 that allows us to only allow access to specific backend routes from specific frontend apps. In our case we will keep scope simple and allow access to all protected routes from our frontend.
- 3.Retrieve access token with
getAccessTokenSilentlyto retrieve access token just before we send an API request via Axios. In Auth0's example they use Fetch to send requests, but the concept is the same.
getAccessTokenSilentlyto get a token for the correct domain and scope
- 2.We need to include the access token in an "Authorization" request header with the format shown in this guide. Our API server will need the header in this format to process the access token.
Voila! We are now ready to set up authorisation in our backends for protected routes!
auth0 Frontend Setup
Access Token & Post Request
We will implement authentication in our backend first because there are certain credentials to set up for our API server that we will need to use in our frontends later.
Some routes in our backend will be protected, for example routes to access user data or manipulate data. Based on the logged-in user, backends can decide what data to expose to that user and record changes by that user.
Auth0 Node (Express) API SDK Quickstarts: Authorization
Official Auth0 route-authorisation guide for Express apps
- 1.Create an API in the Auth0 dashboard and give it an identifier, typically a URL that identifies our API. We will use this API identifier as an
audiencein our frontends when retrieving an access token to communicate with our backends
- 2.There is no need to understand RS256 and what a private/public keypair is at the moment, other than knowing they are industry-standard security mechanisms.
- 3.We can ignore scope for now because our apps will be simple and all users should be able to access all features
- 4.Install Auth0's
express-oauth2-jwt-bearermiddleware to verify authentication on our routes
- 5.Initialise the middleware in the root
index.jsfile of our Express app with our API's identifier as
issuerBaseURLprovided by Auth0 (login to Auth0 while viewing this guide to see it)
checkJwtmiddleware in routes that require authentication, and add
checkScopesmiddleware in routes that also require specific scopes.
Great job! We now have authentication and secure access to our APIs!
auth0 Backend Implementation & Testing
Hopefully this gave us a clear high-level overview of what steps we need to implement Auth0 authentication in our frontends, how to send auth info in requests and protect our backends using Auth0 authorisation. We will get more hands-on practice with Auth0 in the upcoming hands-on auth exercise.