Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extracts Saml::XML into SamlIdp::XML to free up the use of the Saml namespace #210

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ CERT
# phone: { getter: :phone },
# email: {
# getter: :email,
# name_format: Saml::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS,
# name_id_format: Saml::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS
# name_format: SamlIdp::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS,
# name_id_format: SamlIdp::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS
# }
# }
# end
Expand Down
69 changes: 1 addition & 68 deletions lib/saml_idp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module SamlIdp
require 'active_support/all'
require 'saml_idp/saml_response'
require 'saml_idp/xml'
require 'saml_idp/xml_security'
require 'saml_idp/configurator'
require 'saml_idp/controller'
Expand All @@ -23,71 +24,3 @@ def self.metadata
@metadata ||= MetadataBuilder.new(config)
end
end

# TODO Needs extraction out
module Saml
module XML
module Namespaces
METADATA = "urn:oasis:names:tc:SAML:2.0:metadata"
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
SIGNATURE = "http://www.w3.org/2000/09/xmldsig#"
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"

module Statuses
SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success"
end

module Consents
UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
end

module AuthnContext
module ClassRef
PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
PASSWORD_PROTECTED = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
end
end

module Methods
BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
end

module Formats
module Attr
URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
end

module NameId
EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
end
end
end

class Document < Nokogiri::XML::Document
def signed?
!!xpath("//ds:Signature", ds: signature_namespace).first
end

def valid_signature?(fingerprint)
signed? &&
signed_document.validate(fingerprint, :soft)
end

def signed_document
SamlIdp::XMLSecurity::SignedDocument.new(to_xml)
end

def signature_namespace
Namespaces::SIGNATURE
end

