=================
django-simple-sso
=================
|pypi| |build| |coverage|
Documentation
=============
See ``REQUIREMENTS`` in the `setup.py <https://github.com/divio/django-simple-sso/blob/master/setup.py>`_
file for additional dependencies:
|python| |django|
Django Simple SSO Specification (DRAFT)
=======================================
Terminology
***********
Server
------
The server is a Django website that holds all the user information and
authenticates users.
Client
------
The client is a Django website that provides login via SSO using the **Server**.
It does not hold any user information.
Key
---
A unique key identifying a **Client**. This key can be made public.
Secret
------
A secret key shared between the **Server** and a single **Client**. This secret
should never be shared with anyone other than the **Server** and **Client** and
must not be transferred unencrypted.
Workflow
********
* User wants to log into a **Client** by clicking a "Login" button. The
initially requested URL can be passed using the ``next`` GET parameter.
* The **Client**'s Python code does a HTTP request to the **Server** to request a
authentication token, this is called the **Request Token Request**.
* The **Server** returns a **Request Token**.
* The **Client** redirects the User to a view on the **Server** using the
**Request Token**, this is the **Authorization Request**.
* If the user is not logged in the the **Server**, they are prompted to log in.
* The user is redirected to the **Client** including the **Request Token** and a
**Auth Token**, this is the ``Authentication Request``.
* The **Client**'s Python code does a HTTP request to the **Server** to verify the
**Auth Token**, this is called the **Auth Token Verification Request**.
* If the **Auth Token** is valid, the **Server** returns a serialized Django User
object.
* The **Client** logs the user in using the Django User recieved from the **Server**.
Requests
********
General
-------
All requests have a ``signature`` and ``key`` parameter, see **Security**.
Request Token Request
---------------------
* Client: Python
* Target: **Server**
* Method: GET
* Extra Parameters: None
* Responses:
* ``200``: Everything went fine, the body of the response is a url encoded
query string containing with the ``request_token`` key holding the
**Request Token** as well as the ``signature``.
* ``400``: Bad request (missing GET parameters)
* ``403``: Forbidden (invalid signature)
Authorization Request
---------------------
* Client: Browser (User)
* Target: **Server**
* Method: GET
* Extra Parameters:
* ``request_token``
* Responses:
* ``200``: Everything okay, prompt user to log in or continue.
* ``400``: Bad request (missing GET parameter).
* ``403``: Forbidden (invalid **Request Token**).
Authentication Request
----------------------
* Client: Browser (User)
* Target: **Client**
* Method: GET
* Extra Parameters:
* ``request_token``: The **Request Token** returned by the
**Request Token Request**.
* ``auth_token``: The **Auth Token** generated by the **Authorization Request**.
* Responses:
* ``200``: Everything went fine, the user is now logged in.
* ``400``: Bad request (missing GET parameters).
* ``403``: Forbidden (invalid **Request Token**).
Auth Token Verification Request
-------------------------------
* Client: Python
* Target: **Server**
* Method: GET
* Extra Parameters:
* ``auth_token``: The **Auth Token** obtained by the **Authentication Request**.
* Responses:
* ``200``: Everything went fine, the body of the response is a url encoded
query string containing the ``user`` key which is the JSON serialized
representation of the Django user to create as well as the ``signature``.
Security
********
Every request is signed using HMAC-SHA256. The signature is in the ``signature``
parameter. The signature message is the urlencoded, alphabetically ordered
query string. The signature key is the **Secret** of the **Client**. To verify
the signature the ``key`` paramater holding the **key** of the **Client** is
also sent with every request from the **Client** to the **Server**.
Example
-------
GET Request with the GET parameters ``key=bundle123`` and the private key
``secret key``: ``fbf6396d0fc40d563e2be3c861f7eb5a1b821b76c2ac943d40a7a63b288619a9``
The User object
***************
The User object returned by a successful **Auth Token Verification Request**
does not contain all the information about the Django User, in particular, it
does not contain the password.
The user object contains must contain at least the following data:
* ``username``: The unique username of this user.
* ``email``: The email of this user.
* ``first_name``: The first name of this user, this field is required, but may
be empty.
* ``last_name``: The last name of this user, this field is required, but may
be empty.
* ``is_staff``: Can this user access the Django admin on the **Client**?
* ``is_superuser``: Does this user have superuser access to the **Client**?
* ``is_active``: Is the user active?
Implementation
**************
On the server
-------------
* Add ``simple_sso.sso_server`` to ``INSTALLED_APPS``.
* Create an instance (potentially of a subclass) of
``simple_sso.sso_server.server.Server`` and include the return value of the
``get_urls`` method on that instance into your url patterns.
On the client
-------------
* Create a new instance of ``simple_sso.sso_server.models.Consumer`` on the
**Server**.
* Add the ``SIMPLE_SSO_SECRET`` and ``SIMPLE_SSO_KEY`` settings as provided by
the **Server**'s ``simple_sso.sso_server.models.Client`` model.
* Add the ``SIMPLE_SSO_SERVER`` setting which is the absolute URL pointing to
the root where the ``simple_sso.sso_server.urls`` where include on the
**Server**.
* Add the ``simple_sso.sso_client.urls`` patterns somewhere on the client.
Running Tests
*************
You can run tests by executing::
virtualenv env
source env/bin/activate
pip install -r tests/requirements.txt
python setup.py test
.. |pypi| image:: https://badge.fury.io/py/django-simple.sso.svg
:target: http://badge.fury.io/py/django-simple.sso
.. |build| image:: https://travis-ci.org/divio/django-simple.sso.svg?branch=master
:target: https://travis-ci.org/divio/django-simple.sso
.. |coverage| image:: https://codecov.io/gh/divio/django-simple.sso/branch/master/graph/badge.svg
:target: https://codecov.io/gh/divio/django-simple.sso
.. |python| image:: https://img.shields.io/badge/python-3.5+-blue.svg
:target: https://pypi.org/project/django-simple.sso/
.. |django| image:: https://img.shields.io/badge/django-2.2,%203.0,%203.1-blue.svg
:target: https://www.djangoproject.com/
Raw data
{
"_id": null,
"home_page": "http://github.com/aldryn/django-simple-sso",
"name": "django-simple-sso",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "",
"author": "Divio AG",
"author_email": "info@divio.com",
"download_url": "https://files.pythonhosted.org/packages/ca/d0/d7286c46635cec3f8058b9c2d5099bcf90d990a6516cf73b09752b153d7d/django-simple-sso-1.2.0.tar.gz",
"platform": null,
"description": "=================\ndjango-simple-sso\n=================\n\n|pypi| |build| |coverage|\n\n\nDocumentation\n=============\n\nSee ``REQUIREMENTS`` in the `setup.py <https://github.com/divio/django-simple-sso/blob/master/setup.py>`_\nfile for additional dependencies:\n\n|python| |django|\n\n\nDjango Simple SSO Specification (DRAFT)\n=======================================\n\nTerminology\n***********\n\nServer\n------\n\nThe server is a Django website that holds all the user information and\nauthenticates users.\n\nClient\n------\n\nThe client is a Django website that provides login via SSO using the **Server**.\nIt does not hold any user information.\n\nKey\n---\n\nA unique key identifying a **Client**. This key can be made public.\n\nSecret\n------\n\nA secret key shared between the **Server** and a single **Client**. This secret\nshould never be shared with anyone other than the **Server** and **Client** and\nmust not be transferred unencrypted.\n\nWorkflow\n********\n\n* User wants to log into a **Client** by clicking a \"Login\" button. The\n initially requested URL can be passed using the ``next`` GET parameter.\n* The **Client**'s Python code does a HTTP request to the **Server** to request a\n authentication token, this is called the **Request Token Request**.\n* The **Server** returns a **Request Token**.\n* The **Client** redirects the User to a view on the **Server** using the\n **Request Token**, this is the **Authorization Request**.\n* If the user is not logged in the the **Server**, they are prompted to log in.\n* The user is redirected to the **Client** including the **Request Token** and a\n **Auth Token**, this is the ``Authentication Request``.\n* The **Client**'s Python code does a HTTP request to the **Server** to verify the\n **Auth Token**, this is called the **Auth Token Verification Request**.\n* If the **Auth Token** is valid, the **Server** returns a serialized Django User\n object.\n* The **Client** logs the user in using the Django User recieved from the **Server**.\n\nRequests\n********\n\nGeneral\n-------\n\nAll requests have a ``signature`` and ``key`` parameter, see **Security**.\n\nRequest Token Request\n---------------------\n\n* Client: Python\n* Target: **Server**\n* Method: GET\n* Extra Parameters: None\n* Responses:\n\n * ``200``: Everything went fine, the body of the response is a url encoded\n query string containing with the ``request_token`` key holding the\n **Request Token** as well as the ``signature``.\n * ``400``: Bad request (missing GET parameters)\n * ``403``: Forbidden (invalid signature)\n\n\nAuthorization Request\n---------------------\n\n* Client: Browser (User)\n* Target: **Server**\n* Method: GET\n* Extra Parameters:\n\n * ``request_token``\n\n* Responses:\n\n * ``200``: Everything okay, prompt user to log in or continue.\n * ``400``: Bad request (missing GET parameter).\n * ``403``: Forbidden (invalid **Request Token**).\n\n\nAuthentication Request\n----------------------\n\n* Client: Browser (User)\n* Target: **Client**\n* Method: GET\n* Extra Parameters:\n\n * ``request_token``: The **Request Token** returned by the\n **Request Token Request**.\n * ``auth_token``: The **Auth Token** generated by the **Authorization Request**.\n\n* Responses:\n\n * ``200``: Everything went fine, the user is now logged in.\n * ``400``: Bad request (missing GET parameters).\n * ``403``: Forbidden (invalid **Request Token**).\n\n\nAuth Token Verification Request\n-------------------------------\n\n* Client: Python\n* Target: **Server**\n* Method: GET\n* Extra Parameters:\n\n * ``auth_token``: The **Auth Token** obtained by the **Authentication Request**.\n\n* Responses:\n\n * ``200``: Everything went fine, the body of the response is a url encoded\n query string containing the ``user`` key which is the JSON serialized\n representation of the Django user to create as well as the ``signature``.\n\nSecurity\n********\n\nEvery request is signed using HMAC-SHA256. The signature is in the ``signature``\nparameter. The signature message is the urlencoded, alphabetically ordered\nquery string. The signature key is the **Secret** of the **Client**. To verify\nthe signature the ``key`` paramater holding the **key** of the **Client** is\nalso sent with every request from the **Client** to the **Server**.\n\nExample\n-------\n\nGET Request with the GET parameters ``key=bundle123`` and the private key\n``secret key``: ``fbf6396d0fc40d563e2be3c861f7eb5a1b821b76c2ac943d40a7a63b288619a9``\n\nThe User object\n***************\n\nThe User object returned by a successful **Auth Token Verification Request**\ndoes not contain all the information about the Django User, in particular, it\ndoes not contain the password.\n\nThe user object contains must contain at least the following data:\n\n* ``username``: The unique username of this user.\n* ``email``: The email of this user.\n* ``first_name``: The first name of this user, this field is required, but may\n be empty.\n* ``last_name``: The last name of this user, this field is required, but may\n be empty.\n* ``is_staff``: Can this user access the Django admin on the **Client**?\n* ``is_superuser``: Does this user have superuser access to the **Client**?\n* ``is_active``: Is the user active?\n\nImplementation\n**************\n\nOn the server\n-------------\n\n* Add ``simple_sso.sso_server`` to ``INSTALLED_APPS``.\n* Create an instance (potentially of a subclass) of\n ``simple_sso.sso_server.server.Server`` and include the return value of the\n ``get_urls`` method on that instance into your url patterns.\n\n\nOn the client\n-------------\n\n* Create a new instance of ``simple_sso.sso_server.models.Consumer`` on the\n **Server**.\n* Add the ``SIMPLE_SSO_SECRET`` and ``SIMPLE_SSO_KEY`` settings as provided by\n the **Server**'s ``simple_sso.sso_server.models.Client`` model.\n* Add the ``SIMPLE_SSO_SERVER`` setting which is the absolute URL pointing to\n the root where the ``simple_sso.sso_server.urls`` where include on the\n **Server**.\n* Add the ``simple_sso.sso_client.urls`` patterns somewhere on the client.\n\n\nRunning Tests\n*************\n\nYou can run tests by executing::\n\n virtualenv env\n source env/bin/activate\n pip install -r tests/requirements.txt\n python setup.py test\n\n\n.. |pypi| image:: https://badge.fury.io/py/django-simple.sso.svg\n :target: http://badge.fury.io/py/django-simple.sso\n.. |build| image:: https://travis-ci.org/divio/django-simple.sso.svg?branch=master\n :target: https://travis-ci.org/divio/django-simple.sso\n.. |coverage| image:: https://codecov.io/gh/divio/django-simple.sso/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/divio/django-simple.sso\n\n.. |python| image:: https://img.shields.io/badge/python-3.5+-blue.svg\n :target: https://pypi.org/project/django-simple.sso/\n.. |django| image:: https://img.shields.io/badge/django-2.2,%203.0,%203.1-blue.svg\n :target: https://www.djangoproject.com/\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "Simple SSO for Django",
"version": "1.2.0",
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "84ae467edc636323f76cdaeca2f47ea6",
"sha256": "6691ebf8573932488c58cc8fcf0befd2bd67dec915e0b93bce8c8914cac0b291"
},
"downloads": -1,
"filename": "django_simple_sso-1.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "84ae467edc636323f76cdaeca2f47ea6",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 17434,
"upload_time": "2022-12-14T14:53:46",
"upload_time_iso_8601": "2022-12-14T14:53:46.637161Z",
"url": "https://files.pythonhosted.org/packages/66/16/5f17bc534d7efc0f94b6ae319dd2a50c8913f9064ea7349b62ffdb2948e8/django_simple_sso-1.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "0d91cfe18e4dab6512a6d0549247e4d2",
"sha256": "b91820a4ebfa088ed53d074179f406cb8dd9b54d0602641c29ee8f597b5baf52"
},
"downloads": -1,
"filename": "django-simple-sso-1.2.0.tar.gz",
"has_sig": false,
"md5_digest": "0d91cfe18e4dab6512a6d0549247e4d2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 14909,
"upload_time": "2022-12-14T14:53:48",
"upload_time_iso_8601": "2022-12-14T14:53:48.209565Z",
"url": "https://files.pythonhosted.org/packages/ca/d0/d7286c46635cec3f8058b9c2d5099bcf90d990a6516cf73b09752b153d7d/django-simple-sso-1.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-12-14 14:53:48",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "aldryn",
"github_project": "django-simple-sso",
"travis_ci": false,
"coveralls": true,
"github_actions": false,
"tox": true,
"lcname": "django-simple-sso"
}