Protecting routes
The auth plugin reads the access token of every request. When it is valid, ctx.user and ctx.auth are set; otherwise, the request stays anonymous. Guards then decide which routes need a user.
Guards
A 401 carries a WWW-Authenticate: Bearer header (RFC 6750), with error="invalid_token" when the request sent an expired, revoked or invalid token: the client knows it must refresh. Every 401 of the app gets this header, unless it already has one.
The plugin reads the access token from the Authorization: Bearer header, then from its cookie in cookie mode. It never reads the request body: a route of the app can receive an accessToken field of its own, a third-party token for instance, without side effects.
Guards are typed middlewares: in the routes using them, directly or through a group, ctx.user and ctx.auth are defined. They also declare the bearerAuth security scheme (AUTH_SECURITY_SCHEMES), without meta.security: the OpenAPI document marks these routes as secured, and the API reference shows an Authorize button.
The type of the user
ctx.user is what dataProvider.findUserById() returns. Describe it once:
ctx.auth holds the access token data:
Roles
requireRole() checks the roles array of the user, or its role string. When roles are stored elsewhere, getUserRoles(user) returns them:
Routes for everyone, better for users
Without a guard, a route serves anonymous and authenticated users alike: ctx.user is then AuthUser | undefined.
Authentication is not authorization
requireAuth proves who the user is, not what they may access. A route that reads /invoices/:id must still check that this invoice belongs to the user: otherwise, any user can read any invoice by changing the ID in the URL. It is the most common vulnerability of APIs (OWASP API1: Broken Object Level Authorization).
Check access in the query itself when you can (WHERE id = ? AND customer_id = ?), or in a middleware of the group for a whole resource: the Tasks API example checks the membership of a project once, on the /projects/:projectId group.
Reading the cookies yourself
In cookie mode, a route of the app that reads the auth cookies itself must apply the same protection against cross-site requests as the plugin: await auth.isCookieAuthenticationAllowed(ctx.req), which resolves to false for a request the plugin would refuse. See Cookie mode and CSRF.