saml-rs 0.3.0

Pure-Rust SAML 2.0 Service Provider and Identity Provider support.
Documentation
use crate::config::NameIdFormat;

/// NameID value and optional format.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NameId {
    value: String,
    format: Option<NameIdFormat>,
}

impl NameId {
    /// Create a NameID value.
    pub fn new(value: impl Into<String>, format: Option<NameIdFormat>) -> Self {
        Self {
            value: value.into(),
            format,
        }
    }

    /// Borrow the NameID text.
    pub fn value(&self) -> &str {
        &self.value
    }

    /// NameID format, when extracted.
    pub fn format(&self) -> Option<&NameIdFormat> {
        self.format.as_ref()
    }
}

/// AuthnRequest NameIDPolicy.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NameIdPolicy {
    format: Option<NameIdFormat>,
    creation_request: NameIdCreationRequest,
}

/// AuthnRequest NameID creation request.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NameIdCreationRequest {
    /// The request did not specify whether the IdP may create a new identifier.
    Unspecified,
    /// The IdP may create a new identifier.
    AllowCreate,
    /// The IdP must not create a new identifier.
    DoNotAllowCreate,
}

impl NameIdPolicy {
    /// Create a NameIDPolicy model.
    pub fn new(format: Option<NameIdFormat>, creation_request: NameIdCreationRequest) -> Self {
        Self {
            format,
            creation_request,
        }
    }

    /// Create a NameIDPolicy without an AllowCreate preference.
    pub fn unspecified(format: Option<NameIdFormat>) -> Self {
        Self::new(format, NameIdCreationRequest::Unspecified)
    }

    /// Create a NameIDPolicy allowing the IdP to create a new identifier.
    pub fn allow_creation(format: Option<NameIdFormat>) -> Self {
        Self::new(format, NameIdCreationRequest::AllowCreate)
    }

    /// Create a NameIDPolicy forbidding the IdP from creating a new identifier.
    pub fn disallow_creation(format: Option<NameIdFormat>) -> Self {
        Self::new(format, NameIdCreationRequest::DoNotAllowCreate)
    }

    pub(crate) fn from_parsed(
        format: Option<NameIdFormat>,
        allow_create: Option<bool>,
    ) -> Option<Self> {
        if format.is_none() && allow_create.is_none() {
            return None;
        }
        Some(match allow_create {
            Some(true) => Self::allow_creation(format),
            Some(false) => Self::disallow_creation(format),
            None => Self::unspecified(format),
        })
    }

    /// Requested NameID format.
    pub fn format(&self) -> Option<&NameIdFormat> {
        self.format.as_ref()
    }

    /// NameID creation request.
    pub fn creation_request(&self) -> NameIdCreationRequest {
        self.creation_request
    }

    /// Whether the IdP may create a new identifier.
    pub fn allow_create(&self) -> Option<bool> {
        match self.creation_request {
            NameIdCreationRequest::Unspecified => None,
            NameIdCreationRequest::AllowCreate => Some(true),
            NameIdCreationRequest::DoNotAllowCreate => Some(false),
        }
    }
}

/// SubjectConfirmation captured from the validated flow result.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SubjectConfirmation {
    raw_xml: String,
}

impl SubjectConfirmation {
    /// Create a subject confirmation from extractor context XML.
    pub fn from_raw_xml(raw_xml: impl Into<String>) -> Self {
        Self {
            raw_xml: raw_xml.into(),
        }
    }

    /// Borrow the raw confirmation XML captured by the extractor.
    pub fn raw_xml(&self) -> &str {
        &self.raw_xml
    }
}

/// SAML subject.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Subject {
    name_id: NameId,
    confirmations: Vec<SubjectConfirmation>,
}

impl Subject {
    /// Create a subject.
    pub fn new(name_id: NameId, confirmations: Vec<SubjectConfirmation>) -> Self {
        Self {
            name_id,
            confirmations,
        }
    }

    /// Subject NameID.
    pub fn name_id(&self) -> &NameId {
        &self.name_id
    }

    /// Subject confirmations.
    pub fn confirmations(&self) -> &[SubjectConfirmation] {
        &self.confirmations
    }
}