Tutorials on Authentication

Learn about Authentication from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

How to use urql authExchange to implement authentication in Next.js

In this article, we will learn how to use the urql authExchange to add authentication with a GraphQL API in a Next.js app.In the last article , we have learnt how to use urql to execute queries and mutations in a Next.js Server-Side Rendered app. In the following sections, we will recap those learnings and build on them to implement authentication using urql exchanges. urql is a lightweight, versatile and extensible GraphQL client for modern frontend apps, with support for React, Svelte, Vue and plain JavaScript. It was introduced as an alternative to existing GraphQL clients like Relay and Apollo . Every query or mutation in urql is modeled as an 'operation', and the system at any moment has a stream of operations issued by various parts of the app. Exchanges are pieces of middleware that transform the stream of operations into a stream of results. This is explained in more detail in the architecture documentation . Some of urql 's core features such as fetching data and caching are also handled via exchanges implemented by the urql team and provided by default. You can also create your own exchanges by implementing functions that conform to the rules defined here . Next.js requires Node to be pre-installed on your system. You can then scaffold a Next.js TypeScript app using the following command in your terminal/command prompt. Once you have a skeleton app set up, you can install the dependencies required for urql . graphql is a peer dependency of urql and provides the underlying GraphQL implementation. No additional type definitions are required since urql is written in TypeScript. next-urql provides the Next.js bindings for urql . react-is is a peer dependency of next-urql , required for react-ssr-prepass to walk the component tree and pre-fetch any data required for rendering. @urql/exchange-auth provides the authExchange that we will implement our API authentication with. Finally, jwt-decode will be used to read the token and determine expiration time. We will also use Material UI to quickly scaffold out a login/register component and one that renders user info. Let us install the required dependencies for Material UI. Let us use the withUrqlClient HOC to wrap our entire app in the urql context. This makes the urql client and hooks usable in the rest of our app. The first parameter to withUrqlClient is a function that returns a ClientOptions object. This can be used to pass configuration into the urql client instance, such as the API URL, custom fetch function, request policy and any additional middleware in the exchanges property. For this tutorial, we will use the Web Collections Demo API from Formidable. In this tutorial, we will build a simple app with two screens - a login/register screen where users will authenticate or sign up to the app, and a user info screen that displays information about the logged in user. We will use the following operations from the Web Collections Demo API: We will use the browser's local storage to persist tokens across page reloads. The authExchange is a piece of middleware for the urql client, which intends to facilitate the typical JSON Web Token (JWT) based authentication flow with a simple and flexible API. It is provided in the @urql/exchange-auth package. We can add the authExchange to the exchanges property when configuring our urql client. The authExchange itself takes four pieces of configuration: The signin , register and refreshCredentials mutations from our API return an object that has the following shape. Let us implement a small helper function that stores the auth state in the browser's local storage. We've added a check for window since we only want this code to run in the browser. When the user logs out, we'd like to clear the auth state from storage. We can now add a couple of convenience functions to fetch the token and refresh token. Let us start implementing the authExchange functions, beginning with getAuth - this function needs to handle a couple of different scenarios: The addAuthToOperation function receives two parameters - the first is the current authState , and the second is the operation that will be executed next. The second parameter is of type Operation and is urql's way of representing an item in the stream of GraphQL requests. Operations have a context that contains the fetch options, either as an object or as an initializer function. We will retrieve the options for the current operation like so. We'll then create a new operation which is basically a clone of the input operation, along with our required override - the addition of our access token to the Authorization header. So the entire implementation of the addAuthToOperation function will look like this: Our API uses the GraphQL error code extension to communicate errors. For the purposes of this tutorial, we will only consider UNAUTHORIZED errors. Token expiry is one of the scenarios when we know the API will error. We are able to determine this by decoding the JWT and reading the exp field which specifies the expiration time. Our API's access token specifies the expiration time as seconds since the Unix epoch. Let us add a buffer of 5 seconds to determine that the token is about to expire. Now, this would work if all of our queries and mutations required the access token to be provided. However, we have mutations such as login and register which do not require the token passed in. We will need to adapt our logic to account for these mutations, and this can be done using the passed in Operation object. The full implementation of the willAuthError function will be as follows. Now that we have implemented all the required functions, the final step is to configure the urql client with the authExchange . Let us create a factory function that receives the ssrExchange and returns a client configuration object. We'll use this on our app's homepage in the next section. Our home page will render the login form when unauthenticated, and a user profile when the user is logged in. We'll use our clientOptions factory function here to provide the urql client to our app. We'll use two mutations login and register from the API in this component. urql 's useMutation hook can be used to consume these mutations within a React component. The useMutation hook returns a tuple containing the current state of the operation, and a function that triggers it. We'll trigger our mutations on submission of the respective form. Here is the full implementation of the page. We'll use the me query from the API to retrieve the user's ID, name and creation time. We can then use urql 's useQuery hook to execute the query. Let us create a simple layout with material-ui components to display the profile data. This will also include a loading indicator and an alert to show any error messages. In this article, we have learnt how to implement JWT authentication with a GraphQL API using urql and @urql/exhange-auth with a Next.js app. We have understood how to apply authentication to queries and mutations, and built a simple app that allows login and registration. All the code used in this article is available on my GitHub .

