django-sso-app


Namedjango-sso-app JSON
Version 0.8.5 PyPI version JSON
download
home_pagehttps://bitbucket.org/pai/django-sso-app
SummaryUser profile management app
upload_time2020-09-16 12:50:52
maintainer
docs_urlNone
authorpai
requires_python
licensemit
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-sso-app

User profile management app built upon [django-allauth](https://github.com/pennersr/django-allauth) library
and [cookiecutter-django](https://github.com/pydanny/cookiecutter-django) as scaffold.
Optionally integrates with [kong](https://github.com/Kong/kong) API gateway.

(This is alpha software and is under heavy development)

## Tech

- [python3](https://github.com/python)
- [django](https://github.com/django/django)
- [django-allauth](https://github.com/pennersr/django-allauth)
- [pyjwt](https://github.com/jpadilla/pyjwt)
- [kong](https://github.com/Kong/kong)


## Design decisions

- After login both JWT and Session Token will be sent to the requesting browser
- Single e-mail address for each user
- Django staff users (is_staff and is_superuser) must login through django admin view
- User logout on password change
- New users username is set to email
- While profile completed_at is None user can update username
- When apigateway is enabled, users with completed_at set to None are on "incomplete" group 
- User login on email confirmation 


### Available configurations (Shapes)

1) Backend only:

    Users profile informations are saved into django project with django-sso-app installed.

    ```
    DJANGO_SSO_APP_SHAPE = 'backend_only'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]
    ```

2) Backend + Api Gateway

    As point **1** but with an api gateway (i.e. kong) proxying authenticated requests to backend.
    By logging in the client receives a JWT crafted by backend with the api gateway generated secret.

    ```
    DJANGO_SSO_APP_SHAPE = 'backend_only_apigateway'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]
    DJANGO_SSO_APP_APIGATEWAY_HOST = 'kong'
    ```

3) Backend + App

    User profile informations are saved into a django-sso-app instance, all protected django projects have
    django-sso-app installed and configured to authenticate users by django-sso-app generated JWT.
    By logging in the client receives a JWT crafted by backend.

    ```
    # Backend config
    DJANGO_SSO_APP_SHAPE = 'backend_app'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ..]

    # App config
    DJANGO_SSO_APP_SHAPE = 'app'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]
    ```

4) Backend + App + Persistence

    As point **3** but protected projects keep user profiles aligned with django-sso-app instance.

    ```
    # Backend config
    DJANGO_SSO_APP_SHAPE = 'backend_app'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]

    # App config
    DJANGO_SSO_APP_SHAPE = 'app_persistence'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]
    ```

5) Backend + App + Api Gateway

    As point **3** but with an api gateway proxying authenticated requests to django projects.

    Protected projects authenticate users by the **X-Consumer-Username** header set by api gateway.
    By logging in the client receives a JWT crafted by backend with the api gateway generated secret.
    All requests to protected services are authenticated by the JWT included in cookie (or header).

    ```
    # Backend config
    DJANGO_SSO_APP_SHAPE = 'backend_app_apigateway'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]
    DJANGO_SSO_APP_APIGATEWAY_HOST = 'http://kong:8001'

    # App config
    DJANGO_SSO_APP_SHAPE = 'app_apigateway'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]
    ```

6) Backend + App + Persistence + Api Gateway

    As point **5** but protected projects keep user profiles aligned with django-sso-app instance.

    ```
    # Backend config
    DJANGO_SSO_APP_SHAPE = 'backend_app_apigateway'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]
    DJANGO_SSO_APP_APIGATEWAY_HOST = 'http://kong:8001'

    # App config
    DJANGO_SSO_APP_SHAPE = 'app_persistence_apigateway'
    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]
    ```


### Note 

Seamless switch between aforementioned configurations is mandatory in order to simplify scaling.


## Setup

### Config vars

#### Required

- APP_DOMAIN

  i.e. *accounts.example.com* (default='localhost:8000')

- DJANGO_SSO_APP_SHAPE

   One of *backend_only*, *backend_only_apigateway*, *backend_app*, *app*, *app_persistence*, *app_apigateway*,
   *app_persistence_apigateway* (default='backend_only').


#### Custom (Shape related)

- COOKIE_DOMAIN

  JWT cookie domain (default=APP_DOMAIN)


- I18N_PATH_ENABLED

  Enables i18n paths (default=True)


- DJANGO_SSO_APP_APIGATEWAY_HOST

  Api gateway instance url (default='http://kong:8001')


- DJANGO_SSO_APP_BACKEND_CUSTOM_FRONTEND_APP

  Custom frontend package (default=None)


- DJANGO_SSO_APP_BACKEND_DOMAINS

  List of backend domains (default=[APP_DOMAIN])


#### Behaviours

- DJANGO_SSO_APP_LOGOUT_DELETES_ALL_PROFILE_DEVICES 

  Either delete or not other profile devices on logout (default=True)


### Django

#### backend.users.models

```python
from django.contrib.auth.models import AbstractUser
from django_sso_app.core.apps.users.models import DjangoSsoAppUserModelMixin

class User(AbstractUser, DjangoSsoAppUserModelMixin):
    pass
```

#### backend.users.forms

```python
from django_sso_app.backend.users.forms import (UserCreationForm as DjangoSsoAppUserCreationForm,
                                                UserChangeForm as DjangoSsoAppUserChangeForm)

class UserChangeForm(DjangoSsoAppUserChangeForm):
    pass

class UserCreationForm(DjangoSsoAppUserCreationForm):
    pass
```

#### backend.users.admin

```python
from django.contrib import admin
from django.contrib.auth import get_user_model

from django_sso_app.core.apps.users.admin import UserAdmin

User = get_user_model()

admin.site.register(User, UserAdmin)
```

#### settings.py

```python

from django_sso_app.settings import *

DJANGO_SSO_APP_SHAPE = env('DJANGO_SSO_APP_SHAPE', default='backend_only')
DJANGO_SSO_APP_APIGATEWAY_HOST = env('DJANGO_SSO_APP_APIGATEWAY_HOST', default='kong')
BACKEND_CUSTOM_FRONTEND_APP = env('BACKEND_CUSTOM_FRONTEND_APP', default=None)

LOCAL_APPS = ["backend.users.apps.UsersConfig"]  # ...

LOCAL_APPS += DJANGO_SSO_APP_DJANGO_APPS

MIDDLEWARE = [
    ...
    'django_sso_app.core.authentication.backends.DjangoSsoAppLoginAuthenticationBackend',

    'django_sso_app.core.authentication.middleware.DjangoSsoAppAuthenticationMiddleware',
    ...
]

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
] + DJANGO_SSO_APP_DJANGO_AUTHENTICATION_BACKENDS


AUTH_USER_MODEL = 'users.User'
LOGIN_URL = '/login/'

DRF_DEFAULT_AUTHENTICATION_CLASSES = [
    'rest_framework.authentication.TokenAuthentication'
    'django_sso_app.core.api.authentication.DjangoSsoApiAuthentication'
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': DRF_DEFAULT_AUTHENTICATION_CLASSES,
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

```


#### urls.py
```python
urlpatterns = []
api_urlpatterns = []
_I18N_URLPATTERNS = []

from django_sso_app.urls import (urlpatterns as django_sso_app__urlpatterns,
                                 api_urlpatterns as django_sso_app__api_urlpatterns,
                                 i18n_urlpatterns as django_sso_app_i18n_urlpatterns)
from django_sso_app.core.mixins import WebpackBuiltTemplateViewMixin

urlpatterns += django_sso_app__urlpatterns
api_urlpatterns += django_sso_app__api_urlpatterns
_I18N_URLPATTERNS += django_sso_app_i18n_urlpatterns

urlpatterns += [
    url(r'^i18n/', include('django.conf.urls.i18n')),
    url(r'^jsi18n/$', ...
]

_I18N_URLPATTERNS += [
    path('', WebpackBuiltTemplateViewMixin.as_view(template_name='pages/home.html'), name='home'),
    path('about/', WebpackBuiltTemplateViewMixin.as_view(template_name='pages/about.html'), name='about'),

    # Django Admin, use {% url 'admin:index' %}
    path(settings.ADMIN_URL, admin.site.urls),
]

if settings.I18N_PATH_ENABLED:
    urlpatterns += i18n_patterns(
        *_I18N_URLPATTERNS
    )
else:
    urlpatterns += _I18N_URLPATTERNS

```



            

Raw data

            {
    "_id": null,
    "home_page": "https://bitbucket.org/pai/django-sso-app",
    "name": "django-sso-app",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "",
    "author": "pai",
    "author_email": "paiuolo@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/ae/22/78c77f0659ea1f1dff8bd9bf26934edc1d3cf1a6eefad02eb571e82233ef/django-sso-app-0.8.5.tar.gz",
    "platform": "any",
    "description": "# django-sso-app\n\nUser profile management app built upon [django-allauth](https://github.com/pennersr/django-allauth) library\nand [cookiecutter-django](https://github.com/pydanny/cookiecutter-django) as scaffold.\nOptionally integrates with [kong](https://github.com/Kong/kong) API gateway.\n\n(This is alpha software and is under heavy development)\n\n## Tech\n\n- [python3](https://github.com/python)\n- [django](https://github.com/django/django)\n- [django-allauth](https://github.com/pennersr/django-allauth)\n- [pyjwt](https://github.com/jpadilla/pyjwt)\n- [kong](https://github.com/Kong/kong)\n\n\n## Design decisions\n\n- After login both JWT and Session Token will be sent to the requesting browser\n- Single e-mail address for each user\n- Django staff users (is_staff and is_superuser) must login through django admin view\n- User logout on password change\n- New users username is set to email\n- While profile completed_at is None user can update username\n- When apigateway is enabled, users with completed_at set to None are on \"incomplete\" group \n- User login on email confirmation \n\n\n### Available configurations (Shapes)\n\n1) Backend only:\n\n    Users profile informations are saved into django project with django-sso-app installed.\n\n    ```\n    DJANGO_SSO_APP_SHAPE = 'backend_only'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n    ```\n\n2) Backend + Api Gateway\n\n    As point **1** but with an api gateway (i.e. kong) proxying authenticated requests to backend.\n    By logging in the client receives a JWT crafted by backend with the api gateway generated secret.\n\n    ```\n    DJANGO_SSO_APP_SHAPE = 'backend_only_apigateway'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n    DJANGO_SSO_APP_APIGATEWAY_HOST = 'kong'\n    ```\n\n3) Backend + App\n\n    User profile informations are saved into a django-sso-app instance, all protected django projects have\n    django-sso-app installed and configured to authenticate users by django-sso-app generated JWT.\n    By logging in the client receives a JWT crafted by backend.\n\n    ```\n    # Backend config\n    DJANGO_SSO_APP_SHAPE = 'backend_app'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ..]\n\n    # App config\n    DJANGO_SSO_APP_SHAPE = 'app'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n    ```\n\n4) Backend + App + Persistence\n\n    As point **3** but protected projects keep user profiles aligned with django-sso-app instance.\n\n    ```\n    # Backend config\n    DJANGO_SSO_APP_SHAPE = 'backend_app'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n\n    # App config\n    DJANGO_SSO_APP_SHAPE = 'app_persistence'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n    ```\n\n5) Backend + App + Api Gateway\n\n    As point **3** but with an api gateway proxying authenticated requests to django projects.\n\n    Protected projects authenticate users by the **X-Consumer-Username** header set by api gateway.\n    By logging in the client receives a JWT crafted by backend with the api gateway generated secret.\n    All requests to protected services are authenticated by the JWT included in cookie (or header).\n\n    ```\n    # Backend config\n    DJANGO_SSO_APP_SHAPE = 'backend_app_apigateway'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n    DJANGO_SSO_APP_APIGATEWAY_HOST = 'http://kong:8001'\n\n    # App config\n    DJANGO_SSO_APP_SHAPE = 'app_apigateway'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n    ```\n\n6) Backend + App + Persistence + Api Gateway\n\n    As point **5** but protected projects keep user profiles aligned with django-sso-app instance.\n\n    ```\n    # Backend config\n    DJANGO_SSO_APP_SHAPE = 'backend_app_apigateway'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n    DJANGO_SSO_APP_APIGATEWAY_HOST = 'http://kong:8001'\n\n    # App config\n    DJANGO_SSO_APP_SHAPE = 'app_persistence_apigateway'\n    DJANGO_SSO_APP_BACKEND_DOMAINS = ['1.accounts.domain', ...]\n    ```\n\n\n### Note \n\nSeamless switch between aforementioned configurations is mandatory in order to simplify scaling.\n\n\n## Setup\n\n### Config vars\n\n#### Required\n\n- APP_DOMAIN\n\n  i.e. *accounts.example.com* (default='localhost:8000')\n\n- DJANGO_SSO_APP_SHAPE\n\n   One of *backend_only*, *backend_only_apigateway*, *backend_app*, *app*, *app_persistence*, *app_apigateway*,\n   *app_persistence_apigateway* (default='backend_only').\n\n\n#### Custom (Shape related)\n\n- COOKIE_DOMAIN\n\n  JWT cookie domain (default=APP_DOMAIN)\n\n\n- I18N_PATH_ENABLED\n\n  Enables i18n paths (default=True)\n\n\n- DJANGO_SSO_APP_APIGATEWAY_HOST\n\n  Api gateway instance url (default='http://kong:8001')\n\n\n- DJANGO_SSO_APP_BACKEND_CUSTOM_FRONTEND_APP\n\n  Custom frontend package (default=None)\n\n\n- DJANGO_SSO_APP_BACKEND_DOMAINS\n\n  List of backend domains (default=[APP_DOMAIN])\n\n\n#### Behaviours\n\n- DJANGO_SSO_APP_LOGOUT_DELETES_ALL_PROFILE_DEVICES \n\n  Either delete or not other profile devices on logout (default=True)\n\n\n### Django\n\n#### backend.users.models\n\n```python\nfrom django.contrib.auth.models import AbstractUser\nfrom django_sso_app.core.apps.users.models import DjangoSsoAppUserModelMixin\n\nclass User(AbstractUser, DjangoSsoAppUserModelMixin):\n    pass\n```\n\n#### backend.users.forms\n\n```python\nfrom django_sso_app.backend.users.forms import (UserCreationForm as DjangoSsoAppUserCreationForm,\n                                                UserChangeForm as DjangoSsoAppUserChangeForm)\n\nclass UserChangeForm(DjangoSsoAppUserChangeForm):\n    pass\n\nclass UserCreationForm(DjangoSsoAppUserCreationForm):\n    pass\n```\n\n#### backend.users.admin\n\n```python\nfrom django.contrib import admin\nfrom django.contrib.auth import get_user_model\n\nfrom django_sso_app.core.apps.users.admin import UserAdmin\n\nUser = get_user_model()\n\nadmin.site.register(User, UserAdmin)\n```\n\n#### settings.py\n\n```python\n\nfrom django_sso_app.settings import *\n\nDJANGO_SSO_APP_SHAPE = env('DJANGO_SSO_APP_SHAPE', default='backend_only')\nDJANGO_SSO_APP_APIGATEWAY_HOST = env('DJANGO_SSO_APP_APIGATEWAY_HOST', default='kong')\nBACKEND_CUSTOM_FRONTEND_APP = env('BACKEND_CUSTOM_FRONTEND_APP', default=None)\n\nLOCAL_APPS = [\"backend.users.apps.UsersConfig\"]  # ...\n\nLOCAL_APPS += DJANGO_SSO_APP_DJANGO_APPS\n\nMIDDLEWARE = [\n    ...\n    'django_sso_app.core.authentication.backends.DjangoSsoAppLoginAuthenticationBackend',\n\n    'django_sso_app.core.authentication.middleware.DjangoSsoAppAuthenticationMiddleware',\n    ...\n]\n\nAUTHENTICATION_BACKENDS = [\n    'django.contrib.auth.backends.ModelBackend',\n] + DJANGO_SSO_APP_DJANGO_AUTHENTICATION_BACKENDS\n\n\nAUTH_USER_MODEL = 'users.User'\nLOGIN_URL = '/login/'\n\nDRF_DEFAULT_AUTHENTICATION_CLASSES = [\n    'rest_framework.authentication.TokenAuthentication'\n    'django_sso_app.core.api.authentication.DjangoSsoApiAuthentication'\n]\n\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': DRF_DEFAULT_AUTHENTICATION_CLASSES,\n    'DEFAULT_PERMISSION_CLASSES': (\n        'rest_framework.permissions.IsAuthenticated',\n    ),\n}\n\n```\n\n\n#### urls.py\n```python\nurlpatterns = []\napi_urlpatterns = []\n_I18N_URLPATTERNS = []\n\nfrom django_sso_app.urls import (urlpatterns as django_sso_app__urlpatterns,\n                                 api_urlpatterns as django_sso_app__api_urlpatterns,\n                                 i18n_urlpatterns as django_sso_app_i18n_urlpatterns)\nfrom django_sso_app.core.mixins import WebpackBuiltTemplateViewMixin\n\nurlpatterns += django_sso_app__urlpatterns\napi_urlpatterns += django_sso_app__api_urlpatterns\n_I18N_URLPATTERNS += django_sso_app_i18n_urlpatterns\n\nurlpatterns += [\n    url(r'^i18n/', include('django.conf.urls.i18n')),\n    url(r'^jsi18n/$', ...\n]\n\n_I18N_URLPATTERNS += [\n    path('', WebpackBuiltTemplateViewMixin.as_view(template_name='pages/home.html'), name='home'),\n    path('about/', WebpackBuiltTemplateViewMixin.as_view(template_name='pages/about.html'), name='about'),\n\n    # Django Admin, use {% url 'admin:index' %}\n    path(settings.ADMIN_URL, admin.site.urls),\n]\n\nif settings.I18N_PATH_ENABLED:\n    urlpatterns += i18n_patterns(\n        *_I18N_URLPATTERNS\n    )\nelse:\n    urlpatterns += _I18N_URLPATTERNS\n\n```\n\n\n",
    "bugtrack_url": null,
    "license": "mit",
    "summary": "User profile management app",
    "version": "0.8.5",
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "4fd5d3bb6fba3c21bb8f44b1906fc572",
                "sha256": "5f81478513f9c323c2f269107381d0cd54aef6ffc07756b3d4a101986c509e87"
            },
            "downloads": -1,
            "filename": "django_sso_app-0.8.5-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4fd5d3bb6fba3c21bb8f44b1906fc572",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 291723,
            "upload_time": "2020-09-16T12:50:49",
            "upload_time_iso_8601": "2020-09-16T12:50:49.703428Z",
            "url": "https://files.pythonhosted.org/packages/b9/ed/a50ce308a9dc17ef5a8cfca9f31d02e7e695340655f274103bf83385775c/django_sso_app-0.8.5-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "b709c1c7e8e3d39538ed02a223ee5a56",
                "sha256": "2ce48869a28454df299a926e892170702756e34bfa6b4670eef44f834ef51e98"
            },
            "downloads": -1,
            "filename": "django-sso-app-0.8.5.tar.gz",
            "has_sig": false,
            "md5_digest": "b709c1c7e8e3d39538ed02a223ee5a56",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 223494,
            "upload_time": "2020-09-16T12:50:52",
            "upload_time_iso_8601": "2020-09-16T12:50:52.154778Z",
            "url": "https://files.pythonhosted.org/packages/ae/22/78c77f0659ea1f1dff8bd9bf26934edc1d3cf1a6eefad02eb571e82233ef/django-sso-app-0.8.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2020-09-16 12:50:52",
    "github": false,
    "gitlab": false,
    "bitbucket": true,
    "bitbucket_user": null,
    "bitbucket_project": "pai",
    "lcname": "django-sso-app"
}
        
pai
Elapsed time: 0.16040s