Cannot access admin panel after setting up django-oauth-toolkit - django

I had a pet-api (testing api) without authentication. I'm trying to learn how to implement oath2 to add security to my app.
I'd like to access the models of my app through a request call using
the API but also through the Django Admin Panel.
I'm following this tutorial: https://medium.com/#halfspring/guide-to-an-oauth2-api-with-django-6ba66a31d6d
for setting up: django-oauth-toolkit
Tutorial says I should add this code to settings:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend' # To keep the Browsable API
'oauth2_provider.backends.OAuth2Backend',
)
But when I run server, and try to access /admin, I get:
ModuleNotFoundError at /admin/login/
No module named 'django.contrib.auth.backends.ModelBackendoauth2_provider'; 'django.contrib.auth.backends' is not a package
If I comment:
# 'django.contrib.auth.backends.ModelBackendoauth2_provider';
I can access the interface for the login, but says my user or password are wrong (they are not).
Commenting both lines I can access the admin panel without problems:
#AUTHENTICATION_BACKENDS = (
# 'django.contrib.auth.backends.ModelBackend' # To keep the Browsable API
# 'oauth2_provider.backends.OAuth2Backend',
#)

There is an error in code,
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend' # To keep the Browsable API
'oauth2_provider.backends.OAuth2Backend',
)
There is a comma (,) missing after 'django.contrib.auth.backends.ModelBackend' so it is taking both lines as single line, as you can see in the error.
So you needed to do just
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', # To keep the Browsable API
'oauth2_provider.backends.OAuth2Backend',
)
Now it will work...

It's okay, mine is working good now without it. I am also following that guide. Just continue http://127.0.0.1:8000/o/applications.
BTW, I am also commenting the ALLOWED_HOSTS = ['0.0.0.0'] and on the users/views.py, I changed all the http://0.0.0.0:8000 to http://127.0.0.1:8000.
And I now get these:
{
"access_token": "C2qukd1zWz9aGSp652qbnpYjoT6ZRx",
"expires_in": 36000,
"token_type": "Bearer",
"scope": "read write",
"refresh_token": "UoI0r9J09F3kcXGO1q3KsYoGHQ9DBw"
}

Related

Set up DRF Browsable API Root with all api urls

In my urls.py I have many rest framework urls:
path(
"api/",
include([
path("users/", api_views.users, name="users"),
path("proposals/", api_views.Proposals.as_view(), name="proposals"),
path("requests/", api_views.Requests.as_view(), name="requests"),
#...
])
)
I can visit the individual endpoints in the browser and access the browsable API, but I want to set up a browsable API Root where I can see all the available endpoints. The DRF tutorial has an example in which they list the urls they want in the root, but I have a lot of urls and I want all of them to show up. Is there a way to include all the urls in my "api/" path?
You should try to use drf_yasg package. Here's a documentation for that.

DigitalOcean Django Rest Framework Authentication credentials were not provided

My live site decided to throw a 403 Forbidden error yesterday on authenticated users when calling an Ajax API and I've trying to troubleshoot with no success. The localhost on my machine works fine when DEBUG = True in my settings.py, but the same code throws the following error:
HTTP 403 Forbidden
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"detail": "Authentication credentials were not provided."
}
My rest framework setting in settings.py:
## REST framework default permissions
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
Since the browsable API requires SessionAuthentication, I tried the following with no success:
## REST framework default permissions
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
I did look at Django Rest Framework Docs and it seems to suggest that if my user is logged in, the Ajax calls after login should work fine. Am I missing something? Really appreciate your input
UPDATE 1:
When I run the command:
sudo journalctl -u gunicorn -n 25
One of the things I see is gunicorn[820]: Session data corrupted
I did restart the server, hoping that by logging back in, the new session data will be generated, but the same message is displayed. The logged in user is still not able to view the data the ajax call is trying to fetch. How do I resolve the sessions data corrupted message. I am guessing this affects the DRF authenticating the request
My problem was with the migrations and so I ended up backing up my database, deleting all tables, recreating the tables using Django migrations. Some migration file must have been not in sync for some reason. I really don't know if I messed up manually manipulating something or if it was a bug. Anyways, water under the bridge...

How to set Authentication and Permission on django URLs for imported views

