NAME
WWW::Zitadel::OIDC - OIDC client for Zitadel - token verification, JWKS, discovery
VERSION
version 0.001
SYNOPSIS
use WWW::Zitadel::OIDC;
my $oidc = WWW::Zitadel::OIDC->new(
issuer => 'https://zitadel.example.com',
);
# Discovery
my $config = $oidc->discovery;
# Fetch JWKS
my $jwks = $oidc->jwks;
# Verify an access token (JWT)
my $claims = $oidc->verify_token($access_token);
# Verify with audience check
my $claims = $oidc->verify_token($token,
audience => 'my-client-id',
);
# Fetch user info
my $user = $oidc->userinfo($access_token);
# Token introspection (requires client credentials)
my $info = $oidc->introspect($token,
client_id => $client_id,
client_secret => $client_secret,
);
# Token endpoint helpers
my $cc = $oidc->client_credentials_token(
client_id => $client_id,
client_secret => $client_secret,
scope => 'openid profile',
);
my $refreshed = $oidc->refresh_token(
$refresh_token,
client_id => $client_id,
client_secret => $client_secret,
);
DESCRIPTION
OIDC client for Zitadel. Handles discovery, JWKS fetching, JWT verification via Crypt::JWT, and userinfo/introspection endpoints.
Token verification automatically retries with a refreshed JWKS on failure, handling key rotation transparently.
issuer
Required. The Zitadel issuer URL, e.g. https://zitadel.example.com.
ua
Optional LWP::UserAgent instance. A default one with 10s timeout is created.
discovery
Returns the parsed OpenID Connect discovery document from /.well-known/openid-configuration.
jwks
Returns the JSON Web Key Set. Caches after first fetch. Pass force_refresh => 1 to bypass the cache.
verify_token
my $claims = $oidc->verify_token($jwt, %options);
Verifies a JWT access token against the JWKS. Returns the decoded claims hashref on success, dies on failure.
Options: audience, verify_exp (default 1), verify_iat (default 0), verify_nbf (default 0), accepted_key_alg (default RS256/384/512).
userinfo
my $info = $oidc->userinfo($access_token);
Calls the UserInfo endpoint with the given access token. Returns parsed JSON response.
introspect
my $info = $oidc->introspect($token,
client_id => $id,
client_secret => $secret,
);
Calls the token introspection endpoint. Requires client_id and client_secret for authentication.
token
my $token_response = $oidc->token(
grant_type => 'client_credentials',
client_id => $id,
client_secret => $secret,
scope => 'openid profile',
);
Generic token endpoint helper. Sends a form-encoded POST to the discovered token_endpoint and returns parsed JSON.
client_credentials_token
my $token_response = $oidc->client_credentials_token(
client_id => $id,
client_secret => $secret,
scope => 'openid profile',
);
Convenience wrapper around token for client_credentials.
refresh_token
my $token_response = $oidc->refresh_token(
$refresh_token,
client_id => $id,
client_secret => $secret,
);
Convenience wrapper around token for refresh_token.
exchange_authorization_code
my $token_response = $oidc->exchange_authorization_code(
code => $code,
redirect_uri => $redirect_uri,
client_id => $id,
client_secret => $secret,
code_verifier => $verifier,
);
Convenience wrapper around token for authorization_code.
SEE ALSO
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/p5-www-zitadel/issues.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@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.