# Authorize Log Fields

## Summary

The **Authorize Log Fields** setting controls which fields will be included in the authorize logs. For each incoming request, the authorize service will emit a log entry with the message `authorize check` containing the policy evaluation result and these additional log fields.

The default log fields should be appropriate for most deployments.

## How to configure

**Core:**

**Enterprise:**

**Kubernetes:**

| **[Parameter name](https://www.pomerium.com/docs/deploy/k8s/reference.md#spec)** | **Type** | **Default** |
| :-- | :-- | :-- |
| `authorizeLogFields` | Array of strings | See [Authorize Fields and Defaults](#authorize-log-fields-and-defaults) |

### Examples

```yaml
authorizeLogFields:
  - request-id
  - path
  - ip
```

## Authorize log fields and defaults

The table below lists all available authorize log fields:

| **Field name** | **Description** | **Default field** |
| :-- | :-- | :-- |
| `body` | The HTTP request body. Only available for protocols with request content inspection such as MCP. | No |
| `check-request-id` | The request ID of the gRPC check call | Yes |
| `cluster-stat-name` | The stat name of the upstream cluster the request was routed to (set via route `name`, route `id`, or the Enterprise Console **Metric Name** field) | No |
| `email` | The logged-in user's email address | Yes |
| `envoy-route-checksum` | The checksum of the Envoy route configuration used to match the request | Yes |
| `envoy-route-id` | The ID of the Envoy route that matched the request | Yes |
| `headers` | The complete set of HTTP request headers | No |
| [`headers.{CustomHeaderName}`](#log-custom-headers-fields) | An HTTP Request Header identified by the `HeaderName` | No |
| `host` | The HTTP request `:authority` or `Host` header value. Can be a domain name or IP address and may contain a port number (for example, `www.example.com`) | Yes |
| `id-token` | The user's ID token | No |
| `id-token-claims` | The user's ID token claims | No |
| `impersonate-email` | If [impersonating](https://www.pomerium.com/docs/capabilities/impersonation.md), the impersonated email | Yes |
| `impersonate-session-id` | If [impersonating](https://www.pomerium.com/docs/capabilities/impersonation.md), the impersonated session ID | Yes |
| `impersonate-user-id` | If [impersonating](https://www.pomerium.com/docs/capabilities/impersonation.md), the impersonated user ID | Yes |
| `ip` | The IP address of the direct downstream client. If Pomerium is deployed behind a load balancer or other proxy, this will not be the IP address of the end user. | Yes |
| `mcp-method` | The MCP method being called (e.g., `tools/call`, `tools/list`) | No |
| `mcp-tool` | The MCP tool name for `tools/call` requests | No |
| `mcp-tool-parameters` | The tool call parameters as a JSON object for `tools/call` requests | No |
| `method` | The HTTP request method, such as `GET`, `POST`, or `PUT` | Yes |
| `path` | The HTTP request path (for example, `/some/path`) | Yes |
| `query` | The HTTP request query (for example, `?test=one&other=13`) | No |
| `removed-groups-count` | The number of groups removed during [JWT groups filtering](https://www.pomerium.com/docs/reference/jwt-groups-filter.md) | Yes |
| `request-id` | The request's unique identifier as assigned by Pomerium | Yes |
| `route-checksum` | The checksum of the Pomerium route policy that matched the request | Yes |
| `route-id` | The ID of the Pomerium route policy that matched the request | Yes |
| `service-account-id` | If using a service account, the service account ID | Yes |
| `session-id` | The session ID | Yes |
| `user` | The user's ID | Yes |

Query parameters and request bodies often contain sensitive information. Do not enable the `query` or `body` log fields without careful consideration.

## Authorize log behavior

### Find authorize logs

To find logs from the authorize service, filter your Pomerium logs for entries containing `"message": "authorize check"`:

```json
{
  "level":"info",
  "service":"authorize",
  "request-id":"f55d5fd5-2d6c-42d1-a7f6-007ad7ec3a85",
  "check-request-id":"f55d5fd5-2d6c-42d1-a7f6-007ad7ec3a85",
  "method":"POST","path":"/pomerium.dashboard.KeyChainService/ListKeyPairs",
  "host":"console.localhost.pomerium.io",
  "ip":"127.0.0.1",
  "session-id":"45445311-b287-4476-b17e-d5a8965ff3f4",
  "user":"google-oauth2|XXXXXXXXXXXXXXXXXXXXX",\
  "email":"example@pomerium.com",
  "allow":true,
  "allow-why-true":["domain-ok"],
  "deny":false,"deny-why-false":[],
  "time":"2023-08-07T09:48:03-04:00",
  "message":"authorize check"
}
```

### Display specific logs

If `authorize_log_fields` is not defined, all the available default fields will be logged.

To log only a specific field, or multiple fields, add the desired field(s) to your configuration file.

For example, if you add the following fields to `authorize_log_fields`:

```yaml
authorize_log_fields:
  - request-id
  - method
  - path
```

Your logs would look similar to the below example:

```json
{
  "level": "info",
  "method": "GET",
  "path": "/index.css",
  "request-id": "c9afae5a-ec5a-4242-864f-df4189f20e99",
  "service": "authorize",
  "allow": true,
  "allow-why-true": ["domain-ok"],
  "deny": false,
  "deny-why-false": [],
  "time": "2023-08-07T10:26:33-04:00",
  "message": "authorize check"
}
```

### Log authorize HTTP headers

To get a list of all authorize HTTP headers, add the `headers` option:

```yaml
authorize_log_fields:
  - headers
```

Your logs would look similar to the example below:

```json
{
  "headers": {
    ":authority": "verify.localhost.pomerium.io",
    ":method": "GET",
    ":path": "/api/verify-info",
    ":scheme": "https",
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "en-US,en;q=0.9",
    "Content-Type": "application/json",
    "Cookie": "_pomerium=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhYnJva2VyX3JlY29yZF92ZXJzaW9uIjozMTQwLCJkYXRhYnJva2VyX3NlcnZlcl92ZXJzaW9uIjo3OTM4MDg0ODcsImlhdCI6MTY5MTQxODM5MiwianRpIjoiMTcyZTQ1NTEtZTllYi00ZmUwLWE2Y2UtMjQ0NWM3NjA0MGJkIiwic3ViIjoiZ29vZ2xlLW9hdXRoMnwxMTU0MjA2NjQ3MjYxODMzMjM3NTgifQ.ktq6oFtiBiGwNsU-5DQzLNTszexFhyNl1Iz4kc_Uq2M",
    "Referer": "https://verify.localhost.pomerium.io/",
    "Sec-Ch-Ua": "\"Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"115\", \"Chromium\";v=\"115\"",
    "Sec-Ch-Ua-Mobile": "?0",
    "Sec-Ch-Ua-Platform": "\"macOS\"",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
    "X-Envoy-Internal": "true",
    "X-Forwarded-For": "XXX.XXX.X.XXX",
    "X-Forwarded-Proto": "https",
    "X-Request-Id": "d6c95dd6-9f3c-4653-94d1-62ea54b11328"
  },
  "allow": true,
  "allow-why-true": ["domain-ok"],
  "deny": false,
  "deny-why-false": [],
  "level": "info",
  "service": "authorize",
  "time": "2023-08-07T10:32:03-04:00",
  "message": "authorize check"
}
```

### Log custom headers fields

The `headers.{CustomHeaderName}` field allows you to enter custom headers. Adding one or multiple custom headers will display only those headers.

For example, if you add the following custom headers to `authorize_field_logs`:

```yaml
authorize_log_fields:
  - headers.Cookie
  - headers.content-type
```

The custom headers will appear in the `headers` field:

```json
{
  "headers": {
    "Content-Type": "application/json",
    "Cookie": "_pomerium=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhYnJva2VyX3JlY29yZF92ZXJzaW9uIjozMTQwLCJkYXRhYnJva2VyX3NlcnZlcl92ZXJzaW9uIjo3OTM4MDg0ODcsImlhdCI6MTY5MTQxODM5MiwianRpIjoiMTcyZTQ1NTEtZTllYi00ZmUwLWE2Y2UtMjQ0NWM3NjA0MGJkIiwic3ViIjoiZ29vZ2xlLW9hdXRoMnwxMTU0MjA2NjQ3MjYxODMzMjM3NTgifQ.ktq6oFtiBiGwNsU-5DQzLNTszexFhyNl1Iz4kc_Uq2M"
  },
  "allow": true,
  "allow-why-true": ["domain-ok"],
  "deny": false,
  "deny-why-false": [],
  "level": "info",
  "service": "authorize",
  "time": "2023-08-07T10:40:38-04:00",
  "message": "authorize check"
}
```

### Log request body

Adding `body` will print the HTTP request body to stdout. Request bodies often contain sensitive information like passwords, tokens, or personal data. Use this field with extreme caution and ensure proper log security measures are in place.

If specified, the `body` option displays the HTTP request body. This can be useful for debugging and audit purposes.

For example, if you add `body`:

```yaml
authorize_log_fields:
  - body
```

Your logs would look similar to the below example:

```json
{
  "body": "{\"username\":\"user@example.com\",\"action\":\"login\"}",
  "allow": true,
  "allow-why-true": ["domain-ok"],
  "deny": false,
  "deny-why-false": [],
  "level": "info",
  "service": "authorize",
  "time": "2023-08-07T10:43:36-04:00",
  "message": "authorize check"
}
```

### Log ID tokens and claims

Adding `id-token` or `id-token-claims` will print these values to stdout.

If specified, the `id-token` option displays the user's ID token received from the identity provider. `id-token-claims` displays the claims contained in the ID token.

For example, if you add `id-token` and `id-token-claims`:

```yaml
authorize_log_fields:
  - id-token
  - id-token-claims
```

Your logs would look similar to the below example:

```json
{
  "id-token": "<ID-TOKEN>",
  "id-token-claims": {
    "aud": "XmDTct9PHNsMRxKxCIObqWnmnEJLguPQ",
    "email": "example@pomerium.com",
    "email_verified": true,
    "exp": 1691452058,
    "family_name": "Painter",
    "given_name": "Zachary",
    "iat": 1691416058,
    "iss": "https://dev-XXXXXXXXXXXXXXXX.us.auth0.com/",
    "locale": "en",
    "name": "Zachary Painter",
    "nickname": "XXXXXXXX",
    "picture": "https://lh3.googleusercontent.com/a/XXX=s96-c",
    "pomerium.io/groups": ["admin"],
    "sid": "L_tMPjzHdHKd6q1NjGdHERgSdWUUZF1b",
    "sub": "google-oauth2|XXXXXXXXXXXXXXXXXXXXX",
    "updated_at": "2023-08-03T17:44:00.171Z"
  },
  "allow": true,
  "allow-why-true": ["domain-ok"],
  "deny": false,
  "deny-why-false": [],
  "level": "info",
  "service": "authorize",
  "time": "2023-08-07T10:43:36-04:00",
  "message": "authorize check"
}
```