I want to use django REST framework's inbuilt API documentation. The problem is that I need it to be private with a login and I couldn't manage thus far. I do the following to create my API doc as documented:
from rest_framework.documentation import include_docs_urls
API_TITLE = "Cool title"
API_DESCRIPTION = "Badass description"
urlpatterns = [
path('docs/', include_docs_urls(title=API_TITLE, description=API_DESCRIPTION)
That creates my docs, which is fantastic. But it is accessible by everyone even though I have set my permissions and authentications for all the endpoints to private. I did this like this in my configs:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAdminUser',
)
}
But even with this set I can access all site of the docs.
So I am looking for a way to protect my URLs which I imported and thus have no classes or methods at my disposal to protect. (So I can't use any decorators on them). Then I tried using the login required decorator on my URL like so:
path('docs/', login_required(include_docs_urls(title=API_TITLE, description=API_DESCRIPTION))),
but it throws me the following error: django.template.exceptions.TemplateDoesNotExist: registration/login.html
Is there a way of protecting such URLs?
Help is very much appreciated! Thanks a lot in advance!
EDIT: I figured I could pass permission classes as argument to my URL, and indeed Pycharm marks it as an option. So I put:
path('docs/', include_docs_urls(title=API_TITLE, description=API_DESCRIPTION, permission_classes= "rest_framework.permissions.IsAdminUser")),
That throws me the error str object not callable. Any ideas on how I could pass my permission classes there maybe?
For anyone ever having this problem. It is possible by doing the following:
from rest_framework.permissions import IsAdminUser
path('api/docs', include_docs_urls(
title=API_TITLE, description=API_DESCRIPTION, permission_classes=[IsAdminUser]
))
I wish this inbuilt API documentation tool was documented better. Took me a while to even find out that this exists....

Linkedin-api This resource is no longer available under v1 APIs

I am using allauth for django to authenticate with linkedin, but when I am trying to authenticate it is returning in api response that "This resource is no longer available under v1 APIs"
below are my settings for django app.
'SCOPE': [
'w_share','r_emailaddress','r_basicprofile','rw_company_admin'
],
'PROFILE_FIELDS': [
'id',
'first-name',
'last-name',
'email-address',
'picture-url',
'public-profile-url',
]
please guide me what I am doing wrong.
As mentioned by #Antwane replace
access_token_url = 'https://api.linkedin.com/uas/oauth2/accessToken'
authorize_url = 'https://www.linkedin.com/uas/oauth2/authorization'
with
access_token_url = 'https://www.linkedin.com/oauth/v2/accessToken'
authorize_url = 'https://www.linkedin.com/oauth/v2/authorization'
and replace r_basicprofile with r_liteprofile in scope. In v2 they replace r_basicprofile with r_liteprofile.
Now to access the basic profile you need to call https://api.linkedin.com/v2/me instead of https://api.linkedin.com/v1/people/~. Unlike the v1 API you will not get the Email address in profile API(in short r_liteprofile does not contain Email Address).
While making API request add Header Field "X-RestLi-Protocol-Version":"2.0.0"
To access the Email address you should call https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))
This is a known issue. You may wait until pull request #2087 is merged so issue #2086 is closed, and a new release of django-allauth is published.
Before that, you may create a customized adapter for Linkedin API, with updated access token and authorization URLs. See allauth documentation for more info.
For example, copy module allauth.socialaccount.providers.linkedin_oauth2 into your own project and edit views.py to update URLs
access_token_url = 'https://api.linkedin.com/uas/oauth2/accessToken'
authorize_url = 'https://www.linkedin.com/uas/oauth2/authorization'
need to be changed to:
access_token_url = 'https://www.linkedin.com/oauth/v2/accessToken'
authorize_url = 'https://www.linkedin.com/oauth/v2/authorization'
Now, adding your custom allauth app to your INSTALLED_APPS will let you use Linkedin API like before.

Facebook login not working properly using django-social-auth

I'm trying to integrate facebook login on a site I'm working on, but so far, it doesn't seem to be working. I'd expect to get something similar to the usual dialog I get like what comes up at the test page at http://social.matiasaguirre.net/
But so far what I'm getting is this
To setup the app on Facebook, I've only added the domain, then under how it integrates with Facebook, I've selected the first option for logging in via Facebook. Then I've copied the id and secret key to my settings file as required by django-social-auth.
My settings file:
SOCIAL_AUTH_ENABLED_BACKENDS = ('facebook', 'twitter')
SOCIAL_AUTH_COMPLETE_URL_NAME = 'socialauth_complete'
SOCIAL_AUTH_ASSOCIATE_URL_NAME = 'associate_complete'
SOCIAL_AUTH_DEFAULT_USERNAME = 'socialauth_user'
SOCIAL_AUTH_CREATE_USERS = True
SOCIAL_AUTH_FORCE_RANDOM_USERNAME = False
SOCIAL_AUTH_CHANGE_SIGNAL_ONLY = False
SOCIAL_AUTH_ERROR_KEY = 'socialauth_error'
SOCIAL_AUTH_ASSOCIATE_BY_MAIL = True
AUTHENTICATION_BACKENDS = (
'social_auth.backends.twitter.TwitterBackend',
'social_auth.backends.facebook.FacebookBackend',
# 'django.contrib.auth.backends.ModelBackend',
'apps.members.backends.Sha256Backend',
)
AUTH_PROFILE_MODULE = 'members.Member'
What could be the problem? I tried running the demo that comes with django-social-auth, and I still get the same results, so my thinking was I'm missing something on Facebook. Any ideas will be appreciated. Thanks.
Update 1
So I've set up the example project that comes with the social auth app, and the error I get is Incorrect authentication service after I click 'Install' on the auth dialog box
What you're showing above is the difference between the new enhanced auth dialog and the older dialog. You can change your app setting to use either one.
Go to: https://developers.facebook.com/apps/{appId}/advanced and set the "Enhanced Auth Dialog" setting to Disabled. And now you will get a similar dialog.