I'm writing a custom Authentication middleware that check the incoming requests for the "Authorization" key in the header, which contains a token.
I'm using this token to check with a third-party (Microsoft Graph) for the validity of the user. MS Graph will respond with an object like below
# the response object
{
'@odata.context': 'https://graph.microsoft.com/v1.0/$metadata#users/$entity',
'businessPhones': ['xxx'],
'displayName': 'xxx',
'givenName': 'xxx',
'id': 'xxx',
'jobTitle': None,
'mail': 'xxx',
'mobilePhone': None,
'officeLocation': None,
'preferredLanguage': 'xxx',
'surname': 'xxx',
'userPrincipalName': 'xxx'
}
EDIT: Adding custom middleware code here:
class AuthenticationMiddleware(MiddlewareMixin):
if not request.user.is_authenticated:
if "Authorization" in request.headers:
# Make a request to MS Graph with the given token
# to get user details and append to request
token = request.headers["Authorization"]
elif "accessToken" in request.GET:
token = request.GET["accessToken"]
else:
token = None
if token:
url = "https://graph.microsoft.com/v1.0/me/"
payload = {}
headers = {"Authorization": "Bearer {}".format(token)}
response = requests.request("GET", url, headers=headers, data=payload)
if response.ok:
request.custom_user = response.json()
else:
request.custom_user = AnonymousUser
else:
request.custom_user = AnonymousUser
Now I want to design this to work just like Django's default authentication backend with proper group and permission. How can I work on a LazyObject to be able to check for user's group membership and permission?
UPDATE
It looks like there's also a custom backend authentication that works like this.
Is it doing the same thing as I'm doing with the middleware?
from django.contrib.auth.backends import BaseBackend
class MyBackend(BaseBackend):
def authenticate(self, request, token=None):
# Check the token and return a user.
...
you should custom an Middleware like the below, and add it to middlewares in settings
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
# todo: do something you want in response
return response
see also:https://docs.djangoproject.com/en/3.1/topics/http/middleware/
EDIT:
Is it doing the same thing as I'm doing with the middleware?
no, it's not.
the most different is that
The backend is used for connecting with database, and the middleware is aim to process the request. You can find more examples code in django.middleware
package.
and if you want to custome how to save the infomation to database eg: customer the authenticate
method, you should customer a backend for the work. otherwise you may custome an middleware to process all of the requests. Because it is easy to customize middleware.