一键导入
www-zitadel-perl
Usage guide for WWW::Zitadel Perl client (OIDC, Management API, token flows, tests)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Usage guide for WWW::Zitadel Perl client (OIDC, Management API, token flows, tests)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | www-zitadel-perl |
| description | Usage guide for WWW::Zitadel Perl client (OIDC, Management API, token flows, tests) |
| user-invocable | true |
| allowed-tools | Read, Grep, Glob, Bash |
| model | sonnet |
Use this skill when the task is "how do I use WWW::Zitadel in Perl?".
WWW::Zitadel: unified entrypoint (issuer, optional token)WWW::Zitadel::OIDC: discovery, JWKS, token verification, userinfo, introspection, token endpoint helpersWWW::Zitadel::Management: Management API v1 (users/projects/apps/roles/grants/IDPs)WWW::Zitadel::Error: exception base; subclasses ::Validation, ::Network, ::APIAsync equivalent: Net::Async::Zitadel in p5-net-async-zitadel/ — same API surface with _f suffixes returning Futures.
use WWW::Zitadel;
my $z = WWW::Zitadel->new(
issuer => 'https://zitadel.example.com',
token => $ENV{ZITADEL_PAT}, # only needed for management calls
);
my $claims = $z->oidc->verify_token($jwt, audience => 'client-id');
my $projects = $z->management->list_projects(limit => 20);
Important: management methods are direct methods like
list_users, create_human_user, create_project (no ->users->list subclient API).
Typical calls:
discoveryjwks(force_refresh => 1?)verify_token($jwt, audience => ..., verify_exp => 1, ...)userinfo($access_token)introspect($token, client_id => ..., client_secret => ...)client_credentials_token(...)refresh_token($refresh_token, ...)exchange_authorization_code(code => ..., redirect_uri => ..., ...)verify_token retries once with refreshed JWKS when signature validation fails
(useful for key rotation).
Create client:
my $mgmt = WWW::Zitadel::Management->new(
base_url => 'https://zitadel.example.com',
token => $ENV{ZITADEL_PAT},
);
Common flow:
create_project(name => ...)create_oidc_app($project_id, name => ..., redirect_uris => [...])add_project_role($project_id, role_key => ...)create_user_grant(user_id => ..., project_id => ..., role_keys => [...])Errors throw typed exception objects (subclasses of WWW::Zitadel::Error).
They stringify to their message, so plain eval/$@ string matching still works.
eval { $mgmt->get_user($id) };
if (my $err = $@) {
if (ref $err && $err->isa('WWW::Zitadel::Error::API')) {
warn "HTTP: ", $err->http_status, "\n"; # e.g. "404 Not Found"
warn "Msg: ", $err->api_message, "\n"; # from Zitadel JSON body
}
die $err; # re-throw
}
Exception classes:
WWW::Zitadel::Error::Validation — bad args before any HTTP callWWW::Zitadel::Error::Network — HTTP-level failure (non-2xx for OIDC endpoints)WWW::Zitadel::Error::API — non-2xx from Management API (has http_status, api_message)PAT creation: ZITADEL UI → Users (top-right avatar) → Personal Access Tokens → Add. Service accounts: Users → Service Users → create → Keys tab → add key.
API base path: Always appends /management/v1 — don't double-include it in paths.
Token format: Authorization: Bearer <PAT> — always Bearer, never Basic.
IDP configuration: After create_oidc_idp, call activate_idp($id) — IDPs start inactive.
The scopes default is ["openid","profile","email"].
User types: create_human_user → human login users; create_service_user → machine/JWT users.
Service users can't log in interactively — use machine keys (add_machine_key).
Metadata values: Zitadel stores metadata base64-encoded. The client handles encoding on write
automatically. On read, $meta->{metadata}{value} comes back base64-encoded — decode it yourself
with MIME::Base64::decode_base64($v) if needed.
LWP + self-signed TLS: Add ssl_opts => { verify_hostname => 0 } to LWP::UserAgent->new
for dev instances with self-signed certs (not for production).
CORS: For browser-based OIDC, add allowed origins in ZITADEL under the app's settings.
PostgreSQL 18 + self-hosted: If init fails with "partitioned tables cannot be unlogged", use ZITADEL v4.11.0+ which includes the PG18 compatibility fix.
Offline tests:
cd /storage/raid/home/getty/dev/perl/p5-www-zitadel
prove -lr t
Live issuer tests:
ZITADEL_LIVE_TEST=1 \
ZITADEL_ISSUER='https://your-zitadel.example.com' \
prove -lv t/90-live-zitadel.t
Kubernetes pod reachability test:
ZITADEL_K8S_TEST=1 \
ZITADEL_ISSUER='https://your-zitadel.example.com' \
ZITADEL_KUBECONFIG='/storage/raid/home/getty/avatar/.kube/config' \
prove -lv t/91-k8s-pod.t