# Request Authentication and Authorization Flows in INFINI Gateway

> Explore INFINI Gateway's request authentication and authorization flows. Learn how security filters validate credentials and manage access control decisions.

- Repository: [INFINI Labs/gateway](https://github.com/infinilabs/gateway)
- Tags: how-to-guide
- Published: 2026-03-04

---

**INFINI Gateway processes request authentication and authorization through a sequential pipeline of security filters that validate credentials against static user maps, LDAP directories, or API keys, then persist identity metadata in the request context for downstream access control decisions.**

The infinilabs/gateway repository handles HTTP request authentication and authorization via configurable filter chains that execute early in the request lifecycle. Each filter can terminate the request with a **401 Unauthorized** response or pass control forward while injecting user identity information—such as user ID, username, and role assignments—into the shared `fasthttp.RequestCtx` for later authorization checks.

## Authentication Filter Architecture

INFINI Gateway organizes security logic into discrete filter plugins that operate on the `fasthttp.RequestCtx` object. When a request enters a configured flow, the gateway executes filters in declaration order, allowing each filter to inspect headers, validate credentials, or modify the request context. Authentication filters typically appear first in the chain, ensuring that only verified requests reach upstream Elasticsearch clusters or other backend services.

## Built-in Authentication Methods

### Basic Authentication Filter

The **basic_auth** filter, implemented in [`proxy/filters/security/auth/basic_auth.go`](https://github.com/infinilabs/gateway/blob/main/proxy/filters/security/auth/basic_auth.go), validates credentials against a static map of usernames and passwords defined in the gateway configuration.

The filter extracts the `Authorization` header using `ctx.Request.Header.PeekAny(fasthttp.AuthHeaderKeys)`, then parses the "Basic " prefix via an internal `parseBasicAuth` function that base64-decodes the value and splits it into username and password components. The decoded username serves as a key into the `ValidUsers` configuration map; if the password matches the configured value, the filter returns silently and the request continues. On failure, the filter sends a **401 Unauthorized** response including a `WWW-Authenticate` header and terminates processing.

```yaml
flow:
  - name: secure_flow
    filter:
      - basic_auth:
          valid_users:
            admin: secret123
            operator: pass456

```

### LDAP Authentication Filter

For enterprise deployments, the **ldap_auth** filter in [`proxy/filters/security/ldap/ldap.go`](https://github.com/infinilabs/gateway/blob/main/proxy/filters/security/ldap/ldap.go) delegates credential validation to external LDAP servers and optionally enforces group membership requirements.

The filter first checks for an `ApiKey` authorization type when `bypass_api_key` is enabled, allowing specific clients to skip LDAP validation. For standard authentication, it calls `ldapQuery.Authenticate` from the underlying LDAP strategy in the `infini.sh/framework/lib/guardian/auth/strategies/ldap` library. Upon successful authentication, the filter extracts the user's directory groups and stores three critical values in the request context:

```go
ctx.Set("user_id", user.GetID())
ctx.Set("user_name", user.GetUserName())
ctx.Set("user_roles", common.GetLDAPGroupsMappingRoles(user.GetGroups()))

```

If the configuration specifies `require_group: true` and the user lacks group memberships, the filter returns **401** with an explanatory error body.

## Authorization and Role-Based Access Control

While authentication filters establish identity, authorization logic typically executes in subsequent filters or custom plugins that read the stored context values.

### Context Propagation Mechanism

All filters share the same `fasthttp.RequestCtx` instance throughout the request lifecycle. When an authentication filter writes `user_id`, `user_name`, or `user_roles` using `ctx.Set()`, downstream filters retrieve these values with `ctx.Get()` to make authorization decisions. This design enables fine-grained access control based on cluster permissions, index-level restrictions, or custom business rules implemented in [`common/role_mapping.go`](https://github.com/infinilabs/gateway/blob/main/common/role_mapping.go).

The current implementation of `common.GetLDAPGroupsMappingRoles` in [`common/role_mapping.go`](https://github.com/infinilabs/gateway/blob/main/common/role_mapping.go) provides a placeholder mapping that returns a slice containing `"admin"` for all authenticated users, though production deployments typically extend this to map specific LDAP groups to gateway roles.

### Building Custom Authorization Filters

Developers can implement role-based access control by creating filters that inspect the `user_roles` context value. The following example demonstrates a custom filter that validates admin privileges before allowing access to sensitive endpoints:

```go
type RoleCheck struct {
    RequiredRole string `config:"required_role"`
}

func (rc *RoleCheck) Name() string { return "role_check" }

func (rc *RoleCheck) Filter(ctx *fasthttp.RequestCtx) {
    roles := ctx.Get("user_roles")
    if roles == nil {
        ctx.Error(fasthttp.StatusMessage(fasthttp.StatusForbidden), fasthttp.StatusForbidden)
        return
    }
    for _, r := range roles.([]string) {
        if r == rc.RequiredRole {
            return // authorized
        }
    }
    ctx.Error(fasthttp.StatusMessage(fasthttp.StatusForbidden), fasthttp.StatusForbidden)
}

```

Register this filter in [`gateway.yml`](https://github.com/infinilabs/gateway/blob/main/gateway.yml) after the authentication step:

```yaml
flow:
  - name: admin_flow
    filter:
      - ldap_auth:
          host: ldap.example.com
          bind_dn: cn=service,dc=example,dc=com
          require_group: true
      - role_check:
          required_role: admin

```

## Configuration Patterns

### Protecting System Administration APIs

The gateway's built-in REST API can be secured independently using the `api.security` configuration block:

```yaml
api:
  enabled: true
  security:
    enabled: true
    username: admin
    password: $[[keystore.API_PASS]]

```

### Upstream Elasticsearch Authentication

When proxying to Elasticsearch clusters that require authentication, the **set_basic_auth** filter in [`proxy/filters/security/auth/set_basic_auth.go`](https://github.com/infinilabs/gateway/blob/main/proxy/filters/security/auth/set_basic_auth.go) injects credentials into outbound requests. This filter removes existing authorization headers and calls `ctx.Request.SetBasicAuth(filter.Username, filter.Password)` to ensure upstream services receive proper credentials.

```yaml
elasticsearch:
  - name: prod_cluster
    endpoint: https://es.internal:9200
    basic_auth:
      username: gateway_user
      password: $[[keystore.ES_PASS]]

```

## Key Source Files

| File | Purpose |
|------|---------|
| [`proxy/filters/security/auth/basic_auth.go`](https://github.com/infinilabs/gateway/blob/main/proxy/filters/security/auth/basic_auth.go) | Static username/password validation against configured `ValidUsers` map |
| [`proxy/filters/security/auth/set_basic_auth.go`](https://github.com/infinilabs/gateway/blob/main/proxy/filters/security/auth/set_basic_auth.go) | Injects Basic Auth headers for upstream service authentication |
| [`proxy/filters/security/ldap/ldap.go`](https://github.com/infinilabs/gateway/blob/main/proxy/filters/security/ldap/ldap.go) | LDAP integration with group extraction and role mapping |
| [`common/role_mapping.go`](https://github.com/infinilabs/gateway/blob/main/common/role_mapping.go) | Maps LDAP groups to gateway-specific roles |
| [`proxy/output/logging/logging.go`](https://github.com/infinilabs/gateway/blob/main/proxy/output/logging/logging.go) | Supports `RemoveAuthHeaderKey` to sanitize logs |

## Summary

- **INFINI Gateway** implements request authentication and authorization through a sequential filter pipeline executing on the `fasthttp.RequestCtx` object.
- The **basic_auth** filter validates credentials against static `ValidUsers` maps defined in [`gateway.yml`](https://github.com/infinilabs/gateway/blob/main/gateway.yml), returning **401 Unauthorized** on failure.
- The **ldap_auth** filter delegates authentication to external LDAP servers, extracts user groups, and populates `user_id`, `user_name`, and `user_roles` in the request context.
- Authorization filters retrieve identity metadata via `ctx.Get()` to enforce fine-grained access control based on LDAP group mappings or custom role assignments.
- The **set_basic_auth** filter enables credential injection for upstream Elasticsearch clusters requiring basic authentication.
- System APIs can be secured independently using the `api.security` configuration block with keystore-backed passwords.

## Frequently Asked Questions

### How does INFINI Gateway persist authenticated user information across filters?

The gateway stores identity metadata in the `fasthttp.RequestCtx` using the `Set()` method. Authentication filters write `user_id`, `user_name`, and `user_roles` into this context, and downstream filters retrieve these values using `ctx.Get("user_roles")` to perform authorization checks. This shared context persists throughout the entire request lifecycle.

### Can INFINI Gateway authenticate users against multiple LDAP servers simultaneously?

While the current implementation in [`proxy/filters/security/ldap/ldap.go`](https://github.com/infinilabs/gateway/blob/main/proxy/filters/security/ldap/ldap.go) supports a single LDAP server per filter configuration, you can create multiple flows with distinct `ldap_auth` filters targeting different hosts. Each flow can apply different LDAP servers to specific routes or endpoints by configuring separate entry points in [`gateway.yml`](https://github.com/infinilabs/gateway/blob/main/gateway.yml).

### What authentication methods support API key bypass for service accounts?

The **ldap_auth** filter provides a `bypass_api_key` configuration option. When enabled, requests containing an `Authorization` header with the `ApiKey` type automatically skip LDAP validation and proceed to downstream filters. This allows service accounts to authenticate via API keys while human users use LDAP credentials.

### How do I customize the mapping between LDAP groups and gateway roles?

Modify the `common.GetLDAPGroupsMappingRoles` function in [`common/role_mapping.go`](https://github.com/infinilabs/gateway/blob/main/common/role_mapping.go). The current placeholder implementation returns `[]string{"admin"}` for all users, but production deployments should implement logic that maps specific LDAP group distinguished names (DNs) to role strings like "admin", "operator", or "viewer" based on organizational requirements.