# Oauth

Implements OAuth 2.0/2.1 authorization flows in Fastify applications, configures...

- Repository: https://github.com/mcollina/skills (1960 stars)
- Category: Security
- License: MIT
- Last updated: 2026-10-27
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add mcollina/skills --skill oauth -g -a claude-code -y`
Codex: `npx skills add mcollina/skills --skill oauth -g -a codex -y`
Cursor: `npx skills add mcollina/skills --skill oauth -g -a cursor -y`
Gemini CLI: `npx skills add mcollina/skills --skill oauth -g -a gemini-cli -y`

## Description

Implements OAuth 2.0/2.1 authorization flows in Fastify applications, configures authorization code with PKCE, client credentials, device flow, refresh token rotation, JWT validation, and token introspection/revocation endpoints. Use when setting up authentication, authorization, login flows, access tokens, API security, or securing Fastify routes with OAuth; also applies when troubleshooting token validation errors, mismatched redirect URIs, CSRF issues, scope problems, or RFC 6749/6750/7636/8252/8628 compliance questions.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

## When to use

Use this skill when you need to:
- Implement or debug an OAuth 2.0/2.1 flow in a Fastify application
- Validate tokens, configure PKCE, or set up refresh token rotation
- Secure Fastify routes and plugins with access-control middleware
- Resolve RFC compliance questions or identify security anti-patterns

---

## Step-by-step: Authorization Code + PKCE in Fastify

### 1. Install dependencies

```bash
npm install @fastify/oauth2 @fastify/cookie @fastify/session fastify-plugin
```

### 2. Register the OAuth plugin

```typescript
// plugins/oauth.ts
import fp from 'fastify-plugin'
import oauth2, { OAuth2Namespace } from '@fastify/oauth2'
import { FastifyInstance } from 'fastify'

export default fp(async function (fastify: FastifyInstance) {
  fastify.register(oauth2, {
    name: 'oauth2',
    scope: ['openid', 'profile', 'email'],
    credentials: {
      client: {
        id: process.env.CLIENT_ID!,
        secret: process.env.CLIENT_SECRET!,
      },
      auth: {
        authorizeHost: process.env.AUTH_SERVER!,
        authorizePath: '/authorize',
        tokenHost: process.env.AUTH_SERVER!,
        tokenPath: '/token',
      },
    },
    startRedirectPath: '/login',
    callbackUri: process.env.CALLBACK_URI!,
    pkce: 'S256',               // RFC 7636, always use for public clients
    generateStateFunction: (req) => req.session.state = crypto.randomUUID(),
    checkStateFunction: (req, callback) =>
      req.query.state === req.session.state ? callback() : callback(new Error('State mismatch')),
  })
})
```

**Validation checkpoint:** Confirm `callbackUri` exactly matches a registered redirect URI at the authorization server before proceeding (RFC 6749 §3.1.2).

### 3. Handle the callback and exchange the code

```typescript
// routes/auth.ts
import { FastifyInstance } from 'fastify'

The rest: https://github.com/mcollina/skills/blob/HEAD/skills/oauth/SKILL.md
