Getting Request User on Django Rest Oauth2 - python

I'm using the Django Rest Framework with the Django Oauth Toolkit.
I'm connecting fine. I have no issues with the token, access and permissions.
But I'd like to have a queryset with a filter of the current user something like:
def get_queryset(self):
return Account.objects.filter(user=self.request.user)
When I do this, the user I get is a None Type. Even though I was able to pass correctly the Token via Authorization Bearer.
The oAuth2 application created for this has the following settings:
client type: confidential
authorization grant type: client credentials

Related

Django REST Custom (token) authentication

Because I'm mixing things up and just making myself more confused, maybe someone can actually guide me through it.
I need to make a Django REST API that requires login. However the User table already exists in a Postgres database. I think token-based authentication is most suitable, however, those tokens don't exist yet.
(Login once to retrieve/create a token, check the token on each request)
How can I use a POST request to submit login details purely for verifying the user?
How would I generate a token upon successful login, and should I store it in a new Token table?
After this, how can I use the token to provide authentication/authorization on API data requests?
All examples I can find use the default Django User model or don't go into enough detail, which I can't use in this case.
I've made a custom authenticator that checks the username and password, however I can't get through the next steps.
from api.models import LogonAccount
from rest_framework import authentication
from rest_framework import exceptions
import bcrypt
class ExampleAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
username = request.data.get('username') # get the username request header
password = request.data.get('password') # get the password request header
if not username or not password: # no username or password passed in request headers
return None # authentication did not succeed
try:
user = LogonAccount.objects.get(username=username)
if bcrypt.hashpw(password.encode(), user.password.encode()):
print("succes")
return (user, None) # authentication successful
except LogonAccount.DoesNotExist:
raise exceptions.AuthenticationFailed('No such user')
Don't get confused, you are simply trying to achieve token-based authentication with DRF. DRF already comes with this feature. This article will guide you through that https://simpleisbetterthancomplex.com/tutorial/2018/11/22/how-to-implement-token-authentication-using-django-rest-framework.html

Why is my Python code getting 401 access denied from the Microsoft Dynamics 365 CRM API?

I am trying to download some data from a customer's Microsoft Dyanmics 365 CRM API. Below is my code written in Python 3.7, using MSAL (Microsoft Authentication Library) for Python.
import msal
import requests
class Downloader:
AUTHORITY = 'https://login.microsoftonline.com/common'
SCOPES = ["https://admin.services.crm.dynamics.com/user_impersonation"]
def __init__(self, client_id, client_credential, refresh_token):
self.client_id = client_id
self.client_credential = client_credential
self.refresh_token = refresh_token
def download(self):
application = msal.ConfidentialClientApplication(
client_id=self.client_id,
client_credential=self.client_credential,
authority=self.AUTHORITY,
token_cache=None)
response = application.acquire_token_by_refresh_token(self.refresh_token, self.SCOPES)
instances = requests.get(
'https://globaldisco.crm.dynamics.com/api/discovery/v1.0/Instances',
headers={'Authorization': 'Bearer ' + response['access_token']},
)
return response
When I run the download() method I successfully get a response that contains an Access Token but when I use it to GET instances I get back HTTP Status Code 401 Access Denied.
My question is: Why am I getting 401 Access Denied and how can I fix my code to get 200 OK?
More data:
client_id and client_credential identify a multi-tenant Azure App Registration I've setup. This app registration is not verified yet. It has these API Permissions (scopes) configured:
https://admin.services.crm.dynamics.com/user_impersonation
https://graph.microsoft.com/User.Read
refresh_token has been generated based on Quickstart: Add sign-in with Microsoft to a Python web app. The quickstart goes through setting up a small Flask web application where a person can sign in via Microsoft Identity and grant permission for my app registration to impersonate them when later accessing the Dynamics 365 CRM API. I've setup the Flask app to use my App Registration and the two scopes above.
Because my App Registration is not verified yet, I had an admin of the target tenet sign in via the Flask app, approve and give consent for my app registration to be used by the tenet org. I've tried both their refresh token and another non-admin person's refresh token. Both yield 401.
The tenet org (to which my customers' identities belong) is linked to a Dynamics 365 account.
Update:
When I view my app registration in my customer's (i.e. tenet's) Azure Portal under Enterprise Applications I can see the Common Data Service user_impersonation permission under the Admin consent tab but it's missing from the User consent tab.
I'm trying to figure out whether this might explain why users are denied access and how to add the missing permission to User consent.
Has the user been added to CRM? The identity you are using should still have full roles assigned within CRM. Someone should have added that app registration to the list of users in CRM. Settings->Security (change the list view to "Application Users") press "New", change the form from "user" to "Application User".
Set the Name, copy the application Id from the Application registration. The email can exist or not.

Enable SSO for user authentication in django python project using keycloak as identity broker

