django-oidc-provider/doc.md

227 lines
6.4 KiB
Markdown
Raw Normal View History

2015-02-26 19:44:31 +00:00
# Welcome to the Docs!
Django OIDC Provider can help you providing out of the box all the endpoints, data and logic needed to add OpenID Connect capabilities to your Django projects.
**This project is still in DEVELOPMENT and is rapidly changing. DO NOT USE IT FOR PRODUCTION SITES, unless you know what you do.**
Before getting started there are some important things that you should know:
* Although OpenID was built on top of OAuth2, this isn't an OAuth2 server. Maybe in a future it will be.
* Despite that implementation MUST support TLS. You can make request without using SSL. There is no control on that.
* This cover authorization_code flow and implicit flow, NO support for hybrid flow at this moment.
* Only support for requesting Claims using Scope Values.
# Table Of Contents
2015-02-27 17:24:43 +00:00
- [Requirements](#requirements)
2015-02-26 19:44:31 +00:00
- [Installation](#installation)
- [Settings](#settings)
2015-02-27 21:14:46 +00:00
- [SITE_URL](#site_url)
- [LOGIN_URL](#login_url)
- [OIDC_CODE_EXPIRE](#oidc_code_expire)
2015-02-27 21:17:20 +00:00
- [OIDC_EXTRA_SCOPE_CLAIMS](#oidc_extra_scope_claims)
- [OIDC_IDTOKEN_EXPIRE](#oidc_idtoken_expire)
- [OIDC_TOKEN_EXPIRE](#oidc_token_expire)
2015-02-26 19:44:31 +00:00
- [Users And Clients](#users-and-clients)
- [Templates](#templates)
- [Server Endpoints](#server-endpoints)
2015-02-27 17:24:43 +00:00
## Requirements
- Python 2.7.*.
- Django 1.7.*.
2015-02-26 19:44:31 +00:00
## Installation
Install the package using pip.
```bash
pip install django-oidc-provider
# Or latest code from repo.
2015-02-27 17:21:45 +00:00
pip install git+https://github.com/juanifioren/django-oidc-provider.git#egg=oidc_provider
2015-02-26 19:44:31 +00:00
```
Add it to your apps.
```python
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
2015-02-27 17:21:45 +00:00
'oidc_provider',
2015-02-26 19:44:31 +00:00
# ...
)
```
Add the provider urls.
```python
urlpatterns = patterns('',
# ...
2015-02-27 17:21:45 +00:00
url(r'^openid/', include('oidc_provider.urls', namespace='oidc_provider')),
2015-02-26 19:44:31 +00:00
# ...
)
```
## Settings
Add required variables to your project settings.
2015-02-27 21:23:06 +00:00
##### SITE_URL
2015-02-27 21:14:46 +00:00
*REQUIRED.* The OP server url. For example `http://localhost:8000`.
2015-02-27 21:23:06 +00:00
##### LOGIN_URL
*REQUIRED.* Used to log the user in. [Read more in Django docs](https://docs.djangoproject.com/en/1.7/ref/settings/#login-url). Default is `/accounts/login/`.
2015-02-27 21:14:46 +00:00
2015-02-27 21:23:06 +00:00
##### OIDC_CODE_EXPIRE
*OPTIONAL.* Expressed in seconds. Default is `60*10`.
2015-02-27 21:14:46 +00:00
2015-02-27 21:23:06 +00:00
##### OIDC_EXTRA_SCOPE_CLAIMS
2015-02-27 21:14:46 +00:00
*OPTIONAL.* Used to add extra scopes specific for your app. This class MUST inherit ``AbstractScopeClaims``.
OpenID Connect Clients will use scope values to specify what access privileges are being requested for Access Tokens.
[Here](http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims) you have the standard scopes defined by the protocol.
Check out an example:
2015-02-26 19:44:31 +00:00
```python
2015-02-27 21:14:46 +00:00
from oidc_provider.lib.claims import AbstractScopeClaims
2015-02-26 19:44:31 +00:00
2015-02-27 21:14:46 +00:00
class MyAppScopeClaims(AbstractScopeClaims):
2015-02-26 19:44:31 +00:00
2015-02-27 21:14:46 +00:00
def __init__(self, user, scopes):
# Don't forget this.
super(StandardScopeClaims, self).__init__(user, scopes)
2015-02-26 19:44:31 +00:00
2015-02-27 21:14:46 +00:00
# Here you can load models that will be used
# in more than one scope for example.
try:
self.some_model = SomeModel.objects.get(user=self.user)
except UserInfo.DoesNotExist:
# Create an empty model object.
self.some_model = SomeModel()
2015-02-26 19:44:31 +00:00
2015-02-27 21:14:46 +00:00
def scope_books(self, user):
# Here you can search books for this user.
dic = {
'books_readed': books_readed_count,
}
return dic
2015-02-26 19:44:31 +00:00
```
2015-02-27 21:14:46 +00:00
See how we create our own scopes using the convention:
``def scope_<SCOPE_NAME>(self, user):``
If a field is empty or ``None`` will be cleaned from the response.
2015-02-27 21:23:06 +00:00
##### OIDC_IDTOKEN_EXPIRE
*OPTIONAL.* Expressed in seconds. Default is `60*10`.
2015-02-27 21:14:46 +00:00
2015-02-27 21:23:06 +00:00
##### OIDC_TOKEN_EXPIRE
*OPTIONAL.* Token object expiration after been created. Expressed in seconds. Default is `60*60`.
2015-02-27 21:14:46 +00:00
2015-02-26 19:44:31 +00:00
## Users And Clients
User and client creation it's up to you. This is because is out of the scope in the core implementation of OIDC.
So, there are different ways to create your Clients. By displaying a HTML form or maybe if you have internal thrusted Clients you can create them programatically.
[Read more about client creation](http://tools.ietf.org/html/rfc6749#section-2).
For your users, the tipical situation is that you provide them a login and a registration page.
If you want to test the provider without getting to deep into this topics you can:
Create a user with: ``python manage.py createsuperuser``.
And then create a Client with django shell: ``python manage.py shell``.
```python
>>> from oidc_provider.models import Client
>>> c = Client(name='Some Client', client_id='123', client_secret='456', response_type='code', redirect_uris=['http://example.com/'])
>>> c.save()
```
## Templates
Add your own templates files inside a folder named ``templates/oidc_provider/``.
You can copy the sample html here and edit them with your own styles.
**authorize.html**
```html
<h1>Request for Permission</h1>
<p>Client <strong>{{ client.name }}</strong> would like to access this information of you ...</p>
<form method="post" action="{% url 'oidc_provider:authorize' %}">
{% csrf_token %}
{{ hidden_inputs }}
<ul>
{% for scope in params.scope %}
<li>{{ scope | capfirst }}</li>
{% endfor %}
</ul>
<input name="allow" type="submit" value="Authorize" />
</form>
{% endblock %}
```
**error.html**
```html
<h3>{{ error }}</h3>
<p>{{ description }}</p>
```
## Server Endpoints
**/authorize endpoint**
Example of an OpenID Authentication Request using the ``Authorization Code`` flow.
```curl
GET /openid/authorize?client_id=123&redirect_uri=http%3A%2F%2Fexample.com%2F&response_type=code&scope=openid%20profile%20email&state=abcdefgh HTTP/1.1
Host: localhost:8000
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
```
After the user accepts and authorizes the client application, the server redirects to:
```curl
http://example.com/?code=5fb3b172913448acadce6b011af1e75e&state=abcdefgh
```
The ``code`` param will be use it to obtain access token.
**/token endpoint**
```curl
POST /openid/token/ HTTP/1.1
Host: localhost:8000
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
client_id=123&client_secret=456&redirect_uri=http%253A%252F%252Fexample.com%252F&grant_type=authorization_code&code=[CODE]&state=abcdefgh
```
**/userinfo endpoint**
```curl
POST /openid/userinfo/ HTTP/1.1
Host: localhost:8000
Authorization: Bearer [ACCESS_TOKEN]
```