core: add new token intent and auth backend

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-08-23 16:05:29 +02:00
parent aad753de68
commit 20572c728d
4 changed files with 40 additions and 3 deletions

View File

@ -408,6 +408,9 @@ class TokenIntents(models.TextChoices):
# Recovery use for the recovery app # Recovery use for the recovery app
INTENT_RECOVERY = "recovery" INTENT_RECOVERY = "recovery"
# App-specific passwords
INTENT_APP_PASSWORD = "app_password"
class Token(ManagedModel, ExpiringModel): class Token(ManagedModel, ExpiringModel):
"""Token used to authenticate the User for API Access or confirm another Stage like Email.""" """Token used to authenticate the User for API Access or confirm another Stage like Email."""

View File

@ -0,0 +1,29 @@
"""Authenticate with tokens"""
from typing import Any, Optional
from django.contrib.auth.backends import ModelBackend
from django.http.request import HttpRequest
from authentik.core.models import Token, TokenIntents, User
class TokenBackend(ModelBackend):
"""Authenticate with token"""
def authenticate(
self, request: HttpRequest, username: Optional[str], password: Optional[str], **kwargs: Any
) -> Optional[User]:
try:
user = User._default_manager.get_by_natural_key(username)
except User.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
User().set_password(password)
return None
tokens = Token.filter_not_expired(
user=user, key=password, intent=TokenIntents.INTENT_APP_PASSWORD
)
if not tokens.exists():
return None
return user

View File

@ -1,3 +1,4 @@
"""Backend paths""" """Backend paths"""
BACKEND_DJANGO = "django.contrib.auth.backends.ModelBackend" BACKEND_DJANGO = "django.contrib.auth.backends.ModelBackend"
BACKEND_LDAP = "authentik.sources.ldap.auth.LDAPBackend" BACKEND_LDAP = "authentik.sources.ldap.auth.LDAPBackend"
BACKEND_TOKEN = "authentik.core.token_auth.TokenBackend"

View File

@ -9,7 +9,7 @@ from rest_framework.serializers import BaseSerializer
from authentik.core.types import UserSettingSerializer from authentik.core.types import UserSettingSerializer
from authentik.flows.models import ConfigurableStage, Stage from authentik.flows.models import ConfigurableStage, Stage
from authentik.stages.password import BACKEND_DJANGO, BACKEND_LDAP from authentik.stages.password import BACKEND_DJANGO, BACKEND_LDAP, BACKEND_TOKEN
def get_authentication_backends(): def get_authentication_backends():
@ -17,11 +17,15 @@ def get_authentication_backends():
return [ return [
( (
BACKEND_DJANGO, BACKEND_DJANGO,
_("authentik-internal Userdatabase"), _("User database + standard password"),
),
(
BACKEND_TOKEN,
_("User database + app passwords"),
), ),
( (
BACKEND_LDAP, BACKEND_LDAP,
_("authentik LDAP"), _("User database + LDAP password"),
), ),
] ]