core: add new token intent and auth backend
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
aad753de68
commit
20572c728d
|
@ -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."""
|
||||||
|
|
|
@ -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
|
|
@ -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"
|
||||||
|
|
|
@ -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"),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Reference in New Issue