OAuth 2.1
Flight booking with OAuth-protected tools and interactive widgets
The OAuth 2.1 template is a flight booking server that shows authentication end to end: every tool is protected by an OAuth guard, and widgets guide the user from search to booking.
What's included
OAuth 2.1
Token validation against your provider, such as Auth0, with PKCE and scopes.
Seven protected tools
Search flights and airports, view details and seat maps, and create, view, or cancel orders.
Seven widgets
Search results, flight details, airport search, seat selection, order summary, payment, and cancellation.
Duffel API
Real flight data when you add a Duffel API key.
Create the project
Scaffold the template in your language:
npx @nitrostack/cli init my-flights --template typescript-oauth
cd my-flights
cp .env.example .envCreate an application with your OAuth provider, then set its values in .env:
RESOURCE_URI=https://mcplocal
AUTH_SERVER_URL=https://your-tenant.auth0.com
TOKEN_AUDIENCE=https://mcplocal
TOKEN_ISSUER=https://your-tenant.auth0.com
JWKS_URI=https://your-tenant.auth0.com/.well-known/jwks.json
OAUTH_REQUIRED=true
# Optional: real flight data
DUFFEL_API_KEY=your_duffel_api_keyThen start it with npm run dev.
nitrostack-py init flights --template python-oauthFlight-booking server (Duffel-style) with OAuth 2.1, prompts, resources, widgets, and OAUTH_SETUP.md plus guards/oauth_guard.py.
Follow OAUTH_SETUP.md for JWKS vs introspection, OAUTH_REQUIRED, and scopes. Use @use_guards(OAuthGuard, create_scope_guard([...])).
How tools are protected
Each tool carries the OAuth guard, so it only runs for a caller with a valid token:
@UseGuards(OAuthGuard)
@Tool({
name: 'search_flights',
description: 'Search for flights between airports',
})
async searchFlights(input: any, ctx: ExecutionContext) {
// Only accessible with a valid token
}@use_guards(OAuthGuard, create_scope_guard([...]))The flow: the user calls a protected tool, the server answers with an authorization challenge, the user signs in with the provider, and the client retries with the access token. Tokens are refreshed automatically when they expire.
Project structure
The files that matter:
src/
├── modules/flights/
│ ├── flights.tools.ts # Flight search and details
│ ├── booking.tools.ts # Orders
│ ├── flights.resources.ts
│ └── flights.prompts.ts
├── services/duffel.service.ts # Duffel API client
├── guards/oauth.guard.ts # OAuth guard
├── widgets/app/ # Seven widgets
└── app.module.ts # Root module with OAuthTry it
Ask your AI client things like these:
| Ask | What happens |
|---|---|
| "Find flights from NYC to LAX next week" | search_flights runs after sign-in and the results widget lists flights. |
| "Show me details for the first flight" | get_flight_details opens the flight details widget. |
| "Book this flight for 2 passengers" | create_order returns a booking confirmation. |
