Commit 09c7171
Changed files (10)
lib/saml/kit/builders/assertion.rb
@@ -45,7 +45,7 @@ module Saml
def conditions_options
{
NotBefore: now.utc.iso8601,
- NotOnOrAfter: configuration.session_timeout.from_now.utc.iso8601,
+ NotOnOrAfter: configuration.session_timeout.since(now).utc.iso8601,
}
end
@@ -53,7 +53,7 @@ module Saml
{
AuthnInstant: now.iso8601,
SessionIndex: reference_id,
- SessionNotOnOrAfter: 3.hours.since(now).utc.iso8601,
+ SessionNotOnOrAfter: configuration.session_timeout.since(now).utc.iso8601,
}
end
end
lib/saml/kit/builders/authentication_request.rb
@@ -16,11 +16,13 @@ module Saml
@version = "2.0"
end
+ # @deprecated Use {#assertion_consumer_service_url} instead of this method.
def acs_url
Saml::Kit.deprecate("acs_url is deprecated. Use assertion_consumer_service_url instead")
self.assertion_consumer_service_url
end
+ # @deprecated Use {#assertion_consumer_service_url=} instead of this method.
def acs_url=(value)
Saml::Kit.deprecate("acs_url= is deprecated. Use assertion_consumer_service_url= instead")
self.assertion_consumer_service_url = value
lib/saml/kit/authentication_request.rb
@@ -1,8 +1,25 @@
module Saml
module Kit
+ # This class can be used to parse a SAML AuthnRequest or generate one.
+ #
+ # To generate an AuthnRequest use the builder API.
+ #
+ # request = AuthenticationRequest.build do |builder|
+ # builder.name_id_format = [Saml::Kit::Namespaces::EMAIL_ADDRESS]
+ # end
+ #
+ # <?xml version="1.0" encoding="UTF-8"?>
+ # <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_ca3a0e72-9530-41f1-9518-c53716de88b2" Version="2.0" IssueInstant="2017-12-19T16:27:44Z" Destination="http://hartmann.info" AssertionConsumerServiceURL="https://carroll.com/acs">
+ # <saml:Issuer>Day of the Dangerous Cousins</saml:Issuer>
+ # <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"/>
+ # </samlp:AuthnRequest>
class AuthenticationRequest < Document
include Requestable
+ # Create an instance of an AuthnRequest document.
+ #
+ # @param xml [String] the raw xml.
+ # @param configuration [Saml::Kit::Configuration] defaults to the global configuration.
def initialize(xml, configuration: Saml::Kit.configuration)
super(xml, name: "AuthnRequest", configuration: configuration)
end
lib/saml/kit/buildable.rb
@@ -4,15 +4,15 @@ module Saml
extend ActiveSupport::Concern
class_methods do
- def build(*args, &block)
+ def build(*args, &block) # :yields builder
builder(*args, &block).build
end
- def build_xml(*args, &block)
+ def build_xml(*args, &block) # :yields builder
builder(*args, &block).to_xml
end
- def builder(*args)
+ def builder(*args) # :yields builder
builder_class.new(*args).tap do |builder|
yield builder if block_given?
end
lib/saml/kit/composite_metadata.rb
@@ -1,6 +1,6 @@
module Saml
module Kit
- class CompositeMetadata < Metadata
+ class CompositeMetadata < Metadata # :nodoc:
include Enumerable
attr_reader :service_provider, :identity_provider
lib/saml/kit/configuration.rb
@@ -1,12 +1,39 @@
module Saml
module Kit
+ # This class represents the main configuration that is use for generating SAML documents.
+ #
+ # Saml::Kit::Configuration.new do |config|
+ # config.issuer = "com:saml:kit"
+ # config.signature_method = :SHA256
+ # config.digest_method = :SHA256
+ # config.registry = Saml::Kit::DefaultRegistry.new
+ # config.session_timeout = 30.minutes
+ # config.logger = Rails.logger
+ # end
+ #
+ # To specify global configuration it is best to do this in an initialize
+ # that runs at the start of the program.
+ #
+ # Saml::Kit.configure do |configuration|
+ # configuration.issuer = "https://www.example.com/saml/metadata"
+ # configuration.generate_key_pair_for(use: :signing)
+ # configuration.add_key_pair(ENV["X509_CERTIFICATE"], ENV["PRIVATE_KEY"], password: ENV['PRIVATE_KEY_PASSWORD'], use: :encryption)
+ # end
class Configuration
+ # The issuer or entity_id to use.
attr_accessor :issuer
- attr_accessor :signature_method, :digest_method
- attr_accessor :registry, :session_timeout
+ # The signature method to use when generating signatures (See {SAML::Kit::Builders::XmlSignature::SIGNATURE_METHODS})
+ attr_accessor :signature_method
+ # The digest method to use when generating signatures (See {SAML::Kit::Builders::XmlSignature::DIGEST_METHODS})
+ attr_accessor :digest_method
+ # The metadata registry to use for searching for metadata associated with an issuer.
+ attr_accessor :registry
+ # The session timeout to use when generating an Assertion.
+ attr_accessor :session_timeout
+ # The logger to write log messages to.
attr_accessor :logger
- def initialize
+ def initialize # :yields configuration
@signature_method = :SHA256
@digest_method = :SHA256
@registry = DefaultRegistry.new
@@ -16,42 +43,65 @@ module Saml
yield self if block_given?
end
- def add_key_pair(certificate, private_key, password:, use: :signing)
+ # Add a key pair that can be used for either signing or encryption.
+ #
+ # @param certificate [String] the x509 certificate with public key.
+ # @param private_key [String] the plain text private key.
+ # @param password [String] the password to decrypt the private key.
+ # @param use [Symbol] the type of key pair, `:signing` or `:encryption`
+ def add_key_pair(certificate, private_key, password: '', use: :signing)
@key_pairs.push(KeyPair.new(certificate, private_key, password, use.to_sym))
end
+ # Generates a unique key pair that can be used for signing or encryption.
+ #
+ # @param use [Symbol] the type of key pair, `:signing` or `:encryption`
+ # @param password [String] the private key password to use.
def generate_key_pair_for(use:, password: SecureRandom.uuid)
certificate, private_key = SelfSignedCertificate.new(password).create
add_key_pair(certificate, private_key, password: password, use: use)
end
+ # Return each key pair for a specific use.
+ #
+ # @param use [Symbol] the type of key pair to return `nil`, `:signing` or `:encryption`
def key_pairs(use: nil)
use.present? ? @key_pairs.find_all { |x| x.for?(use) } : @key_pairs
end
+ # Return each certificate for a specific use.
+ #
+ # @param use [Symbol] the type of key pair to return `nil`, `:signing` or `:encryption`
def certificates(use: nil)
key_pairs(use: use).flat_map(&:certificate)
end
+ # Return each private for a specific use.
+ #
+ # @param use [Symbol] the type of key pair to return `nil`, `:signing` or `:encryption`
def private_keys(use: :signing)
key_pairs(use: use).flat_map(&:private_key)
end
+ # @deprecated Use {#certificates} instead of this method.
def encryption_certificate
Saml::Kit.deprecate("encryption_certificate is deprecated. Use certificates(use: :encryption) instead")
certificates(use: :encryption).last
end
+ # @deprecated Use {#private_keys} instead of this method.
def signing_private_key
Saml::Kit.deprecate("signing_private_key is deprecated. Use private_keys(use: :signing) instead")
private_keys(use: :signing).last
end
+ # @deprecated Use {#private_keys} instead of this method.
def encryption_private_key
Saml::Kit.deprecate("encryption_private_key is deprecated. Use private_keys(use: :encryption) instead")
private_keys(use: :encryption).last
end
+ # Returns true if there is at least one signing certificate registered.
def sign?
certificates(use: :signing).any?
end
lib/saml/kit/key_pair.rb
@@ -1,6 +1,6 @@
module Saml
module Kit
- class KeyPair
+ class KeyPair # :nodoc:
attr_reader :certificate, :private_key, :use
def initialize(certificate, private_key, password, use)
lib/saml/kit/signatures.rb
@@ -1,6 +1,6 @@
module Saml
module Kit
- class Signatures
+ class Signatures # :nodoc:
attr_reader :configuration
def initialize(configuration:)
lib/saml/kit/xml.rb
@@ -1,6 +1,6 @@
module Saml
module Kit
- class Xml
+ class Xml # :nodoc:
include ActiveModel::Validations
NAMESPACES = {
"NameFormat": Namespaces::ATTR_SPLAT,
spec/saml/authentication_request_spec.rb
@@ -40,6 +40,7 @@ RSpec.describe Saml::Kit::AuthenticationRequest do
it 'is valid when left untampered' do
subject = described_class.new(raw_xml, configuration: configuration)
+ puts subject.to_xml(pretty: true)
expect(subject).to be_valid
end