sources/oauth: directly call AuthorizedServiceBackend instead of authenticate()

This commit is contained in:
Jens Langhammer 2020-07-07 21:47:07 +02:00
parent cfc181eed1
commit 5644e57e6a
3 changed files with 15 additions and 19 deletions

View File

@ -1,24 +1,23 @@
"""passbook oauth_client Authorization backend""" """passbook oauth_client Authorization backend"""
from django.contrib.auth.backends import ModelBackend from django.contrib.auth.backends import ModelBackend
from django.db.models import Q from django.db.models import Q
from django.http import HttpRequest
from passbook.core.models import User
from passbook.sources.oauth.models import OAuthSource, UserOAuthSourceConnection from passbook.sources.oauth.models import OAuthSource, UserOAuthSourceConnection
class AuthorizedServiceBackend(ModelBackend): class AuthorizedServiceBackend(ModelBackend):
"Authentication backend for users registered with remote OAuth provider." "Authentication backend for users registered with remote OAuth provider."
def authenticate(self, request, source=None, identifier=None): def authenticate(
self, request: HttpRequest, source: OAuthSource, identifier: str
) -> User:
"Fetch user for a given source by id." "Fetch user for a given source by id."
source_q = Q(source__name=source) source_q = Q(source__name=source)
if isinstance(source, OAuthSource): if isinstance(source, OAuthSource):
source_q = Q(source=source) source_q = Q(source=source)
try:
access = UserOAuthSourceConnection.objects.filter( access = UserOAuthSourceConnection.objects.filter(
source_q, identifier=identifier source_q, identifier=identifier
).select_related("user")[0] ).select_related("user")[0]
except IndexError:
return None
else:
return access.user return access.user

View File

@ -1,9 +1,5 @@
"""Oauth2 Client Settings""" """Oauth2 Client Settings"""
AUTHENTICATION_BACKENDS = [
"passbook.sources.oauth.backends.AuthorizedServiceBackend",
]
PASSBOOK_SOURCES_OAUTH_TYPES = [ PASSBOOK_SOURCES_OAUTH_TYPES = [
"passbook.sources.oauth.types.discord", "passbook.sources.oauth.types.discord",
"passbook.sources.oauth.types.facebook", "passbook.sources.oauth.types.facebook",

View File

@ -3,7 +3,6 @@ from typing import Any, Callable, Dict, Optional
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import authenticate
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import Http404, HttpRequest, HttpResponse from django.http import Http404, HttpRequest, HttpResponse
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
@ -22,6 +21,7 @@ from passbook.flows.planner import (
) )
from passbook.flows.views import SESSION_KEY_PLAN from passbook.flows.views import SESSION_KEY_PLAN
from passbook.lib.utils.urls import redirect_with_qs from passbook.lib.utils.urls import redirect_with_qs
from passbook.sources.oauth.auth import AuthorizedServiceBackend
from passbook.sources.oauth.clients import BaseOAuthClient, get_client from passbook.sources.oauth.clients import BaseOAuthClient, get_client
from passbook.sources.oauth.models import OAuthSource, UserOAuthSourceConnection from passbook.sources.oauth.models import OAuthSource, UserOAuthSourceConnection
from passbook.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND from passbook.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
@ -134,7 +134,7 @@ class OAuthCallback(OAuthClientMixin, View):
identifier=identifier, identifier=identifier,
access_token=token.get("access_token"), access_token=token.get("access_token"),
) )
user = authenticate( user = AuthorizedServiceBackend().authenticate(
source=self.source, identifier=identifier, request=request source=self.source, identifier=identifier, request=request
) )
if user is None: if user is None:
@ -181,7 +181,8 @@ class OAuthCallback(OAuthClientMixin, View):
self.request, self.request,
{ {
PLAN_CONTEXT_PENDING_USER: user, PLAN_CONTEXT_PENDING_USER: user,
PLAN_CONTEXT_AUTHENTICATION_BACKEND: user.backend, # Since we authenticate the user by their token, they have no backend set
PLAN_CONTEXT_AUTHENTICATION_BACKEND: "django.contrib.auth.backends.ModelBackend",
PLAN_CONTEXT_SSO: True, PLAN_CONTEXT_SSO: True,
}, },
) )
@ -206,7 +207,7 @@ class OAuthCallback(OAuthClientMixin, View):
% {"source": self.source.name} % {"source": self.source.name}
), ),
) )
user = authenticate( user = AuthorizedServiceBackend().authenticate(
source=access.source, identifier=access.identifier, request=self.request source=access.source, identifier=access.identifier, request=self.request
) )
return self.handle_login_flow(source.authentication_flow, user) return self.handle_login_flow(source.authentication_flow, user)
@ -249,7 +250,7 @@ class OAuthCallback(OAuthClientMixin, View):
) )
) )
# User was not authenticated, new user has been created # User was not authenticated, new user has been created
user = authenticate( user = AuthorizedServiceBackend().authenticate(
source=access.source, identifier=access.identifier, request=self.request source=access.source, identifier=access.identifier, request=self.request
) )
messages.success( messages.success(