Skip to content

Guards & Scopes

ApiKeysGuard reads the bearer token, verifies it, and attaches an ApiKeyContext (containing tenantId, environment, and the matched scopes) to the request. Authorization decorators run on top of that context.

Protecting a route

typescript
import { Controller, Get, UseGuards } from '@nestjs/common';
import { ApiKeysGuard, RequireScope } from '@nestarc/api-keys';

@Controller('reports')
@UseGuards(ApiKeysGuard)
export class ReportsController {
  @Get()
  @RequireScope('reports', 'read')
  list() {
    return [];
  }
}

Apply @UseGuards(ApiKeysGuard) at the controller level when every route uses API-key auth. Use @RequireScope(resource, level) per handler to specify the required permission.

Scope model

Scopes are { resource, level } pairs:

  • resource is a free-form string like reports, invoices, projects.
  • level is read or write.
  • write implies read — a key with reports:write satisfies @RequireScope('reports', 'read').
typescript
const { id, key } = await apiKeys.create({
  tenantId: 'tenant_123',
  name: 'Primary',
  scopes: [
    { resource: 'reports', level: 'write' }, // also grants reports:read
    { resource: 'projects', level: 'read' },
  ],
});

Reading the context in a handler

typescript
import { Controller, Get, Req, UseGuards } from '@nestjs/common';
import { ApiKeysGuard, ApiKeyContext } from '@nestarc/api-keys';

@Controller('reports')
@UseGuards(ApiKeysGuard)
export class ReportsController {
  @Get()
  list(@Req() req: { apiKey: ApiKeyContext }) {
    return this.service.listForTenant(req.apiKey.tenantId);
  }
}

ApiKeyContext surfaces:

  • id — the key's record id
  • tenantId
  • environment (live | test)
  • scopes — the full scope list granted to this key

Failures

SituationError codeHTTP
No Authorization headerapi_key_missing401
Header doesn't match the expected formatapi_key_malformed401
Key not found or secret mismatchapi_key_invalid401
Key was revokedapi_key_revoked401
Key is past expiresAtapi_key_expired401
Route requires live but key is test (or vice versa)api_key_environment_mismatch403
Key lacks the required scopeapi_key_scope_insufficient403

Branch on the code value — not the message — in clients and structured logs.

Released under the MIT License.