sources/saml: fix AuthnRequest Singing for redirect bindings
This commit is contained in:
parent
8aa0b72b67
commit
ff6e270886
|
@ -1,20 +1,22 @@
|
||||||
"""SAML AuthnRequest Processor"""
|
"""SAML AuthnRequest Processor"""
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import padding
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from lxml import etree # nosec
|
from lxml import etree # nosec
|
||||||
from lxml.etree import Element # nosec
|
from lxml.etree import Element # nosec
|
||||||
from signxml import XMLSigner, methods
|
from signxml import XMLSigner
|
||||||
|
|
||||||
from passbook.providers.saml.utils import get_random_id
|
from passbook.providers.saml.utils import get_random_id
|
||||||
from passbook.providers.saml.utils.encoding import deflate_and_base64_encode
|
from passbook.providers.saml.utils.encoding import deflate_and_base64_encode, nice64
|
||||||
from passbook.providers.saml.utils.time import get_time_string
|
from passbook.providers.saml.utils.time import get_time_string
|
||||||
from passbook.sources.saml.models import SAMLSource
|
from passbook.sources.saml.models import SAMLSource
|
||||||
from passbook.sources.saml.processors.constants import (
|
from passbook.sources.saml.processors.constants import (
|
||||||
NS_MAP,
|
NS_MAP,
|
||||||
NS_SAML_ASSERTION,
|
NS_SAML_ASSERTION,
|
||||||
NS_SAML_PROTOCOL,
|
NS_SAML_PROTOCOL,
|
||||||
NS_SIGNATURE,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,27 +84,37 @@ class RequestProcessor:
|
||||||
|
|
||||||
def build_auth_n_detached(self) -> Dict[str, str]:
|
def build_auth_n_detached(self) -> Dict[str, str]:
|
||||||
"""Get Dict AuthN Request for Redirect bindings, with detached
|
"""Get Dict AuthN Request for Redirect bindings, with detached
|
||||||
Signature"""
|
Signature. See https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf"""
|
||||||
auth_n_request = self.get_auth_n()
|
auth_n_request = self.get_auth_n()
|
||||||
|
|
||||||
|
saml_request = deflate_and_base64_encode(
|
||||||
|
etree.tostring(auth_n_request).decode()
|
||||||
|
)
|
||||||
|
|
||||||
response_dict = {
|
response_dict = {
|
||||||
"SAMLRequest": deflate_and_base64_encode(
|
"SAMLRequest": saml_request,
|
||||||
etree.tostring(auth_n_request).decode()
|
|
||||||
),
|
|
||||||
"RelayState": self.relay_state
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.relay_state != "":
|
||||||
|
response_dict["RelayState"] = self.relay_state
|
||||||
|
|
||||||
if self.source.signing_kp:
|
if self.source.signing_kp:
|
||||||
signer = XMLSigner(methods.detached)
|
sig_alg = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
|
||||||
signature = signer.sign(
|
sig_hash = hashes.SHA1() # nosec
|
||||||
auth_n_request,
|
# Create the full querystring in the correct order to be signed
|
||||||
cert=self.source.signing_kp.certificate_data,
|
querystring = f"SAMLRequest={quote_plus(saml_request)}&"
|
||||||
key=self.source.signing_kp.key_data,
|
if self.relay_state != "":
|
||||||
|
querystring += f"RelayState={quote_plus(self.relay_state)}&"
|
||||||
|
querystring += f"SigAlg={sig_alg}"
|
||||||
|
|
||||||
|
signature = self.source.signing_kp.private_key.sign(
|
||||||
|
querystring.encode(),
|
||||||
|
padding.PSS(
|
||||||
|
mgf=padding.MGF1(sig_hash), salt_length=padding.PSS.MAX_LENGTH
|
||||||
|
),
|
||||||
|
sig_hash,
|
||||||
)
|
)
|
||||||
signature_value = signature.find(
|
response_dict["SigAlg"] = sig_alg
|
||||||
f".//{{{NS_SIGNATURE}}}SignatureValue"
|
response_dict["Signature"] = nice64(signature)
|
||||||
).text
|
|
||||||
response_dict["Signature"] = signature_value
|
|
||||||
response_dict["SigAlg"] = signer.sign_alg
|
|
||||||
|
|
||||||
return response_dict
|
return response_dict
|
||||||
|
|
Reference in New Issue