NAME
WWW::Authentik - Perl client for the authentik identity provider (OIDC + REST API v3)
VERSION
version 0.001
SYNOPSIS
use WWW::Authentik;
my $ak = WWW::Authentik->new(
base_url => 'https://id.example.org',
application => 'my-app', # the application slug, for OIDC
client_id => $client_id, # its provider's client id, checked as the audience
token => $ENV{AUTHENTIK_TOKEN}, # an API token, for the REST API
);
# OpenID Connect against the application
my $claims = $ak->oidc->verify_token( $jwt, type => 'access' );
# REST API v3, repeatable
$ak->api->ensure_user( username => 'alice', name => 'Alice', password => $pw );
my $r = $ak->api->ensure_application( slug => 'my-app', name => 'My App', provider_name => 'my-app' );
print $r->{changed}; # 'created', 'updated' or ''
# another application, same instance and token
my $other = $ak->for_application('second-app');
DESCRIPTION
A client for authentik in two parts: WWW::Authentik::OIDC for what an application does with its OpenID Connect endpoints, and WWW::Authentik::API for bringing an authentik into a wanted state from Perl, repeatably.
authentik has no realm. The API is instance-wide under <base_url>/api/v3/ and needs an API token; OpenID Connect is addressed per application, with discovery, keys and the end-session endpoint under <base_url>/application/o/<slug>/ and the token, userinfo, introspection, revocation and device endpoints shared by the whole instance. So "token" and "application" are both optional: without a slug there is no "oidc", without a token there is no "api", and either may be left out.
An authentik API token is long-lived and is used as it is. There is no login to manage and nothing to renew; authentik answers a token it does not accept with 403, not 401.
Coming from WWW::Keycloak
The two distributions have the same shape, but two return values differ, and deliberately. create_* and update_* return the representation, not an id, because authentik answers a create with the whole object and sends no Location header. And ensure_* returns { object => \%rep, changed => ... }, not { id => ..., changed => ... }, because authentik has no single kind of identifier: an application is addressed by its slug, a provider by an integer, a group by a UUID, a token by its identifier. The caller almost always needs the next key out of the object anyway.
Developed and tested against authentik 2026.8.3.
base_url
Required. Where authentik is, without /api/v3 and without /application/o/. Trailing slashes are removed.
application
The slug of the application "oidc" talks to. Without it "oidc" throws a validation error.
token
An authentik API token, sent as a bearer token with every call of "api". Without it "api" throws a validation error. It is used as it is and never renewed.
client_id
The client id of "application"'s provider. "verify_token" in WWW::Authentik::OIDC checks it as the audience, which is what keeps a token of another application of the same authentik from passing. Worth setting.
ua
The LWP::UserAgent every part shares. "default_ua" builds it.
default_ua
my $ua = WWW::Authentik->default_ua;
The user agent this client wants, for a caller who needs to build their own and keep the two settings that matter:
max_redirect => 0-
authentik redirects at the authorize endpoint and between the stages of a flow. Those answers are read, not followed, and no redirect may carry the API token anywhere.
send_te => 0-
An injected user agent without this will hang. LWP announces
TE: deflate,gzip;q=0.3andConnection: TE, closeby default, and authentik 2026.8.3 answers every second request carrying theTEconnection token not at all: the call sits until the timeout, the next one is fine, the one after that hangs again. Observed against 2026.8.3 with plain sockets as well, so it is authentik's front end, not LWP.send_te => 0tells Net::HTTP to leave the header out, and libwww-perl has taken the option since 6.33. On anything older this method throws rather than hand back a user agent that works every other time.
oidc
The WWW::Authentik::OIDC of "application".
api
The WWW::Authentik::API of this instance.
api_url
print $ak->api_url; # https://id.example.org/api/v3
application_url
print $ak->application_url; # https://id.example.org/application/o/my-app
Where this application's OpenID Connect endpoints live, without the trailing slash. The slug is URI encoded.
issuer
print $ak->issuer; # https://id.example.org/application/o/my-app/
The issuer in its address form, which is what authentik puts into a token while the provider is set to issuer_mode: per_provider (its default). The authoritative value is "issuer" in WWW::Authentik::OIDC, read out of the discovery document; with issuer_mode: global the two differ.
for_application
my $other = $ak->for_application('second-app');
The same client for another application, sharing the user agent and the API token.
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/p5-www-authentik/issues.
IRC
Join #kubernetes on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <getty@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.