# Security groups

Many credentials on one channel, mTLS channels and the proxy header contract.

A channel with one [security definition](https://zato.io/docs/dev/rest/authentication.html) has one credential. A channel with security groups has as many as the groups hold members - each partner or application keeps its own [API key](https://zato.io/docs/security/api-keys.html), [Basic Auth](https://zato.io/docs/security/basic-auth.html) username or [bearer token](https://zato.io/docs/security/bearer-tokens/index.html), and one channel serves them all.

## How groups work {#how-groups-work}

A security group is a named set of security definitions. A channel lists one or more groups, and a request is allowed through when its credential matches any member of any of the channel's groups.

Three credential kinds work through groups:

- A bearer token, in the `Authorization` header
- Basic Auth, in the `Authorization` header
- An API key, in the header the channel's API key definitions name

Two constraints keep a channel's groups unambiguous:

- All API key definitions across one channel's groups share one header name - members with conflicting headers are refused when the configuration loads
- Usernames and API key values are unique across a channel's groups

A request with both Basic Auth and an API key at once is answered 400 - one credential per request.

## Create a group {#create-a-group}

To create a group, go to **Security** > **Groups** in the Dashboard, click **Create a new group** and fill in the form:

1. **Name:** Partner Applications
2. **Members:** pick the Basic Auth and API key definitions that belong to the group
3. Click **OK**

![New security group](https://zatosource-production.b-cdn.net/docs/gfx/rest/security-group-create.webp?v=1790440704)

Dashboard menu: Security > Groups

Assign the group in the channel's create or edit form and any client whose credential is a member of the group can call the channel. To revoke one client's access, remove its definition from the group - the channel and the other clients stay untouched.

In service code, `self.channel.security.username` names the member whose credential authenticated the request, so you can tell which client made each call.

## 403, not 401 {#403-not-401}

A channel secured through groups answers failed authentication with 403, both for a wrong credential and for a missing one. Only a channel secured with a directly assigned security definition answers 401 with a `WWW-Authenticate` challenge - the difference tells a caller which of the two rejected it. The full status map is in the [error catalog](https://zato.io/docs/dev/rest/error-catalog.html).

## Groups in enmasse {#groups-in-enmasse}

```yaml
channel_rest:

  - name: api.partner.orders
    service: demo.rest.partner-orders
    url_path: /api/partner/orders
    data_format: json
    groups:
      - Partner Applications
      - Internal Tools
```

The [enmasse reference](https://zato.io/docs/dev/rest/enmasse.html) documents the remaining channel keys.

## mTLS channels {#mtls-channels}

A channel requires client certificates by attaching an mTLS security definition. The definition may pin a certificate's SHA-256 fingerprint, its subject DN, or neither - with neither configured, any certificate the TLS layer verified is accepted.

Zato itself never terminates TLS for mTLS channels - the proxy in front of the server does, and it reports the outcome through three headers:

| Header | What it contains |
| --- | --- |
| `X-Zato-SSL-Client-Verify` | The verification outcome - the value must be exactly `SUCCESS` |
| `X-Zato-SSL-Client-SHA256` | The client certificate's SHA-256 fingerprint, in hex |
| `X-Zato-SSL-Client-Subject-DN` | The certificate's subject DN |

The bundled HAProxy configuration strips all three headers from every incoming request before setting them itself, so a caller can never inject them. A proxy of your own must do the same - the headers are trusted, which is safe only when the proxy is their sole source.

A request whose headers do not verify, or whose certificate matches neither the pinned fingerprint nor the pinned subject DN, is answered 401.

The [mTLS](https://zato.io/docs/security/mtls/index.html) page covers creating the definitions and certificates end to end.

## See also {#see-also}

- [Authentication](https://zato.io/docs/dev/rest/authentication.html) - The Basic Auth, API key and Bearer token definitions groups hold
- [REST channels](https://zato.io/docs/dev/rest/channels.html) - The channels that groups are assigned to
- [Error catalog](https://zato.io/docs/dev/rest/error-catalog.html) - The full status map, including the 401 versus 403 rule
- [Enmasse reference](https://zato.io/docs/dev/rest/enmasse.html) - The remaining channel\_rest keys next to the groups list

## Learn more {#learn-more}

- [REST integration overview](https://zato.io/integrations/rest/) - Start here to see how teams build REST integrations
- [In-depth API tutorial](https://zato.io/tutorials/main/01.html) - Master architectural patterns for production-ready integrations
- [Modern REST API tutorial](https://zato.io/tutorials/rest-api/python.html) - Design, build and secure REST APIs with Python
