Skip to content
Snippets Groups Projects
authentication.py 1.73 KiB
Newer Older
Eliot Berriot's avatar
Eliot Berriot committed
from rest_framework import authentication, exceptions

from funkwhale_api.users.models import User


def get_token(salt, password):
    to_hash = password + salt
    h = hashlib.md5()
Eliot Berriot's avatar
Eliot Berriot committed
    h.update(to_hash.encode("utf-8"))
    return h.hexdigest()


def authenticate(username, password):
    try:
Eliot Berriot's avatar
Eliot Berriot committed
        if password.startswith("enc:"):
            password = password.replace("enc:", "", 1)
            password = binascii.unhexlify(password).decode("utf-8")
            username__iexact=username, is_active=True, subsonic_api_token=password
Eliot Berriot's avatar
Eliot Berriot committed
    except (User.DoesNotExist, binascii.Error):
        raise exceptions.AuthenticationFailed("Wrong username or password.")

    return (user, None)


def authenticate_salt(username, salt, token):
    try:
        user = User.objects.get(
Eliot Berriot's avatar
Eliot Berriot committed
            username=username, is_active=True, subsonic_api_token__isnull=False
Eliot Berriot's avatar
Eliot Berriot committed
    except User.DoesNotExist:
        raise exceptions.AuthenticationFailed("Wrong username or password.")
    expected = get_token(salt, user.subsonic_api_token)
    if expected != token:
Eliot Berriot's avatar
Eliot Berriot committed
        raise exceptions.AuthenticationFailed("Wrong username or password.")

    return (user, None)


class SubsonicAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        data = request.GET or request.POST
Eliot Berriot's avatar
Eliot Berriot committed
        username = data.get("u")
Eliot Berriot's avatar
Eliot Berriot committed
        p = data.get("p")
        s = data.get("s")
        t = data.get("t")
Eliot Berriot's avatar
Eliot Berriot committed
            raise exceptions.AuthenticationFailed("Missing credentials")

        if p:
            return authenticate(username, p)

        return authenticate_salt(username, s, t)