Skip to main content
Traffic Policy gives you powerful options for adding authentication to your endpoints—without touching your application code. Whether you need a quick login prompt for a demo, OAuth for production apps, or JWT validation for APIs, ngrok has you covered.
For a deeper dive into authentication concepts and when to use each method, see the Authentication with ngrok blog post.

Authentication and access control methods

MethodBest for
Basic AuthQuick demos, internal tools
OAuthUser-facing apps with social login
OpenID Connect (OIDC)Enterprise apps with corporate IdPs
JWT validationAPIs with token-based auth
IP restrictionsNetwork-level access control
Mutual TLS (mTLS)Machine-to-machine, zero trust

Basic Auth

HTTP Basic Auth is the simplest form of authentication—it prompts visitors for a username and password with zero setup. Use it for one-off demos or sharing local development work.
on_http_request:
  # Prompt for username and password with up to 10 credential pairs
  - actions:
      - type: basic-auth
        config:
          credentials:
            - username: user1
              password: password123
            - username: user2
              password: securepass456
See the basic-auth action docs for more information.

OAuth

OAuth lets you leverage existing identity providers like Google, GitHub, or Microsoft for authentication. Users sign in with their existing accounts—no password management required. ngrok supports these OAuth providers out of the box with managed applications:
  • Google
  • GitHub
  • GitLab
  • LinkedIn
  • Microsoft
  • Twitch

Simple OAuth setup

on_http_request:
  # Redirect unauthenticated users to Google sign-in
  - actions:
      - type: oauth
        config:
          provider: google

Restrict access by email domain

Use expressions to restrict access based on email domain, allowing only users from specific organizations.
on_http_request:
  # Authenticate with Google OAuth
  - actions:
      - type: oauth
        config:
          provider: google
  # Only allow users with company email addresses
  - expressions:
      - "!actions.ngrok.oauth.identity.email.endsWith('@your-company.com')"
    actions:
      - type: deny
        config:
          status_code: 403
For more OAuth examples—including session controls, multiple email domains, custom OAuth apps, and login/logout flows—see the oauth action docs and the OAuth protection guide.

OpenID Connect (OIDC)

OIDC connects to managed corporate identity providers like Okta, Azure AD, or any OIDC-compliant IdP. This gives you fine-grained control over authentication while leveraging your existing identity infrastructure.

Basic OIDC setup

on_http_request:
  # Authenticate with your OIDC provider
  - actions:
      - type: openid-connect
        config:
          issuer_url: https://accounts.google.com
          client_id: "<your-oidc-client-id>"
          client_secret: "<your-oidc-client-secret>"
          scopes:
            - openid
            - profile
            - email

Pass identity tokens to your service

Forward the OIDC identity token to your upstream service via headers for further authorization logic.
on_http_request:
  # Authenticate with OIDC
  - actions:
      - type: openid-connect
        config:
          issuer_url: https://accounts.google.com
          client_id: "<your-oidc-client-id>"
          client_secret: "<your-oidc-client-secret>"
          scopes:
            - openid
            - profile
            - email
  # Forward identity token and email to upstream service
  - actions:
      - type: add-headers
        config:
          headers:
            x-identity-token: "${actions.ngrok.oidc.identity_token}"
            x-user-email: "${actions.ngrok.oidc.identity.email}"
See the openid-connect action docs for more information.

JWT validation

For APIs, JWT validation lets you verify tokens without managing user sessions. Combine it with rate limiting for robust API protection.

Basic JWT validation

on_http_request:
  # Validate JWT from Authorization header using JWKS endpoint
  - actions:
      - type: jwt-validation
        config:
          issuer:
            allow_list:
              - value: https://your-auth-provider.com
          audience:
            allow_list:
              - value: "your-api-audience"
          http:
            tokens:
              - type: jwt
                method: header
                name: Authorization
                prefix: 'Bearer '
          jws:
            allowed_algorithms:
              - RS256
            keys:
              sources:
                additional_jkus:
                  - https://your-auth-provider.com/.well-known/jwks.json

JWT validation with rate limiting

Combine authentication with key-based rate limiting for complete API protection.
on_http_request:
  # Rate limit by API key, then validate JWT
  - actions:
      - type: rate-limit
        config:
          name: 30 requests per minute per API key
          algorithm: sliding_window
          capacity: 30
          rate: 60s
          bucket_key:
            - req.headers['x-api-key']
      - type: jwt-validation
        config:
          issuer:
            allow_list:
              - value: https://<YOUR-AUTH-PROVIDER>
          audience:
            allow_list:
              - value: "<YOUR-NGROK-DOMAIN>"
          http:
            tokens:
              - type: jwt
                method: header
                name: Authorization
                prefix: 'Bearer '
          jws:
            allowed_algorithms:
              - RS256
            keys:
              sources:
                additional_jkus:
                  - https://<YOUR-AUTH-PROVIDER>/.well-known/jwks.json
See the jwt-validation action docs and the Auth0 integration guide for more information.

IP restrictions

Restrict access to specific IP addresses or CIDR ranges. Use this for network-level access control, such as allowing only office IPs or blocking known bad actors.
on_http_request:
  # Only allow requests from trusted IPs
  - actions:
      - type: restrict-ips
        config:
          allow:
            - 203.0.113.0/24
            - 198.51.100.42/32
You can also combine IP restrictions with other authentication methods. See the IP restrictions + Basic Auth example for a pattern that allows users to authenticate with one method OR another. See the restrict-ips action docs for more information.

Mutual TLS (mTLS)

Mutual TLS requires clients to present a valid certificate, enabling strong machine-to-machine authentication. Use this for zero-trust architectures or when you need to verify client identity at the transport layer. mTLS is configured at the endpoint level rather than through Traffic Policy actions. See the Mutual TLS documentation for setup instructions. Once mTLS is enabled, you can use Traffic Policy to make routing or access decisions based on client certificate details. See the routing by client certificate example.

Enforce authentication

Use Traffic Policy to require authentication or apply different rate limits based on authentication status.

Reject unauthenticated requests

For APIs that require authentication, immediately reject requests that don’t include an Authorization header.
on_http_request:
  # Return 401 if no Authorization header is present
  - expressions:
      - "!('authorization' in req.headers)"
    actions:
      - type: custom-response
        config:
          status_code: 401
          body: '{"error": "Authorization header required"}'
          headers:
            content-type: application/json

Tiered rate limits

Create different rate limits based on authentication status—unauthenticated users get a lower limit while authenticated users get higher capacity.
on_http_request:
  # Unauthenticated requests get 10 req/min by IP
  - expressions:
      - "!('Authorization' in req.headers)"
    actions:
      - type: rate-limit
        config:
          name: Free tier - 10 requests per minute
          algorithm: sliding_window
          capacity: 10
          rate: 60s
          bucket_key:
            - conn.client_ip
  # Authenticated requests get 100 req/min by token
  - expressions:
      - "'Authorization' in req.headers"
    actions:
      - type: rate-limit
        config:
          name: Authenticated - 100 requests per minute
          algorithm: sliding_window
          capacity: 100
          rate: 60s
          bucket_key:
            - req.headers['authorization']