providers/saml: add verification_kp when verifying assertions against certificates without private key
This commit is contained in:
parent
5cb7f0794e
commit
1edcda58ba
|
@ -25,6 +25,7 @@ class SAMLProviderSerializer(ModelSerializer):
|
||||||
"signature_algorithm",
|
"signature_algorithm",
|
||||||
"signing_kp",
|
"signing_kp",
|
||||||
"require_signing",
|
"require_signing",
|
||||||
|
"verification_kp",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,12 @@ class SAMLProviderForm(forms.ModelForm):
|
||||||
"assertion_valid_not_before",
|
"assertion_valid_not_before",
|
||||||
"assertion_valid_not_on_or_after",
|
"assertion_valid_not_on_or_after",
|
||||||
"session_valid_not_on_or_after",
|
"session_valid_not_on_or_after",
|
||||||
"property_mappings",
|
|
||||||
"digest_algorithm",
|
"digest_algorithm",
|
||||||
"require_signing",
|
"require_signing",
|
||||||
"signature_algorithm",
|
"signature_algorithm",
|
||||||
"signing_kp",
|
"signing_kp",
|
||||||
|
"verification_kp",
|
||||||
|
"property_mappings",
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
"name": forms.TextInput(),
|
"name": forms.TextInput(),
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated by Django 3.1.3 on 2020-11-08 21:22
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("passbook_crypto", "0002_create_self_signed_kp"),
|
||||||
|
("passbook_providers_saml", "0006_remove_samlprovider_name"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="samlprovider",
|
||||||
|
name="verification_kp",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
default=None,
|
||||||
|
help_text="If selected, incoming assertion's Signatures will be validated.",
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name="+",
|
||||||
|
to="passbook_crypto.certificatekeypair",
|
||||||
|
verbose_name="Verification Keypair",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -87,6 +87,15 @@ class SAMLProvider(Provider):
|
||||||
default="rsa-sha256",
|
default="rsa-sha256",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
verification_kp = models.ForeignKey(
|
||||||
|
CertificateKeyPair,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
help_text=_("If selected, incoming assertion's Signatures will be validated."),
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
verbose_name=_("Verification Keypair"),
|
||||||
|
related_name="+",
|
||||||
|
)
|
||||||
signing_kp = models.ForeignKey(
|
signing_kp = models.ForeignKey(
|
||||||
CertificateKeyPair,
|
CertificateKeyPair,
|
||||||
default=None,
|
default=None,
|
||||||
|
|
|
@ -69,10 +69,11 @@ class AuthNRequestParser:
|
||||||
"""Validate and parse raw request with enveloped signautre."""
|
"""Validate and parse raw request with enveloped signautre."""
|
||||||
decoded_xml = decode_base64_and_inflate(saml_request)
|
decoded_xml = decode_base64_and_inflate(saml_request)
|
||||||
|
|
||||||
if self.provider.signing_kp:
|
if self.provider.verification_kp:
|
||||||
try:
|
try:
|
||||||
XMLVerifier().verify(
|
XMLVerifier().verify(
|
||||||
decoded_xml, x509_cert=self.provider.signing_kp.certificate_data
|
decoded_xml,
|
||||||
|
x509_cert=self.provider.verification_kp.certificate_data,
|
||||||
)
|
)
|
||||||
except InvalidSignature as exc:
|
except InvalidSignature as exc:
|
||||||
raise CannotHandleAssertion("Failed to verify signature") from exc
|
raise CannotHandleAssertion("Failed to verify signature") from exc
|
||||||
|
@ -98,7 +99,11 @@ class AuthNRequestParser:
|
||||||
querystring += f"RelayState={quote_plus(relay_state)}&"
|
querystring += f"RelayState={quote_plus(relay_state)}&"
|
||||||
querystring += f"SigAlg={sig_alg}"
|
querystring += f"SigAlg={sig_alg}"
|
||||||
|
|
||||||
public_key = self.provider.signing_kp.private_key.public_key()
|
if not self.provider.verification_kp:
|
||||||
|
raise CannotHandleAssertion(
|
||||||
|
"Provider does not have a Validation Certificate configured."
|
||||||
|
)
|
||||||
|
public_key = self.provider.verification_kp.private_key.public_key()
|
||||||
try:
|
try:
|
||||||
public_key.verify(
|
public_key.verify(
|
||||||
b64decode(signature),
|
b64decode(signature),
|
||||||
|
|
Reference in New Issue