Projet

Général

Profil

SpPythonTutorial

Simplest service provider AssertionConsumer ever as a WSGI application

The prerequisite for this example is:
  • you must set the IdP signature and encryption keys in the idp_metata_xml string containing the IdP metadata file,
    you can replace it completely by the IdP metadata file if you have one,
  • the AuthnResponse is transmitted using the HTTP-Post binding.
import sys
import lasso
from wsgiref.simple_server import make_server
import logging
import urlparse

logging.basicConfig(level=logging.DEBUG)

sp_metadata_xml = '''<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" 
      xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
      xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
      entityID="http://localhost:8081/metadata">
  <SPSSODescriptor
      AuthnRequestsSigned="true" 
      protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">

    <AssertionConsumerService isDefault="true" index="0" 
      Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" 
      Location="http://localhost:8081/singleSignOnPost" />
    <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
  </SPSSODescriptor>
  <Organization>
     <OrganizationName xml:lang="en">Example SAML 2.0 metadatas</OrganizationName>
  </Organization>
</EntityDescriptor>'''

idp_metadata_xml = '''<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" 
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
    entityID="http://localhost:3001/saml/metadata">

  <IDPSSODescriptor
      WantAuthnRequestsSigned="true" 
      protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <KeyDescriptor use="signing">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <KeyValue  xmlns="http://www.w3.org/2000/09/xmldsig#">
    <RSAKeyValue>
        <Modulus>4yalpsp9Sxlsj07PEI8jJxhSJdo4F0iW0H8u1dhwmsW5YQvRUw/yPlmC09q4WjImmnFVNCJarAOYeFgQCxfIoBasKNnUeBQpogo8W0Q/3mCuKl6lNSr/PIuxMVVNPDWmWkhHXJx/MVar2IREKa1P4jHL0Uxl69/idLwc7TtK1h8=</Modulus>
        <Exponent>AQAB</Exponent>
    </RSAKeyValue>
</KeyValue>
      </ds:KeyInfo>
    </KeyDescriptor>
    <KeyDescriptor use="encryption">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <KeyValue  xmlns="http://www.w3.org/2000/09/xmldsig#">
    <RSAKeyValue>
        <Modulus>wLu5SdmwyS4o1On/aw4nElLGERFG931exvkzu0ewaM1/oUyD3dO7UC5xMGnPfc6IaH5BcJc3fLr6PJhX55ZrMR98ToPwoUFwuLKK43exwYBEBOOMe1CrCB/Bq+EH6/2sKNXKfgJqj06/3yzafLRiWpMxy2isllxMAvaZXrkpm4c=</Modulus>
        <Exponent>AQAB</Exponent>
    </RSAKeyValue>
</KeyValue>
      </ds:KeyInfo>
    </KeyDescriptor>
  </IDPSSODescriptor>

</EntityDescriptor>
'''

def app(environ, start_response):
    server = lasso.Server.newFromBuffers(sp_metadata_xml)
    server.addProviderFromBuffer(lasso.PROVIDER_ROLE_IDP, idp_metadata_xml)
    login = lasso.Login(server)
    try:
        data = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))
        qs = urlparse.parse_qs(data)
        try:
            login.processAuthnResponseMsg(qs['SAMLResponse'][0])
        except (lasso.DsError, lasso.ProfileCannotVerifySignatureError):
            raise Exception('Invalid signature')
        except lasso.Error:
            raise Exception('Misc error')
        try:
            login.acceptSso()
        except lasso.Error:
            raise Exception('Invalid assertion')
    except Exception, e:
        start_response('500 Internal Error', [('content-type', 'text/plain')],
            sys.exc_info())
        return ['Erreur: ', str(e)]
    else:
        start_response('200 Ok', [('content-type', 'text/plain')], sys.exc_info())
        return ['You are identified as ', login.assertion.subject.nameId.content]

s = make_server('0.0.0.0', 8081, app)
s.serve_forever()

Formats disponibles : PDF HTML TXT