OAuthAuthorizer
Protect API Gateway routes with Auth0, Clerk, Okta, Google or any OIDC provider. Give it an issuer and audience; Anvil does the rest.
Pass authorizerId to HttpApi.defaultAuthorizerId; the HttpApi creates the authorizer on its API. API Gateway fetches public signing keys from the issuer's JWKS endpoint to verify token signatures.
Minimal
The smallest config that deploys.
import { App } from '@anvil-cloud/sdk';
import * as anvil from '@anvil-cloud/sdk';
export default new App({
run(ctx) {
const auth = new anvil.aws.OAuthAuthorizer('auth', {
issuer: 'https://your-tenant.auth0.com/',
audience: ['https://api.myapp.com'],
});
const me = new anvil.aws.Lambda('me', {
runtime: 'nodejs24.x',
handler: 'functions/me/index.handler',
});
// Every route now needs a valid token; skipAuth opts a route out.
const api = new anvil.aws.HttpApi('api', {
defaultAuthorizerId: auth.authorizerId,
routes: [
{ method: 'GET', path: '/me', consumer: { lambda: { arn: me.arn } } },
{ method: 'GET', path: '/health', consumer: { lambda: { arn: me.arn } }, skipAuth: true },
],
});
ctx.export('url', api.url);
},
});import anvil_cloud as anvil
def infra(ctx: anvil.Context):
auth = anvil.aws.OAuthAuthorizer("auth",
issuer="https://your-tenant.auth0.com/",
audience=["https://api.myapp.com"],
)
me = anvil.aws.Lambda("me",
runtime="nodejs24.x",
handler="functions/me/index.handler",
)
# Every route now needs a valid token; skip_auth opts a route out.
api = anvil.aws.HttpApi("api",
default_authorizer_id=auth.authorizer_id,
routes=[
{"method": "GET", "path": "/me", "consumer": {"lambda_": {"arn": me.arn}}},
{"method": "GET", "path": "/health", "consumer": {"lambda_": {"arn": me.arn}}, "skip_auth": True},
],
)
ctx.export("url", api.url)
anvil.App(run=infra)package main
import (
"github.com/anvil-cloud/anvil/sdk/go/anvil"
anvilaws "github.com/anvil-cloud/anvil/sdk/go/anvil/aws"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
anvil.Run(anvil.AppConfig{
Run: func(ctx *anvil.Context) error {
auth, err := anvilaws.NewOAuthAuthorizer(ctx.PulumiCtx(), "auth", &anvilaws.OAuthAuthorizerArgs{
Issuer: pulumi.String("https://your-tenant.auth0.com/"),
Audience: pulumi.StringArray{pulumi.String("https://api.myapp.com")},
})
if err != nil {
return err
}
me, err := anvilaws.NewLambda(ctx.PulumiCtx(), "me", &anvilaws.LambdaArgs{
Runtime: anvilaws.LambdaRuntime_Nodejs24_x,
Handler: pulumi.String("functions/me/index.handler"),
})
if err != nil {
return err
}
// Every route now needs a valid token; SkipAuth opts a route out.
api, err := anvilaws.NewHttpApi(ctx.PulumiCtx(), "api", &anvilaws.HttpApiArgs{
DefaultAuthorizerId: auth.AuthorizerId,
Routes: anvilaws.HttpApiRouteArray{
anvilaws.HttpApiRouteArgs{
Method: anvilaws.HttpApiMethod("GET"),
Path: pulumi.String("/me"),
Consumer: anvilaws.HttpApiRouteConsumerArgs{Lambda: &anvilaws.HttpApiLambdaConsumerArgs{Arn: me.Arn}},
},
anvilaws.HttpApiRouteArgs{
Method: anvilaws.HttpApiMethod("GET"),
Path: pulumi.String("/health"),
Consumer: anvilaws.HttpApiRouteConsumerArgs{Lambda: &anvilaws.HttpApiLambdaConsumerArgs{Arn: me.Arn}},
SkipAuth: pulumi.Bool(true),
},
},
})
if err != nil {
return err
}
ctx.Export("url", api.Url)
return nil
},
})
}Good to know
- For Auth0,
audienceis the API identifier (e.g.https://api.myapp.com), not the application's client ID, and the application must be authorized for that API. - API Gateway fetches signing keys from
{issuer}/.well-known/jwks.json, so the issuer URL must match the provider's exactly, including any trailing slash. - Pass
authorizerIdtoHttpApi.defaultAuthorizerId. Every route then needs a valid token unless it setsskipAuth, andscopeson a route requires specific scopes too.
The Full example tab has a complete program. Every argument and attribute is on the Reference tab.