Skip to content

Instantly share code, notes, and snippets.

@bureado
Created May 20, 2015 18:49
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bureado/5dbddb0bb24bb7c0b447 to your computer and use it in GitHub Desktop.
Save bureado/5dbddb0bb24bb7c0b447 to your computer and use it in GitHub Desktop.
Setting up python-saml for Azure AD
#!/usr/bin/env python
"""
This script will help you authenticate a Django application using python-saml with Azure AD.
This is sample code.
Usage:
./script.py <application host> <federation metadata URL>
Example:
python script.py http://vm.cloudapp.net https://login.microsoftonline.com/95133f51-071a-4531-99b9-5a3b9a116600/federationmetadata/2007-06/federationmetadata.xml > saml/settings.json
1. Get and build python-saml from https://github.com/onelogin/python-saml
* In Ubuntu, requirements include python-libxml2 libxml2-dev libxmlsec1-dev libpython2.7-dev swig python-django python-lxml python-isodate
* Also, sudo pip install untangle to use this script.
2. Create your Azure AD domain, a user for testing, and an application
* SSO URI is http://fqdn/?sso
* ID URI is http://fqdn/metadata/
3. Grab the federation metadata URL for your application (under "View endpoints")
4. Use this script to generate a demo-django/saml/settings.json file
5. Run python manage.py runserver and browse to http://fqdn/?sso
"""
import untangle
import base64
import re
import json
import sys
from subprocess import Popen, PIPE, STDOUT
host = sys.argv[1]
addr = sys.argv[2]
obj = untangle.parse(addr)
svc = obj.EntityDescriptor.IDPSSODescriptor.SingleSignOnService[0]["Location"]
der = base64.b64decode(obj.EntityDescriptor.ds_Signature.KeyInfo.X509Data.X509Certificate.cdata)
ssl = Popen(["openssl", "x509", "-fingerprint", "-inform", "der", "-noout"], stdout=PIPE, stdin=PIPE)
out = ssl.communicate(input=der)[0]
bts = out.decode().rstrip().split('=')[1].split(':')[0:20]
fin = ''.join(bts).lower()
jac = { "url": host + "/?acs", "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" }
jsl = { "url": host + "/?sls", "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" }
jsp = { "entityId": host + "/metadata", "assertionConsumerService": jac, "singleLogoutService": jsl, "NameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" }
jso = { "url": svc, "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" }
jsu = { "url": svc, "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" }
jid = { "entityId": svc, "singleSignOnService": jso, "singleLogoutService": jsu, "certFingerprint": fin }
stg = { "strict": "true", "debug": "true", "sp": jsp, "idp": jid }
print json.dumps(stg)
@hobzcalvin
Copy link

hobzcalvin commented Sep 8, 2016

Thanks for posting this! FYI to get it working, I needed to change ds_Signature to Signature on line 43. The XML returned by the Microsoft endpoint had no ds_Signature element.

@merutak
Copy link

merutak commented Oct 7, 2017

I had to make several changes, notably remove the 'metadata/' suffix from the "issuer", "login" and "logout" URLs.

Copy link

ghost commented Dec 4, 2017

Thanks for sharing.

FYI, yesterday I got the "metadata.xml" of Azure IDP from our company's administrator, and the data format is a little different.

So I modified the line 43 as following for my circumstance:

der = base64.b64decode(obj.EntityDescriptor.RoleDescriptor[0].KeyDescriptor.KeyInfo.X509Data.X509Certificate.cdata)

to @hobzcalvin @merutak @bureado :

By the way, I just start SSO related work on Python flask+Python3-saml with Azue as IDP, I appreciate if anyone could share me some an complete example of SP.

Thanks!

@asfaltboy
Copy link

@gongmingwei did you manage to finish off your SSO/SAML solution? Could you share you experience, or point us new to the area to some resources?

@mhoangpayfone
Copy link

Hi, @ghost I'm also working on getting an Azure SAML SSO + flask + python 3. I'm currently using pysaml2 but I'm getting bad responses from the IDP. Were you able to get your project working?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment