NAME
Langertha::Knarr::Authorizer - Role for who may use a Knarr, and with which model
VERSION
version 1.103
SYNOPSIS
package My::Authorizer;
use Moose;
with 'Langertha::Knarr::Authorizer';
sub identify {
my ( $self, $http_req, $action ) = @_;
return { identity => {} } if $http_req->header('X-Trusted');
return { status => 401, message => 'unauthorized' };
}
sub authorize { return } # every model
sub visible_models { $_[2] } # every listed model
sub forwards_client_key { 1 }
__PACKAGE__->meta->make_immutable;
my $knarr = Langertha::Knarr->new(
handler => $handler,
authorizer => My::Authorizer->new,
);
DESCRIPTION
Decides who may use a Langertha::Knarr, in two phases:
- 2. Authorize -- may this identity do this action with this model. Runs once the action and the model are known: after the chat request was parsed, with the model of a
POST /api/showbody. A request that names no model gets the identity's ownmodelfirst, when it has one ("apply_grant" in Langertha::Knarr::Request).
Every refusal is answered by Knarr in the client protocol's error shape ("ERRORS" in Langertha::Knarr), on the native server and under Langertha::Knarr::PSGI alike.
The identity is a plain HashRef. It goes to the handler chain as "grant" in Langertha::Knarr::Request. It must never carry a secret: no key, no token, no hash of one.
Two authorizers ship with Knarr: Langertha::Knarr::Authorizer::StaticKey ("auth_token" in Langertha::Knarr, the default) and Langertha::Knarr::Authorizer::Token (one short-lived token per model, checked against a Langertha::Knarr::TokenStore).
identify_f
my $result = await $authorizer->identify_f( $http_req, $action );
Returns a Future that is done with the result of the identify phase and never fails:
{ identity => \%identity } # go on
{ status => 401, message => 'unauthorized' } # refused
The native server uses it, so a check that has to ask something (a database) does not hold the event loop. The default calls "identify".
identify
my $result = $authorizer->identify( $http_req, $action );
Required. The same result, synchronously (Langertha::Knarr::PSGI, where the request may block). $http_req answers ->header($name); $action is the route's action (chat, models, a2a_card, ...).
authorize
my ( $status, $message ) = $authorizer->authorize( $identity, $action, $model );
Required. Empty list when the identity may do $action with $model (undef when the action has none), else the status and the client's message of the refusal.
visible_models
my $models = $authorizer->visible_models( $identity, \@models );
Required. The models a model list (/v1/models, /api/tags, ACP /agents, /api/show) shows this identity, from the list the handler or router gives, as hashes with an id (the shape "format_models_response" in Langertha::Knarr::Protocol takes).
forwards_client_key
Required. True when the client's own key may reach an upstream: then the raw passthrough runs and a passthrough handler forwards the client's Authorization and x-api-key (Knarr's proxy key taken out). False: the raw passthrough never runs, and both headers are dropped from every header set Knarr forwards.
start
$authorizer->start($loop);
Called by Langertha::Knarr once a process starts serving, with the IO::Async::Loop it serves on: by "start" in Langertha::Knarr with one worker, in every forked worker otherwise -- never in the prefork supervisor, whose connections every worker would share. An authorizer that needs a connection opens it here, without blocking, so the first request does not wait for it. It may be called again in the same process (an admin push hands the same authorizer over again) and must then do nothing. The default does nothing. Langertha::Knarr::PSGI does not call it.
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha-knarr/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.