# `Ash.Authorizer`
[🔗](https://github.com/ash-project/ash/blob/v3.27.8/lib/ash/authorizer.ex#L5)

The interface for an ash authorizer

These will typically be implemented by an extension, but a custom
one can be implemented by defining an extension that also adopts this behaviour.

Then you can extend a resource with `authorizers: [YourAuthorizer]`

# `context`

```elixir
@type context() :: map()
```

# `state`

```elixir
@type state() :: map()
```

# `add_calculations`
*optional* 

```elixir
@callback add_calculations(Ash.Query.t() | Ash.Changeset.t(), state(), context()) ::
  {:ok, Ash.Query.t() | Ash.Changeset.t(), state()} | {:error, Ash.Error.t()}
```

# `alter_filter`
*optional* 

```elixir
@callback alter_filter(filter :: Ash.Filter.t(), state(), context()) ::
  {:ok, Ash.Filter.t()} | {:error, Ash.Error.t()}
```

# `alter_results`
*optional* 

```elixir
@callback alter_results(state(), [Ash.Resource.Record.t()], context()) ::
  {:ok, [Ash.Resource.Record.t()]} | {:error, Ash.Error.t()}
```

# `apply_field_level_auth`
*optional* 

```elixir
@callback apply_field_level_auth(
  resource :: Ash.Resource.t(),
  records :: [Ash.Resource.Record.t()],
  opts :: Keyword.t()
) :: {:ok, [Ash.Resource.Record.t()]} | {:error, Ash.Error.t()}
```

Apply field-level authorization to a list of records that already have
values populated in memory, without re-fetching them through a read.

Implementations should walk each record and substitute `%Ash.ForbiddenField{}`
for any field the actor isn't allowed to see (typically via field policies).

This is the lightweight counterpart to `add_calculations/3` + the read
pipeline's field-policy scrubbing — used when you have records in hand and
just need to enforce field-level visibility without running a load.

# `check`

```elixir
@callback check(state(), context()) ::
  :authorized
  | {:data, [Ash.Resource.Record.t()]}
  | {:error, :forbidden, state()}
  | {:error, Ash.Error.t()}
```

# `check_context`

```elixir
@callback check_context(state()) :: [atom()]
```

# `exception`
*optional* 

```elixir
@callback exception(atom(), state()) :: Exception.t()
```

# `initial_state`

```elixir
@callback initial_state(
  Ash.Resource.t(),
  Ash.Resource.Record.t(),
  Ash.Resource.Actions.action(),
  Ash.Domain.t()
) :: state()
```

# `protected_fields`
*optional* 

```elixir
@callback protected_fields(Ash.Resource.t()) :: [atom()]
```

Returns the fields this authorizer may protect at field level for the resource.

This is metadata for callers that need to know which fields can be hidden by
authorization without running an action. Authorizers that do not implement this
callback are treated as protecting no fields.

# `strict_check`

```elixir
@callback strict_check(state(), context()) ::
  {:authorized, state()}
  | {:continue, state()}
  | {:filter, Keyword.t()}
  | {:filter, Keyword.t(), state()}
  | {:filter_and_continue, Keyword.t(), state()}
  | {:error, term()}
```

# `strict_check_context`

```elixir
@callback strict_check_context(state()) :: [atom()]
```

# `apply_field_level_auth`

```elixir
@spec apply_field_level_auth(
  Ash.Resource.t(),
  Ash.Resource.Record.t() | [Ash.Resource.Record.t()],
  Keyword.t()
) ::
  {:ok, Ash.Resource.Record.t() | [Ash.Resource.Record.t()]}
  | {:error, Ash.Error.t()}
```

Apply field-level authorization to records that are already in memory,
scrubbing any fields the actor isn't allowed to see.

Walks each authorizer configured on the resource and invokes its
`apply_field_level_auth/3` callback if defined. Returns the records with
forbidden fields replaced by `%Ash.ForbiddenField{}`.

Use this when you have records in hand (for example, returned from a
generic action or constructed in memory) and want field policies applied
without driving the records through a full read.

Supported options:

- `:actor` - the actor whose visibility is being checked.
- `:tenant` - the tenant the records belong to.
- `:domain` - the domain context.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
