# django-auth-spngeo 🪄

Django authentication backend for adding Kerberos/GSS auth to your Django application for single sign-on.

Provides authentication backends and views that are ready-to-use without further modification or can be used
as mixins and part of already-existing logic.


## Requirements

* Generated keytab file that's either at `/etc/krb5.keytab` or set via environment variable `KRB5_KTNAME`
  See [here](https://kantega-sso.atlassian.net/wiki/spaces/KSE/pages/28180757/Create+a+keytab) 
  for excellent information on how to create one
* A working Kerberos KDC (MIT, Microsoft AD DS, Heimdall, ...)
* SPN (Service Principal Name) for your application server(s)
* A method for mapping Kerberos Principals to User objects in your backend


## Installation 👾

Install the package with pip:

`pip install django-auth-spnego2`

To use the auth backend in a Django project, add `'django_auth_spnego.backends.SpnegoModelBackend'` to 
`AUTHENTICATION_BACKENDS`:

```python
AUTHENTICATION_BACKENDS = [
    'django_auth_spnego.backends.SpnegoModelBackend',
]
```

If you want to use the pre-configured views to authenticate users, add `django_auth_spnego` to `INSTALLED_APPS` 
to be able to use the views:

```python
INSTALLED_APPS = [
    ...
    'django_auth_spnego',
]
```

Then simply add the authentication view to your `urls.py` (alternatively use `SpnegoLoginView` for redirects):

```python
from django_auth_spnego.views import SpnegoView

urls.append(r"^auth/spnego$", SpnegoView.as_view(), name="spnego")
```


## Configuration 🛠️

```python
# Optional setting to define which SPN to use in your keytab file. If this is empty, all keytab entries will be used.
#   For example: `HTTP/sso.contoso.loc`
AUTH_KERBEROS_SPN: str = ''

# Split the Kerberos ticket UPN (User Principal Name) at the rightmost `@` sign. This can be useful if you want to match
#   the left part to Django's default username or don't have your UPN's set up to match the e-mail address.
#       `Administrator@CONTOSO.LOC ==> Administrator`
#   This is only relevant when using the default authentication backend.
AUTH_KERBEROS_UPN_SPLIT: bool = True

# Which Django user field should be used for lookup (e.g. `username`, `email`). If this is empty, the `USERNAME_FIELD`
#   configured in the user model will be used instead.
#   This is only relevant when using the default authentication backend.
AUTH_KERBEROS_USERNAME_LOOKUP: str = ''

# Automatically create users attempting to authenticate that do not exist yet. 
#   This is only relevant when using the default authentication backend.
AUTH_KERBEROS_CREATE_UNKNOWN_USERS: bool = True
```


## Advanced Usage Information & Client Auth

Optionally, combine Kerberos authentication with LDAP via [django-auth-ldap](https://github.com/django-auth-ldap/django-auth-ldap) 
to aggregate further user information from your Domain Controller after successful authentication – 
like display name, email address and group memberships.

```python
from django_auth_ldap.backend import LDAPBackend
from django_auth_spnego.backends import SpnegoBackendMixin


class SpnegoLdapBackend(SpnegoBackendMixin, LDAPBackend):
    def get_user_from_username(self, username):
        return self.populate_user(username)
```


To test Kerberos authentication, acquire a ticket, and point your favorite supported client at the endpoint. 

```python
import requests
from requests_kerberos import HTTPKerberosAuth

r = requests.get('http://sso.contoso.loc/auth/spnego', auth=HTTPKerberosAuth())
r.status_code
```

See [here](https://www.roguelynn.com/words/apache-kerberos-for-django/) for further excellent information!


## Acknowledgements

* [Brandon Ewing (bewing)](https://github.com/bewing) for providing the [initial library](https://github.com/imc-trading/django-gss-spnego) this fork is based on
* [Matt Magin (AzMoo)](https://github.com/AzMoo) for writing a [similar Middleware](https://github.com/AzMoo/django-auth-spnego)
* [Lynn Root (econchick)](https://github.com/econchick) for an [excellent write-up](https://www.roguelynn.com/words/apache-kerberos-for-django/) on client auth
