I'm trying to solve problem described here but code provided in that answer not works for latest django==2.2
I have tried to port this code but failed with that
settings.py:
MIDDLEWARE = ['polls.mymiddleware.CookieMiddleware',
mysite/polls/authbackend.py:
from django.contrib.auth.backends import RemoteUserBackend, UserModel
class Backend(RemoteUserBackend):
def authenticate(**credentials):
"""We could authenticate the token by checking with OpenAM
Server. We don't do that here, instead we trust the middleware to do it.
"""
try:
user = UserModel.objects.get(username=credentials['remote_user'])
print('__user exists')
except UserModel.DoesNotExist:
user = UserModel.objects.create(username=credentials['remote_user'])
print('__user not exists')
# Here is a good place to map roles to Django Group instances or other features.
return user
mysite/polls/mymiddleware.py:
from django.contrib.auth import authenticate, login, ImproperlyConfigured
class CookieMiddleware(object):
"""Authentication Middleware for OpenAM using a cookie with a token.
Backend will get user.
"""
def process_request(self, request):
if not hasattr(request, 'user'):
raise ImproperlyConfigured()
if "thecookiename" not in request.COOKIES:
return
# token = request.COOKIES["thecookiename"]
# REST request to OpenAM server for user attributes.
# token, attribute, role = identity_manager.get_attributes(token)
# user = authenticate(remote_user=attribute['uid'][0])
user = authenticate(remote_user=1) # simplified for test
request.user = user
login(request, user)
result of that:
File "C:\Users\Administrator\Desktop\my_scripts\mysite\mysite\wsgi.py", line 16, in <module>
application = get_wsgi_application()
File "C:\Users\Administrator\Desktop\my_scripts\venv\lib\site-packages\django\core\wsgi.py", line 13, in get_wsgi_application
return WSGIHandler()
File "C:\Users\Administrator\Desktop\my_scripts\venv\lib\site-packages\django\core\handlers\wsgi.py", line 135, in __init__
self.load_middleware()
File "C:\Users\Administrator\Desktop\my_scripts\venv\lib\site-packages\django\core\handlers\base.py", line 37, in load_middleware
mw_instance = middleware(handler)
TypeError: object() takes no parameters
Update 1: fixed issue above, thanks to #Daniel_Rossman for that:
need to put your middleware after the SessionMiddleware in your MIDDLEWARE settings.
but got now new problem:
Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\my_scripts\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\Administrator\Desktop\my_scripts\venv\lib\site-packages\django\utils\deprecation.py", line 93, in __call__
response = self.process_request(request)
File "C:\Users\Administrator\Desktop\my_scripts\mysite\polls\mymiddleware.py", line 22, in process_request
login(request, user, backend='polls.mymiddleware.CookieMiddleware')
File "C:\Users\Administrator\Desktop\my_scripts\venv\lib\site-packages\django\contrib\auth\__init__.py", line 126, in login
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
AttributeError: 'NoneType' object has no attribute '_meta'
[25/Apr/2019 12:40:07] "GET /admin/ HTTP/1.1" 500 64298
Inherit yor middleware from MiddlewareMixin like this
from django.utils.deprecation import MiddlewareMixin
class CookieMiddleware(MiddlewareMixin):
"""Authentication Middleware for OpenAM using a cookie with a token.
Backend will get user.
"""
def process_request(self, request):
if not hasattr(request, 'user'):
raise ImproperlyConfigured()
if "thecookiename" not in request.COOKIES:
return
# token = request.COOKIES["thecookiename"]
# REST request to OpenAM server for user attributes.
# token, attribute, role = identity_manager.get_attributes(token)
# user = authenticate(remote_user=attribute['uid'][0])
user = authenticate(remote_user=1) # simplified for test
request.user = user
login(request, user)
Related
I am new to Django and was trying to implement the below-mentioned scenario which is as such:
I have a google account as well as a facebook account with the same email address by using django-allauth. So if I am already logged in using google/facebook account and try to login from facebook/google i.e. the other social account in the same session, I should show that the user has already been logged in with this email ID. My approach is to set email and provider id in the session request and manipulate it in the pre_social_login signal in my social adapter.
So far I have defined my middleware as such:
middleware.py
from django.contrib import messages
class SimpleMiddleware(object):
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.
if request.path == '/accounts/login/' and request.method == 'GET' and not request.user.is_authenticated:
if 'email' not in request.session:
request.session['email'] = ''
request.session['provider']=''
request.session['is_active']='False'
response = self.get_response(request)
return response
my_adapter.py
from allauth import account
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
class MySocialAccountAdapter(DefaultSocialAccountAdapter):
def pre_social_login(self, request, sociallogin):
if request.session['email']=='' and request.session['provider']=='':
request.session['email']=sociallogin.account.extra_data['email']
request.request.session['provider']=sociallogin.account.provider
request.session['is_active']=False
response = self.get_response(request)
elif request.session['email']==sociallogin.account.extra_data['email'] and request.session['provider']!=sociallogin.account.provider:
request.session['is_active']=True
response = self.get_response(request)
else:
request.session['is_active']=True
response = self.get_response(request)
return response
But after the accounts/login/callback is hit, the following error is thrown:
AttributeError at /accounts/google/login/callback/
'WSGIRequest' object has no attribute 'request'
Request Method: GET
Request URL: https://a2d3-110-36-226-234.ngrok.io/accounts/google/login/callback/?state=22U9GJsvDe3e&code=4%2F0AX4XfWg-xpibKpAXe-Bl0Tpj8Un_PLLNZ-seIwyI0QGgOPbJdHZW1Wt87WZoRMztn5Jikg&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=0&prompt=none
Django Version: 4.0
Exception Type: AttributeError
Exception Value:
'WSGIRequest' object has no attribute 'request'
Exception Location: C:\Users\user\Desktop\project\social\login_app\my_adapter.py, line 13, in pre_social_login
Python Executable: C:\Users\user\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\python.exe
Python Version: 3.9.9
ANY SUGGESTIONS, PLEASE?
I am implementating custom registration flow in which a user gets a verification email upon registration and thence clicks on the confirmation link to activate account. However, clicking the link gives this error:
Internal Server Error: /accounts/activate/Ng/5ho-db922c523f2c7f1a7f51/
Traceback (most recent call last):
File "/data/data/com.termux/files/home/webapps/django/Bloom/Bloom/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/data/data/com.termux/files/home/webapps/django/Bloom/Bloom/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/data/data/com.termux/files/home/webapps/django/Bloom/Bloom/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/data/data/com.termux/files/home/webapps/django/Bloom/accounts/views.py", line 118, in activate
user = User.objects.get(id=uid)
AttributeError: 'str' object has no attribute 'objects'
I am using Django 3.0.7 and the function I think orchestrated this error is:
def client_sign_up(request):
msg = 'Input your credentials'
if request.method == "POST":
form = ClientSignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db()
user.profile.birth_date = form.cleaned_data.get('birth_date')
# user can't login until link confirmed
user.is_active = False
user.save()
current_site = get_current_site(request)
subject = 'Please Activate Your Account'
# load a template like get_template()
# and calls its render() method immediately.
message = render_to_string('accounts/activation_request.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
# method will generate a hash value with user related data
'token': account_activation_token.make_token(user),
})
user.email_user(subject, message)
username = form.cleaned_data.get("username")
raw_password = form.cleaned_data.get("password1")
user = authenticate(username=username, password=raw_password)
return redirect("accounts:activation_sent")
else:
msg = 'Form is not valid'
else:
form = ClientSignUpForm()
context = {
"form": form,
"msg": msg,
"section": "signup"
}
return render(request, "accounts/register.html", context)
And, particularly:
def activate(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = User.objects.get(id=uid)
except (TypeError, ValueError, OverflowError):
user = None
# checking if the user exists, if the token is valid.
if user is not None and account_activation_token.check_token(user, token):
# if valid set active true
user.is_active = True
# set signup_confirmation true
user.profile.email_confirmed = True
user.save()
return redirect('accounts:client_signin')
else:
return render(request, 'accounts/activation_invalid.html')
I am also using a custom user model and my imports look like this:
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.conf import settings
from django.forms.utils import ErrorList
from django.http import HttpResponse
from .forms import ClientLoginForm, ClientSignUpForm
# Create your views here.
from django.views.generic import CreateView
from django.utils.encoding import force_text
from django.contrib.sites.shortcuts import get_current_site
from django.utils.http import urlsafe_base64_decode
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from django.template.loader import render_to_string
from .tokens import account_activation_token
User = settings.AUTH_USER_MODEL
I have tried changing the user = User.objects.get(id=uid) in line 118, the source of the error according to the error message, to user=User.objects.get(ok=uid) and googling, but none helped. I need you to help fix it please.
However, looking at my imports again, I discovered that:
from django.conf import settings
.
.
.
User = settings.AUTH_USER_MODEL
gives a string.
Changing it to:
from .models import User
fixed it.
Thanks everyone.
I upgraded my project from Django 1.11 to 2.2, made all the changes but came with new error that says login() got an unexpected keyword argument 'template_name'.It worked fine with the previous version of Django 1.11 (All the other urls are working, only the landing page gives the error). I couldn't find any references to this issue. Below is the error and urls and views for the issue.
Internal Server Error: /
Traceback (most recent call last):
File "C:\Users\User\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\User\venv\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\User\venv\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\User\PycharmProjects\MyWebsite\landing\views.py", line 43, in landing_validation
login_response = login(request, template_name='landing.html')
TypeError: login() got an unexpected keyword argument 'template_name'
[19/Apr/2019 16:20:00] "GET / HTTP/1.1" 500 71948
Landing\urls.py
from django.conf.urls import url
from landing.views import landing_validation
app_name='landing'
urlpatterns = [
url(r'^$', landing_validation, name='landing')
]
Landing\views.py
from django.contrib.auth import login
def landing_validation(request):
login_response = login(request, template_name='landing.html')
return login_response
C:\Users\User\venv\Lib\site-packages\django\contrib\auth__init__.py
def login(request, user, backend=None):
"""
Persist a user id and a backend in the request. This way a user doesn't
have to reauthenticate on every request. Note that data set during
the anonymous session is retained when the user logs in.
"""
session_auth_hash = ''
if user is None:
user = request.user
if hasattr(user, 'get_session_auth_hash'):
session_auth_hash = user.get_session_auth_hash()
if SESSION_KEY in request.session:
if _get_user_session_key(request) != user.pk or (
session_auth_hash and
not constant_time_compare(request.session.get(HASH_SESSION_KEY, ''), session_auth_hash)):
# To avoid reusing another user's session, create a new, empty
# session if the existing session corresponds to a different
# authenticated user.
request.session.flush()
else:
request.session.cycle_key()
try:
backend = backend or user.backend
except AttributeError:
backends = _get_backends(return_tuples=True)
if len(backends) == 1:
_, backend = backends[0]
else:
raise ValueError(
'You have multiple authentication backends configured and '
'therefore must provide the `backend` argument or set the '
'`backend` attribute on the user.'
)
else:
if not isinstance(backend, str):
raise TypeError('backend must be a dotted import path string (got %r).' % backend)
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
request.session[BACKEND_SESSION_KEY] = backend
request.session[HASH_SESSION_KEY] = session_auth_hash
if hasattr(request, 'user'):
request.user = user
rotate_token(request)
user_logged_in.send(sender=user.__class__, request=request, user=user)
There was no need to do a landing_validation view this line solved the issue.
url(r'^$', LoginView.as_view(template_name='landing.html'), name='landing')
In Django 2.2 app I fixed similar error by using LoginView instead of login.
File users/urls.py:
from django.conf.urls import url
# from django.contrib.auth.views import login
from django.contrib.auth.views import LoginView
from . import views
app_name = 'users'
urlpatterns = [
# url(r'^login/$', login, {'template_name': 'users/login.html'}, name='login'),
url(r'^login/$', LoginView.as_view(template_name='users/login.html'), name='login'),
]
The login function that you're using is not actually a view. It's just a regular function which you can use to authenticate a user and set the session cookie, etc.
Read the docs for it's usage: https://docs.djangoproject.com/en/2.2/topics/auth/default/#django.contrib.auth.login
Judging by your code, it appears you want to use LoginView.
from django.contrib.auth.views import LoginView
def landing_validation(request):
login_response = LoginView.as_view()(request, template_name='landing.html')
return login_response
You can see that django.contrib.auth.login takes request, user, and an optional backend. There is no template_name. This hasn't changed recently, so I think you would get the same problem in 1.11, too.
It looks like you want a view function, but django.contrib.auth.login is not that. It doesn't return a response.
I am trying to use graphQL queries in django. Basically I have two apps, my 'api' app which contains everything I need to make the queries and another one called 'frontend' from which I call the api to use these queries.
I can use the GraphQL view to type queries in it and it works perfectly, but whenever I try to make the query, I get this: "OrderedDict([('users', None)])"
Result of my query in the GraphQl view
The code:
In 'api' my schema.py:
import graphene
import graphql_jwt
from graphene import relay, ObjectType, AbstractType, List, String, Field,InputObjectType
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
from datetime import date, datetime
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
....
class Query(graphene.ObjectType):
me = graphene.Field(UserType)
users = graphene.List(UserType)
profile = relay.Node.Field(ProfileNode)
all_profiles = DjangoFilterConnectionField(ProfileNode)
def resolve_users(self, info):
### Returns all users ###
user = info.context.user
if user.is_anonymous:
raise Exception('Not logged!')
if not user.is_superuser:
raise Exception('premission denied')
return User.objects.all()
def resolve_me(self, info):
### Returns logged user ###
user = info.context.user
if user.is_anonymous:
raise Exception('Not logged!')
return user
def resolve_all_profiles(self, info, **kwargs):
### Returns all profiles ###
return Profile.objects.all()
.....
def execute(my_query):
schema = graphene.Schema(query=Query)
return schema.execute(my_query)
And the views.py that calls the app 'api' in my app frontend:
from django.shortcuts import render
import graphene
from api import schema
from django.contrib.auth import authenticate
def accueil(request):
if request.user.is_authenticated:
check = "I am logged"
else:
check = "I am not logged"
result = schema.execute("""query {
users {
id
username
}
}""")
return render(request, 'frontend/accueil.html', {'result' : result.data, 'check' : check})
The template :
<h1>OTC</h1>
<p> the users are : {{result}}</p>
<br/>
<p>{{check}}</p>
login
logout
and finally:
The web page result
and the error in the console:
An error occurred while resolving field Query.users
Traceback (most recent call last):
File "/home/victor/myenv/lib/python3.5/site-packages/graphql/execution/executor.py", line 311, in resolve_or_error
return executor.execute(resolve_fn, source, info, **args)
File "/home/victor/myenv/lib/python3.5/site-packages/graphql/execution/executors/sync.py", line 7, in execute
return fn(*args, **kwargs)
File "/home/victor/poc2/poc2/api/schema.py", line 67, in resolve_users
user = info.context.user
AttributeError: 'NoneType' object has no attribute 'user'
Traceback (most recent call last):
File "/home/victor/myenv/lib/python3.5/site-packages/graphql/execution/executor.py", line 330, in complete_value_catching_error
exe_context, return_type, field_asts, info, result)
File "/home/victor/myenv/lib/python3.5/site-packages/graphql/execution/executor.py", line 383, in complete_value
raise GraphQLLocatedError(field_asts, original_error=result)
graphql.error.located_error.GraphQLLocatedError: 'NoneType' object has no attribute 'user'
Unless you're writing a test client, you probably should not be calling schema.execute from inside a Django view. But assuming that you have your reasons for doing this, your specific problem is that you're not passing the user when you invoke schema.execute in accueil view.
Have a look at the execute documentation and you'll see that you'll need to supply an optional argument for the context. Your code is not supplying a context, hence the info.context is None, as per your exception. Unfortunately, the example
result = schema.execute('{ name }', context_value={'name': 'Syrus'})
is not Django-specific. But I think what works in a Django functional view is:
result = schema.execute(query, context_value=request)
I'm using python-social-auth in my Django application for authentication via Facebook.
But when a user tries to login, they have been redirected to the Facebook app page, and they click on the "Cancel" button, the following exception appears:
ERROR 2014-01-03 15:32:15,308 base :: Internal Server Error: /complete/facebook/
Traceback (most recent call last):
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 57, in wrapped_view
return view_func(*args, **kwargs)
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/social/apps/django_app/utils.py", line 45, in wrapper
return func(request, backend, *args, **kwargs)
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/social/apps/django_app/views.py", line 21, in complete
redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs)
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/social/actions.py", line 54, in do_complete
*args, **kwargs)
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/social/strategies/base.py", line 62, in complete
return self.backend.auth_complete(*args, **kwargs)
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/social/backends/facebook.py", line 63, in auth_complete
self.process_error(self.data)
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/social/backends/facebook.py", line 56, in process_error
super(FacebookOAuth2, self).process_error(data)
File "/home/vera/virtualenv/myapp/local/lib/python2.7/site-packages/social/backends/oauth.py", line 312, in process_error
raise AuthCanceled(self, data.get('error_description', ''))
AuthCanceled: Authentication process canceled
Is the any way to catch it Django?
python-social-auth is a newer, derived version of django-social-auth.
AlexYar's answer can be slightly modified to work with python-social-auth by modify settings.py with following changes:
Add a middleware to handle the SocialAuthException
MIDDLEWARE_CLASSES += (
'social.apps.django_app.middleware.SocialAuthExceptionMiddleware',
)
URL to redirect to, when an exception occurred
SOCIAL_AUTH_LOGIN_ERROR_URL = '/'
Note that you also need to set
DEBUG = False
That's all or read http://python-social-auth.readthedocs.org/en/latest/configuration/django.html#exceptions-middleware
you can create a middleware and catch any exceptions,
exception list: https://github.com/omab/python-social-auth/blob/master/social/exceptions.py
in this case your AuthCanceled Exception.
middleware.py
from social.apps.django_app.middleware import SocialAuthExceptionMiddleware
from django.shortcuts import HttpResponse
from social import exceptions as social_exceptions
class SocialAuthExceptionMiddleware(SocialAuthExceptionMiddleware):
def process_exception(self, request, exception):
if hasattr(social_exceptions, 'AuthCanceled'):
return HttpResponse("I'm the Pony %s" % exception)
else:
raise exception
settings.py
MIDDLEWARE_CLASSES = (
.....
'pat_to_middleware.SocialAuthExceptionMiddleware',
)
This is slight modification of #Nicolas answer and this works for me.
middleware.py
from social.apps.django_app.middleware import SocialAuthExceptionMiddleware
from django.shortcuts import render
from social.exceptions import AuthCanceled
class SocialAuthExceptionMiddleware(SocialAuthExceptionMiddleware):
def process_exception(self, request, exception):
if type(exception) == AuthCanceled:
return render(request, "pysocial/authcancelled.html", {})
else:
pass
settings.py
MIDDLEWARE_CLASSES += (
'myapp.middleware.SocialAuthExceptionMiddleware',
)
The 2018 answer:
Add SocialAuthExceptionMiddleware middleware to your config:
MIDDLEWARE_CLASSES = [
...
'social_django.middleware.SocialAuthExceptionMiddleware',
]
Set SOCIAL_AUTH_LOGIN_ERROR_URL in your config:
SOCIAL_AUTH_LOGIN_ERROR_URL = '/login'
Now when you have DEBUG = False, your users will get redirected to your login page when they click cancel in social auth provider's page.
When DEBUG = True you will still see the error page in your browser during development.
Just add in
MIDDLEWARE_CLASSES = (
'social_auth.middleware.SocialAuthExceptionMiddleware',
)
and something like
LOGIN_ERROR_URL = '/'
That's all
or read http://django-social-auth.readthedocs.org/en/latest/configuration.html#exceptions-middleware
If you don't care about handling the exception do the following in your settings.py
SOCIAL_AUTH_RAISE_EXCEPTIONS = False
See this answer: How to solve Authentication process canceled error?
This is a updated imports middleware using social_django
from social_django.middleware import SocialAuthExceptionMiddleware
from social_core import exceptions as social_exceptions
from django.shortcuts import HttpResponse
from django.shortcuts import render, redirect
class FacebookAuthCanceledExceptionMiddleware(SocialAuthExceptionMiddleware):
def process_exception(self, request, exception):
if hasattr(social_exceptions, 'AuthCanceled'):
return redirect('auth_login')
else:
raise exception