def to_xml
super(
save_with: Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
).strip
end
end
end
end
6 changes: 3 additions & 3 deletions lib/saml_idp/assertion_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ def initialize(

def fresh
builder = Builder::XmlMarkup.new
builder.Assertion xmlns: Saml::XML::Namespaces::ASSERTION,
builder.Assertion xmlns: SamlIdp::XML::Namespaces::ASSERTION,
ID: reference_string,
IssueInstant: now_iso,
Version: "2.0" do |assertion|
assertion.Issuer issuer_uri
sign assertion
assertion.Subject do |subject|
subject.NameID name_id, Format: name_id_format[:name]
subject.SubjectConfirmation Method: Saml::XML::Namespaces::Methods::BEARER do |confirmation|
subject.SubjectConfirmation Method: SamlIdp::XML::Namespaces::Methods::BEARER do |confirmation|
confirmation_hash = {}
confirmation_hash[:InResponseTo] = saml_request_id unless saml_request_id.nil?
confirmation_hash[:NotOnOrAfter] = not_on_or_after_subject
Expand Down Expand Up @@ -92,7 +92,7 @@ def fresh
asserted_attributes.each do |friendly_name, attrs|
attrs = (attrs || {}).with_indifferent_access
attr_statement.Attribute Name: attrs[:name] || friendly_name,
NameFormat: attrs[:name_format] || Saml::XML::Namespaces::Formats::Attr::URI,
NameFormat: attrs[:name_format] || SamlIdp::XML::Namespaces::Formats::Attr::URI,
FriendlyName: friendly_name.to_s do |attr|
values = get_values_for friendly_name, attrs[:getter]
values.each do |val|
Expand Down
2 changes: 1 addition & 1 deletion lib/saml_idp/attribute_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def friendly_name
end

def name_format
source[:name_format] || Saml::XML::Namespaces::Formats::Attr::URI
source[:name_format] || SamlIdp::XML::Namespaces::Formats::Attr::URI
end

def values
Expand Down
2 changes: 1 addition & 1 deletion lib/saml_idp/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def decode_request(raw_saml_request)
end

def authn_context_classref
Saml::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
SamlIdp::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
end

def encode_authn_response(principal, opts = {})
Expand Down
2 changes: 1 addition & 1 deletion lib/saml_idp/encryptor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def encrypt(raw_xml)
encrypted_key = Xmlenc::EncryptedKey.new(encrypted_key_node)
encrypted_key.encrypt(openssl_cert.public_key, encryption_key)
xml = Builder::XmlMarkup.new
xml.EncryptedAssertion xmlns: Saml::XML::Namespaces::ASSERTION do |enc_assert|
xml.EncryptedAssertion xmlns: SamlIdp::XML::Namespaces::ASSERTION do |enc_assert|
enc_assert << encrypted_data.node.to_s
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/incoming_metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def initialize(raw = "")
end

def document
@document ||= Saml::XML::Document.parse raw
@document ||= SamlIdp::XML::Document.parse raw
end

def entity_id
Expand Down Expand Up @@ -149,16 +149,16 @@ def idp_descriptor_document
end

def contact_person_document
@contact_person_document ||= (xpath("//md:ContactPerson", md: metadata_namespace).first || Saml::XML::Document.new)
@contact_person_document ||= (xpath("//md:ContactPerson", md: metadata_namespace).first || SamlIdp::XML::Document.new)
end

def metadata_namespace
Saml::XML::Namespaces::METADATA
SamlIdp::XML::Namespaces::METADATA
end
private :metadata_namespace

def signature_namespace
Saml::XML::Namespaces::SIGNATURE
SamlIdp::XML::Namespaces::SIGNATURE
end
private :signature_namespace
end
Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/logout_request_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ def build
Version: "2.0",
IssueInstant: now_iso,
Destination: saml_slo_url,
"xmlns" => Saml::XML::Namespaces::PROTOCOL do |request|
request.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION
"xmlns" => SamlIdp::XML::Namespaces::PROTOCOL do |request|
request.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION
sign request
request.NameID name_id, xmlns: Saml::XML::Namespaces::ASSERTION,
Format: Saml::XML::Namespaces::Formats::NameId::PERSISTENT
request.NameID name_id, xmlns: SamlIdp::XML::Namespaces::ASSERTION,
Format: SamlIdp::XML::Namespaces::Formats::NameId::PERSISTENT
request.SessionIndex response_id_string
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/logout_response_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ def build
IssueInstant: now_iso,
Destination: saml_slo_url,
InResponseTo: saml_request_id,
xmlns: Saml::XML::Namespaces::PROTOCOL do |response|
response.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION
xmlns: SamlIdp::XML::Namespaces::PROTOCOL do |response|
response.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION
sign response
response.Status xmlns: Saml::XML::Namespaces::PROTOCOL do |status|
status.StatusCode Value: Saml::XML::Namespaces::Statuses::SUCCESS
response.Status xmlns: SamlIdp::XML::Namespaces::PROTOCOL do |status|
status.StatusCode Value: SamlIdp::XML::Namespaces::Statuses::SUCCESS
end
end
end
Expand Down
10 changes: 5 additions & 5 deletions lib/saml_idp/metadata_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ def fresh
builder = Builder::XmlMarkup.new
generated_reference_id do
builder.EntityDescriptor ID: reference_string,
xmlns: Saml::XML::Namespaces::METADATA,
"xmlns:saml" => Saml::XML::Namespaces::ASSERTION,
"xmlns:ds" => Saml::XML::Namespaces::SIGNATURE,
xmlns: SamlIdp::XML::Namespaces::METADATA,
"xmlns:saml" => SamlIdp::XML::Namespaces::ASSERTION,
"xmlns:ds" => SamlIdp::XML::Namespaces::SIGNATURE,
entityID: entity_id do |entity|
sign entity

Expand Down Expand Up @@ -56,7 +56,7 @@ def fresh

def build_key_descriptor(el)
el.KeyDescriptor use: "signing" do |key_descriptor|
key_descriptor.KeyInfo xmlns: Saml::XML::Namespaces::SIGNATURE do |key_info|
key_descriptor.KeyInfo xmlns: SamlIdp::XML::Namespaces::SIGNATURE do |key_info|
key_info.X509Data do |x509|
x509.X509Certificate x509_certificate
end
Expand Down Expand Up @@ -128,7 +128,7 @@ def entity_id
private :entity_id

def protocol_enumeration
Saml::XML::Namespaces::PROTOCOL
SamlIdp::XML::Namespaces::PROTOCOL
end
private :protocol_enumeration

Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def response_host
private :response_host

def document
@_document ||= Saml::XML::Document.parse(raw_xml)
@_document ||= SamlIdp::XML::Document.parse(raw_xml)
end
private :document

Expand All @@ -179,17 +179,17 @@ def logout_request
private :logout_request

def samlp
Saml::XML::Namespaces::PROTOCOL
SamlIdp::XML::Namespaces::PROTOCOL
end
private :samlp

def assertion
Saml::XML::Namespaces::ASSERTION
SamlIdp::XML::Namespaces::ASSERTION
end
private :assertion

def signature_namespace
Saml::XML::Namespaces::SIGNATURE
SamlIdp::XML::Namespaces::SIGNATURE
end
private :signature_namespace

Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/response_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ def build
resp_options[:Version] = "2.0"
resp_options[:IssueInstant] = now_iso
resp_options[:Destination] = saml_acs_url
resp_options[:Consent] = Saml::XML::Namespaces::Consents::UNSPECIFIED
resp_options[:Consent] = SamlIdp::XML::Namespaces::Consents::UNSPECIFIED
resp_options[:InResponseTo] = saml_request_id unless saml_request_id.nil?
resp_options["xmlns:samlp"] = Saml::XML::Namespaces::PROTOCOL
resp_options["xmlns:samlp"] = SamlIdp::XML::Namespaces::PROTOCOL

builder = Builder::XmlMarkup.new
builder.tag! "samlp:Response", resp_options do |response|
response.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION
response.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION
sign response
response.tag! "samlp:Status" do |status|
status.tag! "samlp:StatusCode", Value: Saml::XML::Namespaces::Statuses::SUCCESS
status.tag! "samlp:StatusCode", Value: SamlIdp::XML::Namespaces::Statuses::SUCCESS
end
response << assertion_and_signature
end
Expand Down
68 changes: 68 additions & 0 deletions lib/saml_idp/xml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
require 'nokogiri'

module SamlIdp
module XML
module Namespaces
METADATA = "urn:oasis:names:tc:SAML:2.0:metadata"
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
SIGNATURE = "http://www.w3.org/2000/09/xmldsig#"
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"

module Statuses
SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success"
end

module Consents
UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
end

module AuthnContext
module ClassRef
PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
PASSWORD_PROTECTED = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
end
end

module Methods
BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
end

module Formats
module Attr
URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
end

module NameId
EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
end
end
end

class Document < Nokogiri::XML::Document
def signed?
!!xpath("//ds:Signature", ds: signature_namespace).first
end

def valid_signature?(fingerprint)
signed? &&
signed_document.validate(fingerprint, :soft)
end

def signed_document
SamlIdp::XMLSecurity::SignedDocument.new(to_xml)
end

def signature_namespace
Namespaces::SIGNATURE
end

def to_xml
super(
save_with: Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
).strip
end
end
end
end
2 changes: 1 addition & 1 deletion spec/lib/saml_idp/assertion_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module SamlIdp
let(:saml_acs_url) { "http://saml.acs.url" }
let(:algorithm) { :sha256 }
let(:authn_context_classref) {
Saml::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
SamlIdp::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
}
let(:expiry) { 3*60*60 }
let (:encryption_opts) do
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/saml_idp/attribute_decorator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module SamlIdp
end

it "has a valid name_format" do
expect(subject.name_format).to eq(Saml::XML::Namespaces::Formats::Attr::URI)
expect(subject.name_format).to eq(SamlIdp::XML::Namespaces::Formats::Attr::URI)
end

it "has a valid values" do
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/saml_idp/metadata_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module SamlIdp
end

it "signs valid xml" do
expect(Saml::XML::Document.parse(subject.signed).valid_signature?(Default::FINGERPRINT)).to be_truthy
expect(SamlIdp::XML::Document.parse(subject.signed).valid_signature?(Default::FINGERPRINT)).to be_truthy
end

it "includes logout element" do
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/saml_idp/saml_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module SamlIdp
let(:x509_certificate) { Default::X509_CERTIFICATE }
let(:xauthn) { Default::X509_CERTIFICATE }
let(:authn_context_classref) {
Saml::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
SamlIdp::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
}
let(:expiry) { 3 * 60 * 60 }
let(:session_expiry) { 24 * 60 * 60 }
Expand Down
Loading