PKG-INFO 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. Metadata-Version: 1.1
  2. Name: djangosaml2
  3. Version: 0.13.0
  4. Summary: pysaml2 integration in Django
  5. Home-page: https://bitbucket.org/lgs/djangosaml2
  6. Author: Yaco Sistemas
  7. Author-email: lgs@yaco.es
  8. License: Apache 2.0
  9. Description: .. contents::
  10. ===========
  11. djangosaml2
  12. ===========
  13. djangosaml2 is a Django application that integrates the PySAML2 library
  14. into your project. This mean that you can protect your Django based project
  15. with a service provider based on PySAML. This way it will talk SAML2 with
  16. your Identity Provider allowing you to use this authentication mechanism.
  17. This document will guide you through a few simple steps to accomplish
  18. such goal.
  19. Installation
  20. ============
  21. PySAML2 uses xmlsec1_ binary to sign SAML assertions so you need to install
  22. it either through your operating system package or by compiling the source
  23. code. It doesn't matter where the final executable is installed because
  24. you will need to set the full path to it in the configuration stage.
  25. .. _xmlsec1: http://www.aleksey.com/xmlsec/
  26. Now you can install the djangosaml2 package using easy_install or pip. This
  27. will also install PySAML2 and its dependencies automatically.
  28. Configuration
  29. =============
  30. There are three things you need to setup to make djangosaml2 works in your
  31. Django project:
  32. 1. **settings.py** as you may already know, it is the main Django
  33. configuration file.
  34. 2. **urls.py** is the file where you will include djangosaml2 urls.
  35. 3. **pysaml2** specific files such as a attribute map directory and a
  36. certificate.
  37. Changes in the settings.py file
  38. -------------------------------
  39. The first thing you need to do is add ``djangosaml2`` to the list of
  40. installed apps::
  41. INSTALLED_APPS = (
  42. 'django.contrib.auth',
  43. 'django.contrib.contenttypes',
  44. 'django.contrib.sessions',
  45. 'django.contrib.sites',
  46. 'django.contrib.messages',
  47. 'django.contrib.admin',
  48. 'djangosaml2', # new application
  49. )
  50. Actually this is not really required since djangosaml2 does not include
  51. any data model. The only reason we include it is to be able to run
  52. djangosaml2 test suite from our project, something you should always
  53. do to make sure it is compatible with your Django version and environment.
  54. .. note::
  55. When you finish the configuation you can run the djangosaml2 test suite
  56. as you run any other Django application test suite. Just type
  57. ``python manage.py test djangosaml2``
  58. Then you have to add the djangosaml2.backends.Saml2Backend
  59. authentication backend to the list of authentications backends.
  60. By default only the ModelBackend included in Django is configured.
  61. A typical configuration would look like this::
  62. AUTHENTICATION_BACKENDS = (
  63. 'django.contrib.auth.backends.ModelBackend',
  64. 'djangosaml2.backends.Saml2Backend',
  65. )
  66. .. note::
  67. Before djangosaml2 0.5.0 this authentication backend was
  68. automatically added by djangosaml2. This turned out to be
  69. a bad idea since some applications want to use their own
  70. custom policies for authorization and the authentication
  71. backend is a good place to define that. Starting from
  72. djangosaml2 0.5.0 it is now possible to define such
  73. backends.
  74. Finally we have to tell Django what is the new login url we want to use::
  75. LOGIN_URL = '/saml2/login/'
  76. SESSION_EXPIRE_AT_BROWSER_CLOSE = True
  77. Here we are telling Django that any view that requires an authenticated
  78. user should redirect the user browser to that url if the user has not
  79. been authenticated before. We are also telling that when the user closes
  80. his browser, the session should be terminated. This is useful in SAML2
  81. federations where the logout protocol is not always available.
  82. .. note::
  83. The login url starts with ``/saml2/`` as an example but you can change that
  84. if you want. Check the section about changes in the ``urls.py``
  85. file for more information.
  86. If you want to allow several authentication mechanisms in your project
  87. you should set the LOGIN_URL option to another view and put a link in such
  88. view to the ``/saml2/login/`` view.
  89. Changes in the urls.py file
  90. ---------------------------
  91. The next thing you need to do is to include ``djangosaml2.urls`` module to your
  92. main ``urls.py`` module::
  93. urlpatterns = patterns(
  94. '',
  95. # lots of url definitions here
  96. (r'^saml2/', include('djangosaml2.urls')),
  97. # more url definitions
  98. )
  99. As you can see we are including ``djangosaml2.urls`` under the *saml2*
  100. prefix. Feel free to use your own prefix but be consistent with what
  101. you have put in the ``settings.py`` file in the LOGIN_URL parameter.
  102. PySAML2 specific files and configuration
  103. ----------------------------------------
  104. Once you have finished configuring your Django project you have to
  105. start configuring PySAML. If you use just that library you have to
  106. put your configuration options in a file and initialize PySAML2 with
  107. the path to that file.
  108. In djangosaml2 you just put the same information in the Django
  109. settings.py file under the SAML_CONFIG option.
  110. We will see a typical configuration for protecting a Django project::
  111. from os import path
  112. import saml2
  113. BASEDIR = path.dirname(path.abspath(__file__))
  114. SAML_CONFIG = {
  115. # full path to the xmlsec1 binary programm
  116. 'xmlsec_binary': '/usr/bin/xmlsec1',
  117. # your entity id, usually your subdomain plus the url to the metadata view
  118. 'entityid': 'http://localhost:8000/saml2/metadata/',
  119. # directory with attribute mapping
  120. 'attribute_map_dir': path.join(BASEDIR, 'attribute-maps'),
  121. # this block states what services we provide
  122. 'service': {
  123. # we are just a lonely SP
  124. 'sp' : {
  125. 'name': 'Federated Django sample SP',
  126. 'name_id_format': saml2.saml.NAMEID_FORMAT_PERSISTENT,
  127. 'endpoints': {
  128. # url and binding to the assetion consumer service view
  129. # do not change the binding or service name
  130. 'assertion_consumer_service': [
  131. ('http://localhost:8000/saml2/acs/',
  132. saml2.BINDING_HTTP_POST),
  133. ],
  134. # url and binding to the single logout service view
  135. # do not change the binding or service name
  136. 'single_logout_service': [
  137. ('http://localhost:8000/saml2/ls/',
  138. saml2.BINDING_HTTP_REDIRECT),
  139. ],
  140. ('http://localhost:8000/saml2/ls/post',
  141. saml2.BINDING_HTTP_POST),
  142. ],
  143. },
  144. # attributes that this project need to identify a user
  145. 'required_attributes': ['uid'],
  146. # attributes that may be useful to have but not required
  147. 'optional_attributes': ['eduPersonAffiliation'],
  148. # in this section the list of IdPs we talk to are defined
  149. 'idp': {
  150. # we do not need a WAYF service since there is
  151. # only an IdP defined here. This IdP should be
  152. # present in our metadata
  153. # the keys of this dictionary are entity ids
  154. 'https://localhost/simplesaml/saml2/idp/metadata.php': {
  155. 'single_sign_on_service': {
  156. saml2.BINDING_HTTP_REDIRECT: 'https://localhost/simplesaml/saml2/idp/SSOService.php',
  157. },
  158. 'single_logout_service': {
  159. saml2.BINDING_HTTP_REDIRECT: 'https://localhost/simplesaml/saml2/idp/SingleLogoutService.php',
  160. },
  161. },
  162. },
  163. },
  164. },
  165. # where the remote metadata is stored
  166. 'metadata': {
  167. 'local': [path.join(BASEDIR, 'remote_metadata.xml')],
  168. },
  169. # set to 1 to output debugging information
  170. 'debug': 1,
  171. # certificate
  172. 'key_file': path.join(BASEDIR, 'mycert.key'), # private part
  173. 'cert_file': path.join(BASEDIR, 'mycert.pem'), # public part
  174. # own metadata settings
  175. 'contact_person': [
  176. {'given_name': 'Lorenzo',
  177. 'sur_name': 'Gil',
  178. 'company': 'Yaco Sistemas',
  179. 'email_address': 'lgs@yaco.es',
  180. 'contact_type': 'technical'},
  181. {'given_name': 'Angel',
  182. 'sur_name': 'Fernandez',
  183. 'company': 'Yaco Sistemas',
  184. 'email_address': 'angel@yaco.es',
  185. 'contact_type': 'administrative'},
  186. ],
  187. # you can set multilanguage information here
  188. 'organization': {
  189. 'name': [('Yaco Sistemas', 'es'), ('Yaco Systems', 'en')],
  190. 'display_name': [('Yaco', 'es'), ('Yaco', 'en')],
  191. 'url': [('http://www.yaco.es', 'es'), ('http://www.yaco.com', 'en')],
  192. },
  193. 'valid_for': 24, # how long is our metadata valid
  194. }
  195. .. note::
  196. Please check the `PySAML2 documentation`_ for more information about
  197. these and other configuration options.
  198. .. _`PySAML2 documentation`: http://packages.python.org/pysaml2/
  199. There are several external files and directories you have to create according
  200. to this configuration.
  201. The xmlsec1 binary was mentioned in the installation section. Here, in the
  202. configuration part you just need to put the full path to xmlsec1 so PySAML2
  203. can call it as it needs.
  204. The ``attribute_map_dir`` points to a directory with attribute mappings that
  205. are used to translate user attribute names from several standards. It's usually
  206. safe to just copy the default PySAML2 attribute maps that you can find in the
  207. ``tests/attributemaps`` directory of the source distribution.
  208. The ``metadata`` option is a dictionary where you can define several types of
  209. metadata for remote entities. Usually the easiest type is the ``local`` where
  210. you just put the name of a local XML file with the contents of the remote
  211. entities metadata. This XML file should be in the SAML2 metadata format.
  212. The ``key_file`` and ``cert_file`` options references the two parts of a
  213. standard x509 certificate. You need it to sign your metadata an to encrypt
  214. and decrypt the SAML2 assertions.
  215. .. note::
  216. Check your openssl documentation to generate a test certificate but don't
  217. forget to order a real one when you go into production.
  218. Custom and dynamic configuration loading
  219. ........................................
  220. By default, djangosaml2 reads the pysaml2 configuration options from the
  221. SAML_CONFIG setting but sometimes you want to read this information from
  222. another place, like a file or a database. Sometimes you even want this
  223. configuration to be different depending on the request.
  224. Starting from djangosaml2 0.5.0 you can define your own configuration
  225. loader which is a callable that accepts a request parameter and returns
  226. a saml2.config.SPConfig object. In order to do so you set the following
  227. setting::
  228. SAML_CONFIG_LOADER = 'python.path.to.your.callable'
  229. User attributes
  230. ---------------
  231. In the SAML 2.0 authentication process the Identity Provider (IdP) will
  232. send a security assertion to the Service Provider (SP) upon a succesful
  233. authentication. This assertion contains attributes about the user that
  234. was authenticated. It depends on the IdP configuration what exact
  235. attributes are sent to each SP it can talk to.
  236. When such assertion is received on the Django side it is used to find
  237. a Django user and create a session for it. By default djangosaml2 will
  238. do a query on the User model with the 'username' attribute but you can
  239. change it to any other attribute of the User model. For example,
  240. you can do this look up using the 'email' attribute. In order to do so
  241. you should set the following setting::
  242. SAML_DJANGO_USER_MAIN_ATTRIBUTE = 'email'
  243. Please, use an unique attribute when setting this option. Otherwise
  244. the authentication process will fail because djangosaml2 does not know
  245. which Django user it should pick.
  246. Another option is to use the SAML2 name id as the username by setting::
  247. SAML_USE_NAME_ID_AS_USERNAME = True
  248. You can configure djangosaml2 to create such user if it is not already in
  249. the Django database or maybe you don't want to allow users that are not
  250. in your database already. For this purpose there is another option you
  251. can set in the settings.py file::
  252. SAML_CREATE_UNKNOWN_USER = True
  253. This setting is True by default.
  254. The other thing you will probably want to configure is the mapping of
  255. SAML2 user attributes to Django user attributes. By default only the
  256. User.username attribute is mapped but you can add more attributes or
  257. change that one. In order to do so you need to change the
  258. SAML_ATTRIBUTE_MAPPING option in your settings.py::
  259. SAML_ATTRIBUTE_MAPPING = {
  260. 'uid': ('username', ),
  261. 'mail': ('email', ),
  262. 'cn': ('first_name', ),
  263. 'sn': ('last_name', ),
  264. }
  265. where the keys of this dictionary are SAML user attributes and the values
  266. are Django User attributes.
  267. If you are using Django user profile objects to store extra attributes
  268. about your user you can add those attributes to the SAML_ATTRIBUTE_MAPPING
  269. dictionary. For each (key, value) pair, djangosaml2 will try to store the
  270. attribute in the User model if there is a matching field in that model.
  271. Otherwise it will try to do the same with your profile custom model.
  272. Learn more about Django profile models at:
  273. https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
  274. Sometimes you need to use special logic to update the user object
  275. depending on the SAML2 attributes and the mapping described above
  276. is simply not enough. For these cases djangosaml2 provides a Django
  277. signal that you can listen to. In order to do so you can add the
  278. following code to your app::
  279. from djangosaml2.signals import pre_user_save
  280. def custom_update_user(sender=user, attributes=attributes, user_modified=user_modified)
  281. ...
  282. return True # I modified the user object
  283. Your handler will receive the user object, the list of SAML attributes
  284. and a flag telling you if the user is already modified and need
  285. to be saved after your handler is executed. If your handler
  286. modifies the user object it should return True. Otherwise it should
  287. return False. This way djangosaml2 will know if it should save
  288. the user object so you don't need to do it and no more calls to
  289. the save method are issued.
  290. IdP setup
  291. =========
  292. Congratulations, you have finished configuring the SP side of the federation.
  293. Now you need to send the entity id and the metadata of this new SP to the
  294. IdP administrators so they can add it to their list of trusted services.
  295. You can get this information starting your Django development server and
  296. going to the http://localhost:8000/saml2/metadata url. If you have included
  297. the djangosaml2 urls under a different url prefix you need to correct this
  298. url.
  299. SimpleSAMLphp issues
  300. --------------------
  301. As of SimpleSAMLphp 1.8.2 there is a problem if you specify attributes in
  302. the SP configuration. When the SimpleSAMLphp metadata parser converts the
  303. XML into its custom php format it puts the following option::
  304. 'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'
  305. But it need to be replaced by this one::
  306. 'AttributeNameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'
  307. Otherwise the Assertions sent from the IdP to the SP will have a wrong
  308. Attribute Name Format and pysaml2 will be confused.
  309. Furthermore if you have a AttributeLimit filter in your SimpleSAMLphp
  310. configuration you will need to enable another attribute filter just
  311. before to make sure that the AttributeLimit does not remove the attributes
  312. from the authentication source. The filter you need to add is an AttributeMap
  313. filter like this::
  314. 10 => array(
  315. 'class' => 'core:AttributeMap', 'name2oid'
  316. ),
  317. Testing
  318. =======
  319. One way to check if everything is working as expected is to enable the
  320. following url::
  321. urlpatterns = patterns(
  322. '',
  323. # lots of url definitions here
  324. (r'^saml2/', include('djangosaml2.urls')),
  325. (r'^test/', 'djangosaml2.views.echo_attributes'),
  326. # more url definitions
  327. )
  328. Now if you go to the /test/ url you will see your SAML attributes and also
  329. a link to do a global logout.
  330. You can also run the unit tests with the following command::
  331. python tests/run_tests.py
  332. If you have `tox`_ installed you can simply call tox inside the root directory
  333. and it will run the tests in multiple versions of Python.
  334. .. _`tox`: http://pypi.python.org/pypi/tox
  335. FAQ
  336. ===
  337. **Why can't SAML be implemented as an Django Authentication Backend?**
  338. well SAML authentication is not that simple as a set of credentials you can
  339. put on a login form and get a response back. Actually the user password is
  340. not given to the service provider at all. This is by design. You have to
  341. delegate the task of authentication to the IdP and then get an asynchronous
  342. response from it.
  343. Given said that, djangosaml2 does use a Django Authentication Backend to
  344. transform the SAML assertion about the user into a Django user object.
  345. **Why not put everything in a Django middleware class and make our lifes
  346. easier?**
  347. Yes, that was an option I did evaluate but at the end the current design
  348. won. In my opinion putting this logic into a middleware has the advantage
  349. of making it easier to configure but has a couple of disadvantages: first,
  350. the middleware would need to check if the request path is one of the
  351. SAML endpoints for every request. Second, it would be too magical and in
  352. case of a problem, much harder to debug.
  353. **Why not call this package django-saml as many other Django applications?**
  354. Following that pattern then I should import the application with
  355. import saml but unfortunately that module name is already used in pysaml2.
  356. Changes
  357. =======
  358. 0.13.0 (2015-02-12)
  359. -------------------
  360. - Django 1.7 support. Thanks to Kamei Toshimitsu
  361. 0.12.0 (2014-11-18)
  362. -------------------
  363. - Pysaml2 2.2.0 support. Thanks to Erick Tryzelaar
  364. 0.11.0 (2014-06-15)
  365. -------------------
  366. - Django 1.5 custom user model support. Thanks to Jos van Velzen
  367. - Django 1.5 compatibility url template tag. Thanks to bula
  368. - Support Django 1.5 and 1.6. Thanks to David Evans and Justin Quick
  369. 0.10.0 (2013-05-05)
  370. -------------------
  371. - Check that RelayState is not empty before redirecting into a loop. Thanks
  372. to Sam Bull for reporting this issue.
  373. - In the global logout process, when the session is lost, report an error
  374. message to the user and perform a local logout.
  375. 0.9.2 (2013-04-19)
  376. ------------------
  377. - Upgrade to pysaml2-0.4.3.
  378. 0.9.1 (2013-01-29)
  379. ------------------
  380. - Add a method to the authentication backend so it is possible
  381. to customize the authorization based on SAML attributes.
  382. 0.9.0 (2012-10-30)
  383. ------------------
  384. - Add a signal for modifying the user just before saving it on
  385. the update_user method of the authentication backend.
  386. 0.8.1 (2012-10-29)
  387. ------------------
  388. - Trim the SAML attributes before setting them to the Django objects
  389. if they are too long. This fixes a crash with MySQL.
  390. 0.8.0 (2012-10-25)
  391. ------------------
  392. - Allow to use different attributes besides 'username' to look for
  393. existing users.
  394. 0.7.0 (2012-10-19)
  395. ------------------
  396. - Add a setting to decide if the user should be redirected to the
  397. next view or shown an authorization error when the user tries to
  398. login twice.
  399. 0.6.1 (2012-09-03)
  400. ------------------
  401. - Remove Django from our dependencies
  402. - Restore support for Django 1.3
  403. 0.6.0 (2012-08-29)
  404. ------------------
  405. - Add tox support configured to run the tests with Python 2.6 and 2.7
  406. - Fix some dependencies and sdist generation. Lorenzo Gil
  407. - Allow defining a logout redirect url in the settings. Lorenzo Gil
  408. - Add some logging calls to improve debugging. Lorenzo Gil
  409. - Add support for custom conf loading function. Sam Bull.
  410. - Make the tests more robust and easier to run when djangosaml2 is
  411. included in a Django project. Sam Bull.
  412. - Make sure the profile is not None before saving it. Bug reported by
  413. Leif Johansson
  414. 0.5.0 (2012-05-22)
  415. ------------------
  416. - Allow defining custom config loaders. They can be dynamic depending on
  417. the request.
  418. - Do not automatically add the authentication backend. This way
  419. we allow other people to add their own backends.
  420. - Support for additional attributes other than the ones that get mapped
  421. into the User model. Those attributes get stored in the UserProfile model.
  422. 0.4.2 (2012-03-23)
  423. ------------------
  424. - Fix a crash in the idplist templatetag about using an old pysaml2 function
  425. - Added a test for the previous crash
  426. 0.4.1 (2012-03-19)
  427. ------------------
  428. - Upgrade pysaml2 dependency to version 0.4.1
  429. 0.4.0 (2012-03-18)
  430. ------------------
  431. - Upgrade pysaml2 dependency to version 0.4.0 (update our tests as a result
  432. of this)
  433. - Add logging calls to make debugging easier
  434. - Use the Django configured logger in pysaml2
  435. 0.3.3 (2012-02-14)
  436. ------------------
  437. - Freeze the version of pysaml2 since we are not (yet!) compatible with
  438. version 0.4.0
  439. 0.3.2 (2011-12-13)
  440. ------------------
  441. - Avoid a crash when reading the SAML attribute that maps to the Django
  442. username
  443. 0.3.1 (2011-12-01)
  444. ------------------
  445. - Load the config in the render method of the idplist templatetag to
  446. make it more flexible and reentrant.
  447. 0.3.0 (2011-11-30)
  448. ------------------
  449. - Templatetag to get the list of available idps.
  450. - Allow to map the same SAML attribute into several Django field.
  451. 0.2.4 (2011-11-29)
  452. ------------------
  453. - Fix restructured text bugs that made pypi page looks bad.
  454. 0.2.3 (2011-06-14)
  455. ------------------
  456. - Set a unusable password when the user is created for the first time
  457. 0.2.2 (2011-06-07)
  458. ------------------
  459. - Prevent infinite loop when going to the /saml2/login/ endpoint and the user
  460. is already logged in and the settings.LOGIN_REDIRECT_URL is (badly) pointing
  461. to /saml2/login.
  462. 0.2.1 (2011-05-09)
  463. ------------------
  464. - If no next parameter is supplied to the login view, use the
  465. settings.LOGIN_REDIRECT_URL as default
  466. 0.2.0 (2011-04-26)
  467. ------------------
  468. - Python 2.4 compatible if the elementtree library is installed
  469. - Allow post processing after the authentication phase by using
  470. Django signals.
  471. 0.1.1 (2011-04-18)
  472. ------------------
  473. - Simple view to echo SAML attributes
  474. - Improve documentation
  475. - Change default behaviour when a new user is created. Now their attributes
  476. are filled this first time
  477. - Allow to set a next page after the logout
  478. 0.1.0 (2011-03-16)
  479. ------------------
  480. - Emancipation from the pysaml package
  481. Keywords: django,pysaml2,saml2,federated authentication,authentication
  482. Platform: UNKNOWN
  483. Classifier: Development Status :: 3 - Alpha
  484. Classifier: Environment :: Web Environment
  485. Classifier: Intended Audience :: Developers
  486. Classifier: Operating System :: OS Independent
  487. Classifier: Programming Language :: Python
  488. Classifier: Topic :: Internet :: WWW/HTTP
  489. Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
  490. Classifier: Topic :: Security
  491. Classifier: Topic :: Software Development :: Libraries :: Application Frameworks