# Protecting Private API Docs with Role-Based Access: A Portal vs Static Hosting

**Quick answer:** Protecting private API documentation requires an authentication layer that identifies the user and an authorization layer that decides what they may see. A hosted developer portal bundles identity, roles, and access management out of the box, while a self-hosted static site needs you to place an auth gate in front of the files, often through a reverse proxy or edge function. The portal is simpler and centrally managed; the static route gives you full control but puts the access design on you.

## Authentication versus authorization

These two are often conflated but solve different problems. Authentication establishes who is visiting, typically through SSO, OAuth, or an identity provider. Authorization determines which documents or API references that identity is allowed to access. A private docs solution needs both; a login page alone does not restrict content if every authenticated user can see everything.

| Layer | Responsibility | Common mechanisms |
| --- | --- | --- |
| Authentication | Confirm identity | SSO, SAML, OIDC, MFA |
| Authorization | Gate content by role | RBAC, groups, access policies |
| Session handling | Maintain and expire access | Tokens, cookies, refresh |

## How a hosted portal handles it

A developer portal integrates with an identity provider and exposes role configuration, so you map groups to sections and the platform enforces the rules on every request. The portal also manages sessions, token refresh, and the access-denied experience. This is the main operational advantage: the access logic lives in a maintained system rather than in infrastructure you build.

`# Conceptual mapping: identity-provider groups to docs sections access: - group: platform-team allow: ["/*"] - group: partner-readonly allow: ["/public/*", "/api/v2/reference/*"] deny: ["/internal/*"]`

## Putting a gate in front of a static site

A static build is just files, so access control cannot be embedded in the HTML. You place an auth layer at the edge or reverse proxy that verifies a session before serving the files. Here is the shape of an edge function that checks a token and a role claim.

The reverse proxy equivalent validates the session and applies the same role rules before forwarding to the static origin. The important point is that protected content must never be reachable by a direct storage URL that bypasses the gate.

## Why client-side gating is not enough

Adding a login screen in JavaScript and hiding navigation elements does not protect the underlying files, because the content is still downloaded and readable in the browser. Real access control runs on the server or edge before any protected bytes are sent. Treat any solution that only hides links as cosmetic rather than security, and verify with an unauthenticated request that a protected URL returns 401 or 403 rather than the document.

## Role design and least privilege

Start from least privilege: default users to the smallest set of pages they need and grant broader access by role. A small number of well-defined roles, such as internal engineer, partner, and support, is easier to audit than many overlapping rules. Review role memberships when people change teams and integrate with your identity provider's group lifecycle so access is removed automatically. Document the mapping so a reviewer can see who can reach sensitive internal references.

## Tradeoffs and how to choose

Choose a hosted portal when you want turnkey SSO, role management, and a maintained access experience, and you accept the platform's model. Choose a self-hosted gate when you need full control over the identity integration, network boundary, or compliance requirements, and you are prepared to build and audit the auth layer. A hybrid is common: public docs as a static site and private references behind a portal or an edge gate, using the same OpenAPI source but exposing different sections.

## Token validation details at the edge

A gate is only as strong as its verification. When the edge checks a JWT, it must validate the signature against the identity provider's keys, confirm the issuer and audience match, and reject an expired token rather than decoding it without verification. Cache the provider's signing keys briefly and refresh them on rotation so a key update does not lock everyone out. Also distinguish a missing or malformed token, which should return 401, from a valid token lacking the required group, which should return 403, and log the authorization decision without recording the token itself. These details turn a simple reverse proxy into a real access boundary.

## Frequently asked questions

### Can a static site really have role-based access?

Yes, but the enforcement must sit at the edge or reverse proxy, not in the static files. The gate verifies identity and role before serving protected content, and direct storage access must be blocked.

### What is the difference between 401 and 403 here?

401 means the request is not authenticated or the token is invalid, while 403 means the identity is known but not allowed to view that section. Both should appear before any protected bytes are sent.

### Is hiding navigation links enough to protect a page?

No. Hiding a link does not prevent a direct request. Always verify with an unauthenticated call that the protected URL itself is blocked.

### How many roles should I define?

Use a small, clear set reflecting real audiences, and default to least privilege. Many overlapping rules become hard to audit and tend to grant more access than intended.

This is part of the [Powerduck vs Redocly: OpenAPI Docs and Linting](https://www.powerduck.com/blog/powerduck-vs-redocly/) — start there for the full comparison of portal features and self-hosted documentation.