I am trying to enable SSO using keycloak as identity broker and Microsoft AD as identity provider(where keycloak will delegate the client's authentication request to AD) in a django python project.
Tech stack of application:
frontend- React,
backend - django python
For this I am using python-keycloak library in django to communicate with keycloak.What I am able to achieve is : setup a connection with keycloak and get access_token and refresh_token when username and password is provided like this:
# Create Keycloak instance
self.keycloak = KeycloakOpenID(server_url=self.server_url,
client_id=self.client_id,
realm_name=self.realm,
client_secret_key=self.client_secret_key)
# Get WellKnow
self.config_well_know = self.keycloak.well_know()
# Get Token
self.token = self.keycloak.token("user","pwd")
# get userinfo
self.userInfo = self.keycloak.userinfo(self.token['access_token'])
# userinfo returned ok
But here i am providing username and password which I should not as I want to enable sso with Microsoft AD(Note: keycloak realm is configured to use Microsoft AD as default IDP) and only username should be sufficient to enable SSO with Microsoft. But it is giving error on passing only username.
Question:
How to authenticate user from Microsoft AD using keycloak broker and what should be the syntax for the same?
Create two clients in your example realm. One for your React app, setup as Public client where you should use Javascript adapter to generate access token where u pass that using headers and your backend Django app setup as a confidential client that could access the access token generated from the fronted react app. Using python-keycloak Library do introspect the token for its correctness.
Try setting up Identity brokering in your example realm using OIDC/SAML use your Azure apps metadata URL to set up the profile along with relevant mappers.
After this setup you should get SSO to work properly.

django authentication and password reset

So, i am currently working on a web application project and i implemented authentication and password confirmation successfully.
But my issue is that i did it using html templates and now the requirement came up that we have to develop our application using api's for the backened.
Now, i am new to api and really confused how to use the authentication system i built (as we have to provide template to the in-built implemented class and they accept the values from their itself)
Is it possible to actually see and manage the registered users from the code-behind while still using there in-built mechanism
For password change you can use this generic view using the inbuilt Django auth framework
#login_required
def change_password(request):
if request.method == "POST":
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
user = form.save()
# Important to update the session otherwise user will have to login again
update_session_auth_hash(request, user)
# Server side alert
print("Password changed for {0}".format(user.username))
return redirect('/index/')
else:
print(form.errors)
else:
form = PasswordChangeForm(request.user)
return render(request, 'website/changepassword.html', {'form': form})
You need to use djangorestframework, and use the decorator #apiview(['GET', 'POST']) to create a RestAPI
You can use TokenAuthentication available in django rest framework. See what documentation says:
TokenAuthentication
This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.
To use the TokenAuthentication scheme you'll need to configure the authentication classes to include TokenAuthentication, and additionally include rest_framework.authtoken in your INSTALLED_APPS setting:
INSTALLED_APPS = (
...
'rest_framework.authtoken'
)
Note: Make sure to run manage.py migrate after changing your settings. The rest_framework.authtoken app provides Django database migrations.
You'll also need to create tokens for your users.
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=...)
print token.key
For clients to authenticate, the token key should be included in the Authorization HTTP header. The key should be prefixed by the string literal "Token", with whitespace separating the two strings. For example:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
Note: If you want to use a different keyword in the header, such as Bearer, simply subclass TokenAuthentication and set the keyword class variable.
If successfully authenticated, TokenAuthentication provides the following credentials.
request.user will be a Django User instance.
request.auth will be a rest_framework.authtoken.models.Token instance.
Unauthenticated responses that are denied permission will result in an HTTP 401 Unauthorized response with an appropriate WWW-Authenticate header. For example:
WWW-Authenticate: Token
The curl command line tool may be useful for testing token authenticated APIs. For example:
curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
Note: If you use TokenAuthentication in production you must ensure that your API is only available over https.
Source: http://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication

Facebook Login in Django Backend with big Frontend separation.

I'm trying to make a login with Facebook.
What I want is to create and endpoint and use it as I use the "standard" email login endpoint, since I need a big separation between the backend and the frontend.
I think it should be easy to do it, but I don't know how to do it.
I read this and when I use the Url in the browser, it works properly and I get the token in the response Url. But, it happens always on the frontend side.
I tried many tutorials this one is an example, and it works, but I'm the backend, I'm not allowed to have something like that, as the frontend is written in Django too.
So, I don't know how should be the workflow when you're just the Backend, I don't know what the Frontend developers wait from me because the authentication happens actually on the frontend side.
And I'm a little bit lost.
Maybe someone had the same problem as Backend and could help me, at least tell me, how the workflow backend - frontend should be.
Facebook JavaScript/Android/iOs SDKs lets the client to authenticate the users. Once the user is authenticated with facebook, your clients can send the accessToken through a HTTP POST over https.
This is what I have done in a similar situation,
At backend,
Create API endpoint to authenticate user by validating their accessToken,
POST /auth/
Use this endpoint to verify the accessToken sent by the client. The token should be validated calling Facebook services with your app secret. Once done validating, return a response as a JSON detailing the status of the authentication and user identification details if successful.
on the request,
body should contain accessToken as a key/or a header
Content-Type header should be application/json
any additional expected headers must be validated
on the request try to include
status of the operation
user identification detail if operation is success
a JWT or some sorta token to identify the user which users can include in Authorization header, so that you can validate the request just buy validating the token against User. Set an expiry as the accessToken if JWT is expired, refresh accessToken at client side and validate again.
At Frontend.
Let the client do the following to authenticate themselves.
send accessToken to /auth as a POST request.
if authentication status is success, let them store the JWT in locally and use it on the upcoming requests.
at backend on upcoming calls,
if token is expired or tampered, redirect client to authenticate with Facebook again.
on logging out of user, delete the token from client.
So for the frontend developers,
Document your API properly and share it with them

Categories

Resources