NAME

Punk::SAML::Error - what a refusal throws

DESCRIPTION

Every refusal in this distribution throws one of these: a blessed hashref with a code and a message.

eval { Punk::SAML::Response->verify($bytes, %opts) };
if (ref $@) {
    warn "saml refused: $@->{code}";
}

code

The interface. The route logs it, the tests assert on it, this page lists it, and an operator greps for it. Codes are added, never reworded.

message

For the log. It never reaches the browser: a verifier that tells the far side which check it failed is telling an attacker which one to work on next. Every refusal produces the same page.

CODES

xml_parse

the document is not well-formed XML, carries a DOCTYPE, or has two elements with the same ID.

xml_shape

the document parsed but is not the shape a Response must have: a wrong root, a wrong Version, no Assertion or more than one, no Subject, no NameID, no bearer SubjectConfirmation, or no AuthnStatement.

bad_base64

the SAMLResponse field is over max_response, or is not strict standard base64.

bad_datetime

a timestamp is not an xs:dateTime in UTC. Core section 1.3.3 requires UTC, and an offset is refused rather than converted.

no_signature

nothing is signed that require_signed requires to be.

bad_signature

a signature is present and does not verify, for any reason: a Reference naming another element, a refused transform, or no configured key verifying it.

bad_digest

the reference digest does not match the element the signature covers, which is what an edited assertion looks like.

alg_refused

a SignatureMethod or DigestMethod this plugin does not accept, including rsa-sha1 and, on the digest side, SHA-1 without allow_sha1.

unknown_issuer

the Issuer is not the provider's entity id.

no_key

no signing certificate is configured for the provider.

expired

the assertion or its subject confirmation window has passed, allowing skew.

not_yet_valid

the assertion is not valid yet, allowing skew. Usually a clock difference larger than skew.

bad_audience

no AudienceRestriction names this application.

bad_destination

the Destination or the SubjectConfirmationData Recipient is not this application's assertion consumer URL.

bad_in_response_to

the Response answers a different login, or answers one this application has no record of starting.

replay

the assertion has been presented before.

unsolicited

there is no flow record and allow_idp_initiated is off.

encrypted_assertion

the Response carries an EncryptedAssertion, which is refused rather than decrypted.

status

the provider returned a StatusCode other than Success. The nested code and any StatusMessage are in the message.

config

a provider was misconfigured or its metadata could not be used.

SEE ALSO

Punk::Plugin::SAML, whose WHAT IS CHECKED section gives these in the order they are checked.

AUTHOR

LNATION, <email at lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION.

This is free software, licensed under the Artistic License 2.0.