# Protecting Your Function

Sinch Functions can require authentication on any handler. When enabled, callers must provide your project's API key and secret via Basic Auth. This lets you expose HTTP endpoints that only your systems can reach.

## How it works

1. You mark which handlers require auth (or all of them)
2. The runtime checks incoming requests for an `Authorization: Basic` header
3. Credentials are validated against `PROJECT_ID_API_KEY` and `PROJECT_ID_API_SECRET`
4. Invalid or missing credentials get a `401 Unauthorized` response


Voice callbacks (ICE, ACE, DiCE, PIE) and health checks are **never** auth-gated — they come from the Sinch platform and use webhook signature validation instead.

## Declaring protected handlers

Node.js
Export an `auth` array with the handler names you want to protect:

```typescript
import type { FunctionContext, FunctionRequest } from '@sinch/functions-runtime';

// Protect the 'webhook' handler — callers must authenticate
export const auth = ['webhook'];

export async function webhook(context: FunctionContext, request: FunctionRequest) {
  // Only reachable with valid credentials
  return { received: request.body };
}

export async function status(context: FunctionContext, request: FunctionRequest) {
  // No auth required — not listed in the auth array
  return { ok: true };
}
```

To protect **all** handlers:

```typescript
export const auth = '*';
```

C#
Add the `[Authorize]` attribute to controller actions:

```csharp
using Microsoft.AspNetCore.Authorization;

public class FunctionController : SinchController
{
    [Authorize]
    public IActionResult Webhook()
    {
        // Only reachable with valid credentials
        return Ok(new { received = "data" });
    }

    public IActionResult Status()
    {
        // No auth required — no [Authorize] attribute
        return Ok(new { ok = true });
    }
}
```

## Credentials

Auth uses your Sinch project's API key and secret — the same credentials you use with `sinch auth login`. When deployed, these are injected automatically as environment variables:

- `PROJECT_ID_API_KEY` — your project's API key
- `PROJECT_ID_API_SECRET` — your project's API secret


You don't need to configure anything. The runtime reads these from the environment at startup.

## Local development

During local development (`sinch functions dev`), auth is **skipped** when credentials aren't configured. This means you can test your handlers without setting up auth locally.

> **If you run `sinch functions dev` with a public tunnel**, your local server is reachable from the internet for the duration of the dev session. With auth skipped, any endpoint you marked as protected is effectively open to the world during that window. To test auth end-to-end through the tunnel, set the credentials (see below) before starting the dev server.


To test auth locally, set the environment variables before starting dev mode:

Node.js
```bash
PROJECT_ID_API_KEY=mykey PROJECT_ID_API_SECRET=mysecret sinch functions dev
```

C#
```bash
PROJECT_ID_API_KEY=mykey PROJECT_ID_API_SECRET=mysecret sinch functions dev
```

## Testing with curl

Once auth is enabled (locally with env vars or after deployment):

```bash
# Authenticated request
curl -u YOUR_API_KEY:YOUR_API_SECRET https://your-function-url/webhook

# This is equivalent to:
curl -H "Authorization: Basic $(echo -n 'YOUR_API_KEY:YOUR_API_SECRET' | base64)" \
  https://your-function-url/webhook

# Without credentials — returns 401
curl https://your-function-url/webhook
```

## What's not protected

These endpoints bypass auth regardless of your configuration:

| Endpoint | Reason |
|  --- | --- |
| Voice callbacks (ICE, ACE, DiCE, PIE) | Validated by webhook signature, not Basic Auth |
| Health checks (`/health`) | Used by infrastructure for liveness probes |