> For the complete documentation index, see [llms.txt](/docs/llms.txt)

# Step 3 - Protected Pages | FusionAuth Docs

Learn how to use FusionAuth by using an example application that has a protected page defined.

# Step 3 - Protected Pages

[Edit on GitHub](https://github.com/FusionAuth/fusionauth-site/blob/main/astro/src/content/docs/get-started/start-here/step-3.mdx)

[View Markdown](/docs/get-started/start-here/step-3.md)

Now that we have the FusionAuth and the example app running, let's take a look at how the application protects pages that require a user to be logged in.

This process is also known as access control. It is the process of controlling the users that have access to specific pages and functions of an application. The first step is to protect a page such that only users that have logged in can view it.

Open the file `src/index.mts` and find the route named `/account`. It should look something like this:

```typescript
app.get("/account", async (req, res) => {
  if (!await sdk.userHasAccess(req, res, ["admin", "user"])) {
    res.redirect(302, '/login');
    return;
  }

  res.sendFile(path.join(__dirname, '../templates/account.html'));
});
```

The first check is where the application determines if the user is logged in or not. This is done by calling the SDK function `userHasAccess` (you can ignore the last parameter, which we will cover in the next section). This function returns true if the user has access, which implicitly verifies that they are logged in. Let's take a look at this function.

Open the file `src/sdk.ts` and find the function named `userHasAccess`. One note is that this application uses `jose` which is a Node library used for validating and parsing [JSON Web Tokens (JWTs)](/docs/lifecycle/authenticate-users/login-api/json-web-tokens). If you want to learn more about `jose`, you can visit the project at Github here: [https://github.com/panva/jose](https://github.com/panva/jose)

The `userHasAccess` method begins by loading the user from the request. This is accomplished by calling the `getUser` function of the SDK, which returns the user's access token. If the access token comes back `null`, that means the user is not logged in and this function returns false.

```typescript
async userHasAccess(req: Request, res: Response, roles: Array<string>): Promise<boolean> {
  const jwt = await this.getUser(req, res);

  // @ts-ignore
  if (!jwt || !jwt.roles || jwt.roles.length === 0) {
    return false;
  }

  // @ts-ignore
  return jwt.roles.some(role => roles.includes(role));
}
```

Let's take a quick peek at the `getUser` function of the SDK. This function looks like this:

```typescript
async getUser(req: Request, res: Response): Promise<JWTPayload> {
  let accessToken = req.cookies[this.configuration.accessTokenCookieName];
  if (!accessToken) {
    return null;
  }

  let payload: JWTPayload;
  try {
    payload = (await jose.jwtVerify(accessToken, this.JWKS, {
      issuer: this.configuration.oauthIssuer,
      audience: this.configuration.applicationId,
    })).payload;
  } catch (e) {
    payload = await this.handleJWTException(req, res, e);
  }

  return payload;
}
```

The first part of this function loads a cookie from the request that contains the user's access token. The access token is part of the OAuth specification, and is generated after the user successfully logs in. FusionAuth uses JWTs for access tokens.

The second part of this function verifies that the JWT is valid using `jose`'s `jwtVerify` function. This function validates the cryptographic signature of the JWT and also ensures that the JWT is not expired and all of the claims are valid.

We won't go into detail about JWTs and all of the claims here, but you can read our [OAuth token documentation](/docs/lifecycle/authenticate-users/oauth/tokens) to learn more.

If the `getUser` function returns `null`, this means that the user is not logged in. The user is then redirected to the login page.

You can also take a look at the `/make-change` route and you'll find that it uses this same approach to ensure that the user is logged in.

In the next step, we'll expand on this and cover role-based access controls.

## Next steps[#](#next-steps)

[<-Step 2: Login Button](step-2)[Step 4: Role-Based Access Control->](step-4)