Thumbnail Image of Tutorial How to use urql authExchange to implement authentication in Next.js

Integrating JWT Authentication with Go and chi jwtauth Middleware

Accessing an e-mail account anywhere in the world on any device requires authenticating yourself to prove the data associated with the account (e.g., e-mail address and inbox messages) actually belongs to you. Often, you must fill out a login form with credentials, such as an e-mail address and password, that uniquely identify your account. When you first create an account, you provide this information in a sign-up form. In some cases, the service sends either a confirmation e-mail or an SMS text message to ensure that you own the supplied e-mail address or phone number. Because it is highly likely that only you know the credentials to your account, authentication prevents unwanted actors from accessing your account and its data. Each time you log into your e-mail account and read your most recent unread messages, you, and like many other end users, don't think about how the service implements authentication to protect/secure your data and hide your activity history. You're busy, and you only want to spend a few minutes in your e-mail inbox before closing it out and resuming your day. For developers, the difficulty in implementing authentication comes from striking a balance between the user experience and the strength of the authentication. For example, a sign up form may prompt the user to enter a password that contains not only alphanumeric characters, but also must meet other requirements such as a minimum password length and containing punctuation marks. Asking for a stronger password decreases the likelihood of a malicious user correctly guessing it, but simultaneously, this password is increasingly more difficult for the user to remember. Keep in mind that poorly designed authentication can easily be bypassed and introduce more vulnerabilities into your application. In most cases, applications implement either session-based or token-based authentication to reliably verify a user's identity and persist authentication for subsequent page visits. Since Go is a popular choice for building server-side applications, Go's ecosystem offers many third-party packages for implementing these solutions into your applications. Below, I'm going to show you how to integrate JWT authentication within a Go and chi application with the chi jwtauth middleware. Let's imagine the following scenario. Within your e-mail inbox, you are asked to re-enter your e-mail address and password on every single action you take (e.g., opening an unread e-mail or switching to a different inbox tab) to continuously verify your identity. This implementation could be useful in the context of accidentally leaving your e-mail inbox open on a publicly-shared library computer when you have to step out to take a phone call. However, if the login credentials are sent over a non-HTTPS connection, then the login credentials are susceptible to a MITM (man-in-the-middle) attack and can be hijacked. Plus, it would result in a frustrating user experience and immediately drive users away to a different service. Traditionally, to persist authentication, an application establishes a session and saves an http-only cookie with this session's ID inside the user's browser. Usually, this session ID maps to the user's ID, which can then be used to fetch the user's information. If you have ever built an Express.js application with the authentication middleware library Passport and session middleware library express-session , then you are probably familiar with the connect.sid http-only cookie, which is a session ID cookie, and managing sessions with Redis . In Redis, the connect.sid cookie's corresponding key is the session ID (the substring proceeding s%3A and preceding the first dot of this cookie's value) prefixed with sess: , and its value contains information about the cookie and user authenticated by Passport. When a user sends an authentication request (via the standard username/password combination or an OAuth 2.0 provider such as Google / Facebook / Twitter ), Passport determines which of these authentication mechanisms ("strategies") to use to process the request. For example, if the user chooses to authenticate via Google, then Passport uses GoogleStrategy , like so: The done function supplies Passport with the authenticated user. To avoid exposing credentials in subsequent requests, the browser uses a unique cookie that identifies the user's session. Passport serializes the least amount of information that's required to map the user to the session. Often, the user's ID gets serialized. By serializing as little information as needed, this means there is less data stored in the user's session. Upon receiving a subsequent requests, Passport deserializes the user's ID (serialized via serializeUser ) into an object with the user's information, which allows it to be up to date with any recent changes. Whenever an Express.js route needs to access this information, it can via the req.user object. With session-based authentication, authentication is stateful because the server persists/tracks the session (either within the server's internal memory or an in-memory data store like Redis or Memcached). With token-based authentication, authentication is stateless . With tokens, nothing needs to be persisted on the server-side, and the server doesn't need to fetch the user's information on every subsequent request. One of the most popular token standards is JSON Web Token (JWT). JWTs are used for authorization, information exchange and verifying the user's authentication. Instead of creating a session, the server creates a cryptographically-signed JWT and saves an http-only cookie with this token inside of the user's browser, which allows the JWT to automatically be sent on every subsequent request. If the JWT is saved in plain memory, then it should be sent in the Authorization header using the Bearer authentication scheme ( Bearer <token> ). A JWT consists of three strings encoded in Base64URL : These strings are concatenated together (separated by dots) to form a token. Example : The following is a simple JWT, which follows the format <BASE64_URL_HEADER>.<BASE64_URL_PAYLOAD>.<BASE64_URL_SIGNATURE> : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c Constructing JWTs is relatively straight-forward. Decoding a JWT is also relatively straight-forward. Try out different signing algorithms, adding scope: [ "admin", "user" ] to the payload or modifying the secret in the JWT debugger . Note : Since a JWT is digitally signed, its content is protected from tampering. Tampering invalidates the token. Having sensitive data in the payload or header requires the JWT to be encrypted. It is recommended to first sign the JWT and then encrypt it . Referring back to the previous Express.js and Passport example, we can remove both Redis, the session middleware and the serialization/deserialization logic (relies on sessions), and then add the Passport JWT strategy passport-jwt for authenticating with a JWT. We no longer have to devote any backend infrastructure/resources to managing sessions with the introduction of token-based authentication via JWT. This will significantly reduce the number of times we need to query the database for the user's information. Like any other authentication method, token-based authentication comes with its own set of unique problems. For example, when we store the token in a cookie, this cookie is sent on every request (bound to a single domain), even those that don't require the user to be authenticated. Although this cookie is stored with the HttpOnly attribute (inaccessible to JavaScript), it is still susceptible to a Cross-Site Request Forgery attack, which happens when a third-party website successfully sends a request to a service without the user's explicit consent due to cookies (those set by the service's server) being sent on all requests to that service's server. If you're running an online banking service, and one of your users is authenticated and visits a malicious website that sends the request POST https://examplebankingservice.com/transfer when they click on a harmless-looking button, then money will be transferred from the user's bank account since their valid token is sent with the request. To mitigate this vulnerability, set the token's cookie SameSite attribute ( sameSite: "lax" or sameSite: "strict" depending on your needs) and include a CSRF token specific to each user of your service in case of malicious subdomains. It should be set as a hidden form field in forms that send requests to protected endpoints upon being submitted, and your service should regenerate a new CSRF token for the user upon them logging in. This way, malicious websites cannot send requests to protected endpoints unless they also know that specific user's CSRF token. Note : By default, the latest versions of some modern browsers already treat cookies without the SameSite attribute as if this attribute was set to Lax . Setting the SameSite attribute of a cookie to Strict restricts a cookie to its originating website only and prevents cookies from being sent on any cross-site request or iframe. Setting the SameSite attribute of a cookie to Lax causes the same behavior as Strict , but relaxes the cross-site request restriction to target only POST requests. The alternative is to store the token in localStorage , but this is not recommended because localStorage is accessible by any JavaScript code running on your website. Therefore, it is susceptible to a Cross-Site Scripting attack, which allows unwanted JavaScript code to be injected into and executed within your website. Common attack vectors for XSS are passing unsanitized user input directly to eval and appending unsanitized HTML (contains a <script /> tag with malicious code). Unlike sessions, an individual JWT cannot be forcefully invalidated when security concerns arise. Rather, there are approaches that can be taken to invalidate a JWT, such as... Fortunately, supporting JWT authentication in a Go and chi application is made easy with the third-party jwtauth library. Similar to the Express.js and Passport example, jwtauth validates and extracts payload information from a JWT for route handlers via several pre-defined middleware handlers ( jwtauth.Verifier and jwtauth.Authenticator ) and context respectively. To demonstrate this, let's walkthrough a simple login flow: Inside of a Go file, scaffold out the routes using the chi router library. This application involves only four routes: ( main.go ) Let's think about these routes in-depth. When the user logs in, the navigation bar should no longer display a "Log In" link. Instead, the navigation bar should display the user's username as a link, which opens the user's "Profile" page when clicked, and a "Log Out" link. This means that all pages that display the navigation bar should be aware of whether or not the user is logged in, as well as the identity of the user. Let's group the GET / , GET /login and GET /profile endpoints together via the r.Group method, and then execute the middleware handler jwtauth.Verifier to seek, verify and validate the user's JWT token. This handler accepts a pointer to a JWTAuth struct, which is returned by the jwtauth.New method. Essentially, this method creates a factory for generating JWT tokens using a specified algorithm and secret (an additional key must be provided for RSA and ECDSA algorithms). The POST /login and POST /logout endpoints can be grouped together to establish them as routes that don't require a JWT token. Behind-the-scenes, jwtauth.Verifier automatically searches for a JWT token in an incoming request in the following order: Once the JWT token is verified, it is decoded and then set on the request context. This allows subsequent handlers to have direct access to the payload claims and the token itself. When the user submits a login form, their credentials are sent to the endpoint POST /login . It's corresponding route handler checks if the credentials are valid, and when they are, the handler generates a token that encodes parts of the user's information (i.e., their username) as payload claims via a MakeToken function and stores the token cookie within the user's browser, all before redirecting the user to their "Profile" page. Note : Underscores indicate placeholders for unused variables. For this simplicity's sake, we're going to accept any username and password combination as long as each is at least one character long. When the user logs out, this token cookie needs to be deleted. To delete this cookie, set its MaxAge to a value less than zero. After this cookie is deleted, redirect the user back to the homepage. Although the GET / , GET /login and GET /profile endpoints rely on the jwtauth.Verifier middleware, they each need to be grouped individually (not together) to add custom middleware to account for these scenarios: When rendering the webpages via data-driven templates , we need to extract the user's username from the JWT token's payload, which we encoded via the MakeToken function, to display it within the navigation bar. The payload's claims can be accessed from the request's context. Once the templates are parsed and prepared via the template.ParseFiles and template.Must methods respectively, apply these templates ( tmpl ) to the page data data via the ExecuteTemplate method. The second argument of ExecuteTemplate method names the root template that contains the other parsed templates (partials). The output is written to the ResponseWriter , which will render the result as a webpage. Note : If building a service, such as a RESTful API, that requires a 401 response to be returned on protected routes that can only be accessed by an authenticated user, use the jwtauth.Authenticator middleware. Finally, spin up the server by running the go run . command. Within a browser, visit the application at http://localhost:8080 and open the browser's developer console. Observe how the browser sets and unsets the cookie when you log in and out of the application, and watch as the user's username gets extracted from the JWT and displayed in the navigation bar. If you find yourself stuck at any point while working through this tutorial, then feel free to visit the main branch of this GitHub repository here for the code. Explore and try out other token standards for authentication. If you want to learn more advanced back-end web development techniques with Go, then check out the Reliable Webservers with Go course by Nat Welch, a site reliability engineer at Time by Ping (and formerly a site reliability engineer at Google), and Steve McCarthy, a senior software engineer at Etsy.

Thumbnail Image of Tutorial Integrating JWT Authentication with Go and chi jwtauth Middleware

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

Firebase Authentication with React

In this article, we will learn how to implement Firebase authentication in a React app.Firebase is an increasingly popular platform that enables rapid development of web and mobile apps. It offers a number of services such as a real-time database, cloud functions and authentication against various providers. In the following sections, we will build a React app that has three screens: Let's create a new project on the Firebase Console . We will call our project react-firebase-auth Once the project is created, we will navigate to the 'Authentication' tab to set up sign-in methods. For now, let us enable sign-ins with a username and password. The only other thing left to do before we start building our React app, is to add it to the Firebase project. Once we add a web app to our project, Firebase gives us the app configuration, that looks somewhat like this: We will add these configuration values into the .env file in our app. Let's use create-react-app to generate a stock React app. We'll call our app react-firebase-auth . Once this is done, we need to add a few dependencies using yarn add : In the app's .env file, we need to add the values supplied by Firebase in Step 1 like so: More information about how environment variables work can be found in the Create React App documentation . In the src folder, let us create a base.js file where we will set up the Firebase SDK. In app.js , we will wrap our app with the Router component from react-router-dom which will allow us to use routes, links and redirects. In order to store the authentication status and make it globally available within our app, we will use React's context API to create an AuthContext in src/Auth.js . We will hold the currentUser in the state using the useState hook, and add an effect that will set this variable whenever the Firebase auth state changes. We also store a pending boolean variable that will show a 'Loading' message when true. In essence, the currentUser will be null when logged out and be a defined object when the user is logged in. We can use this to build a PrivateRoute component which allows the user to access a route only when logged in. The PrivateRoute component takes a component prop which is rendered when the user is logged in. Otherwise, it redirects to the /login route. We can now use this in our app.js file after wrapping our app with the AuthProvider : Let us now implement the screens that make up our app. We can start with the simplest one, which is the home screen. All it will have is the title 'Home' and a 'Sign out' button that logs the user out of the app. This is done by calling the signOut method from Firebase's auth module. Let's now move on to the signup page, which is slightly more complex. It will have the header 'Sign up', with a form that includes text inputs for email and password, and a submit button. We wrap the component with the withRouter HOC to provide access to the history object. When the form is submitted, we will use the createUserWithEmailAndPassword method from Firebase's auth module to sign the user up. We display an alert in case something goes wrong during this process. If the user creation succeeds, we redirect the user to the home ( / ) page using the history.push API. The login page is very similar to the sign up page, with an identical-looking form. The only difference is that we will log the user in rather than create a new user when the form is submitted. The component also uses the currentUser value from our AuthContext , and will redirect to the / route when the user is logged in. And there we have it - we have just implemented a React app with sign up, login and home screens that uses Firebase authentication to register and authenticate users with their email and password. We have now learned how to implement Firebase authentication with a React app. The code used in this article is available at https://github.com/satansdeer/react-firebase-auth and a video version of this article can be found on YouTube .

Thumbnail Image of Tutorial Firebase Authentication with React

Authentication in Angular and Parsing Cookies

Our applications are going to have authenticated users, but how do we pre-render SSR content that is protected only for users of our app? That's what I'm going to show you in this post. Remember that with Angular Universal we can parse incoming HTTP requests on our server of our Angular app and then use that data to show content, depending on who is looking at it. To do this, we inject REQUEST from @nguniversal/express-engine/tokens - and this will let us parse the request from our Angular code but on the server before we render the content. Imagine we have the following UserService on our server: Unfortunately, the request object you have in Angular is not equivalent to what you have in Express.js. There is no .cookies field to easily retrieve a cookie's names and values. We do have request headers, though, so we can extract the cookies that way. Also in the code above, we have a MongoService which lets us access a database - again, on the server, but still in our "Angular" code - as well as a decrypt function, which lets us access to cryptography functions. Cookies are sent by the browser as an HTTP header called cookie . This header contains cookie names and values delimited by the ; character: cookieName=value;cookie2=value2;andSoON=andSoOn . Let's implement the getCookie(name) method that retrieves the value of that header, splits it by the ; delimiter, and returns the value of a particular cookie specified by the function's parameter: Above, we decode the cookie string, and then store it in an object cookies . We can use that function to set up a loggedInCookie object field: Now, to create an observable representing the logged-in user's ID, you can either decrypt the ID value if it's present or return null : While it's great that we can get the userId - we probably want to use that id for something more interesting. For example, we might want to fetch the user object or check for permissions or render some special content. For now, let's fetch the whole user from the database. We'll use this userId to build an observable representing the currently logged-in user: The code above creates the currentUser$ observable by piping userId$ to the mergeMap() operator. Within mergeMap() , you retrieve the given user's data from MongoDB or return null if userId is not present (which means the user is not authenticated). Now that we have this currentUser$ observable, we can implement other helper functions for example, we can add isLoggedIn or getFavorites to our UserService : Angular Universal is incredibly powerful in that it lets us access server-side content when rendering our Angular apps. To learn more, check out: Mastering Angular Universal: Build Blazing-fast Server-Side-Rendered Angular Apps .

Thumbnail Image of Tutorial Authentication in Angular and Parsing Cookies