Django dj-rest-auth (django-allauth) redirection doesn't work, however, LOGIN_REDIRECT_URL is set - django

I'm using Django 4.1 (Djoser doesn't work with 4.x) and dj-rest-auth (if I'm not mistaken, registration is provided by django-allauth module). What am I trying to achieve is getting new user to a profile creation page ('/api/v1/new_hero/' endpoint), right after he signs up. Without any email verification, just right into it. But for now, with all theese settings, after registration, django keeps the user on the same ('auth/registration/') page with tokens demonstration and other stuff. By the way, situation keeps similar with loginning. How am I supposed to direct the user to a target page?
settings.py:
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
REST_USE_JWT = True
JWT_AUTH_COOKIE = 'jwt-auth'
SITE_ID = 1
LOGIN_REDIRECT_URL = '/api/v1/new_hero/'
ACCOUNT_SIGNUP_REDIRECT_URL = '/api/v1/new_hero/'
ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = True
ACCOUNT_EMAIL_VERIFICATION = 'none'
urls.py
urlpatterns = [
re_path(r'^docs(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
re_path(r'^docs/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
re_path(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),
path('api/v1/', include('items.urls')),
path('auth/', include('dj_rest_auth.urls')),
path('auth/registration/', include('dj_rest_auth.registration.urls')),
]
items/urls.py
urlpatterns = [
path('items/', ItemsListCreateView.as_view(), name='list_items'),
path('items/<int:pk>/', ItemDetailView.as_view(), name='update_item'),
path('heroes/', HeroListView.as_view(), name='list_heroes'),
path('new_hero/', HeroCreateView.as_view(), name='create_hero'),
path('heroes/<int:pk>/', HeroDetailView.as_view(), name='update_hero'),
path('classes/', HeroClassListCreateView.as_view(), name='list_classes'),
path('weapons/', WeaponClassListCreateView.as_view(), name='list_weapons'),
# path('reg/', Registration.as_view(), name='custom_registration'),
]
I tryied different django-allauth settings, checked correctness of INSTALLED_APPS, AUTHENTICATION_BACKENDS and other sections of settings.py, and it all end up here, with me writing a question.

Related

How to fix dj-rest-auth sending invalid password rest links

In my Django Rest Framework, the users request to reset the password and when the email is received everytime the link is clicked it shows a message Password reset unsuccessful The password reset link was invalid, possibly because it has already been used. Please request a new password reset.
here is what I have tried API urls.py
app_name = 'api'
router = routers.DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
urlpatterns = [
path('', include(router.urls)),
path('dj-rest-auth/', include('dj_rest_auth.urls')),
path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')),
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
# path('password_reset/',PasswordResetView.as_view(), name='password_reset'),
# path('password_reset_confirm/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
]
here is the users app urls.py if required:
app_name = 'users'
urlpatterns = [
path('password-reset/', auth_views.PasswordResetView.as_view(template_name='users/password_reset.html', success_url=reverse_lazy('users:password_reset_done')), name='password_reset'),
path('password-reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='users/password_reset_done.html'),name='password_reset_done'),
path('password-reset-confirm/<uidb64>/<token>/',auth_views.PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html',success_url=reverse_lazy('users:password_reset_done'),post_reset_login=True),name='password_reset_confirm',),
path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'),name='password_reset_complete'),
]
My question is: Why do I keep receiving invalid links and how can I fix it?
In different questions I got answers to add the commented paths but still did not work. Any suggestions on how to fix it ?

Django, mozilla-django-oidc and admin

i am trying to connect Okta with a custom Django (v.3.0.2) app i am coding, using the mozilla-django-oidc library. So far the initial user authentication and account creation (using Django's user model) works, but i don't understand what i need to do to have the Django AdminSite work.
The Adminsite, before introducing mozilla-django-oidc worked as expected. I created an admin user, named "admin" and the user was able to login.
To integrate the mozilla-django-oidc library i followed the instructions here: https://mozilla-django-oidc.readthedocs.io/en/stable/installation.html. The instructions do not have any specific mention of the AdminSite.
When i access the AdminSite after the library integration, i have the following:
The AdminSite uses the default template - my assumption was that it
would also use Okta to authenticate.
The admin account "admin" that used to be able to login into the AdminSite does not work anymore
My goal is to be able to access the AdminSite. I don't mind if it will be over Okta or over the vanilla interface as long as i can access it.
Below are the relevant segments from the files (in order to integrate):
urls.py
urlpatterns = [
path('', static_site.site_index, name='site_index'),
path('admin/', admin.site.urls),
path('review/', include('review.urls')),
path('oidc/', include('mozilla_django_oidc.urls')),
]
settings.py
# OICD
AUTHENTICATION_BACKENDS = (
'mozilla_django_oidc.auth.OIDCAuthenticationBackend',
)
OIDC_RP_CLIENT_ID = 'xxxxx'
OIDC_RP_CLIENT_SECRET = 'xxxx'
OIDC_RP_SIGN_ALGO = 'RS256'
OIDC_OP_JWKS_ENDPOINT = 'https://dev-xxx.okta.com/oauth2/default/v1/keys'
OIDC_RP_SCOPES = 'openid email profile'
OIDC_OP_AUTHORIZATION_ENDPOINT = 'https://dev-xxx.okta.com/oauth2/default/v1/authorize'
OIDC_OP_TOKEN_ENDPOINT = 'https://dev-xxx.okta.com/oauth2/default/v1/token'
OIDC_OP_USER_ENDPOINT = 'https://dev-xxx.okta.com/oauth2/default/v1/userinfo'
# Provided by mozilla-django-oidc
LOGIN_URL = reverse_lazy('oidc_authentication_callback')
# App urls
LOGIN_REDIRECT_URL = reverse_lazy('review:dashboard')
LOGOUT_REDIRECT_URL = reverse_lazy('site_index')
Any ideas or pointers welcomed!
The goal was achieved by adding the default auth backend to the settings:
settings.py
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'mozilla_django_oidc.auth.OIDCAuthenticationBackend',
]
I don't get Okta auth for the admin, but since i am happy just to have the admin running, i will stop here.
I've come up with a solution for using the mozilla-django-oidc login with the django admin. It's a little hacky but it's a lot less intimidating to redirect the admin login page than to override AdminSite.
In my top-level urls.py I have
class CustomLogin(View):
def get(self, request, **kwargs):
return HttpResponseRedirect(
reverse('oidc_authentication_init') + (
'?next={}'.format(request.GET['next']) if 'next' in request.GET else ''
)
)
urlpatterns = [
path('oidc/', include("mozilla_django_oidc.urls")),
path('admin/login/', CustomLogin.as_view()),
path('admin/', admin.site.urls),
# the rest of my urls...
]
If you don't care about passing the ?next= value correctly you can skip the CustomLogin class and do the following instead
urlpatterns = [
path('oidc/', include("mozilla_django_oidc.urls")),
]
# This only works if you break up urlpatterns so the reverse below can find what it needs
urlpatterns += [
path('admin/login/', RedirectView.as_view(
url=reverse('oidc_authentication_init') + ?next=/admin/,
permanent=False
)),
path('admin/', admin.site.urls),
# the rest of my urls...
]
I added ?next=/admin/ because by default once you log in you will be redirected to settings.LOGIN_REDIRECT_URL which I'm already using for something else
If you're using the default primary identifier, "email", you can create a superuser with that same email which will give SU privileges to that SSO user. So for example, if you have an SSOuser with email testuser#example.com, you can then run python manage.py createsuperuser and when prompted, set the email to testuser#example.com; the username and password don't matter since you're not actually using them for authentication (if you remove 'django.contrib.auth.backends.ModelBackend' from AUTHENTICATION_BACKENDS). I currently have this working, although I am extending the mozilla backend with the steps recommended in https://mozilla-django-oidc.readthedocs.io/en/stable/installation.html#connecting-oidc-user-identities-to-django-users to prevent users from being created on the fly.

Remove user endpoints in Django rest auth

I am using Django rest auth for user account handling. For updating user info i have created custom endpoints, So i don't need the djnago-rest-auth generated endpoints /rest-auth/user/ (GET, PUT, PATCH). How can i remove these endpoints?
urls.py
urlpatterns = [
path('', include("rest_auth.urls"), name="user-auth"),
path('register', include('rest_auth.registration.urls'), name="user-auth-registration"),
path('<uid>/', views.UserProfileView.as_view(), name="user-profile"),
]
Edit
I want to use all other urls of rest-auth like login, register, etc. But i just dont want the /rest-auth/user/ as described here.
#bodoubleu 's answer didn't work, So i added them manually.
from rest_auth.views import (
LoginView, LogoutView, PasswordChangeView,
PasswordResetView, PasswordResetConfirmView
)
urlpatterns = [
path('register', include('rest_auth.registration.urls'), name="user-auth-registration"),
path('login', LoginView.as_view(), name="user-login"),
path('logout', LogoutView.as_view(), name='user-logout'),
path('password/change/', PasswordChangeView.as_view(), name='rest_password_change'),
path('password/reset', PasswordResetView.as_view(), name='rest_password_reset'),
path('password/reset/confirm/', PasswordResetConfirmView.as_view(), name='rest_password_reset_confirm'),
path('<uid>/', views.UserProfileView.as_view(), name="user-profile"),
]
Untested but this should work.
urlpatterns = [
path('user/', django.views.defaults.page_not_found),
path('', include("rest_auth.urls"), name="user-auth"),
path('register', include('rest_auth.registration.urls'), name="user-auth-registration"),
path('<uid>/', views.UserProfileView.as_view(), name="user-profile"),
]
If not you can manually define all the rest_auth.urls in your url patterns

Reverse for 'account_email_verification_sent' not found. 'account_email_verification_sent' is not a valid view function or pattern name

I'm trying to use allauth and rest-auth in my project and try to use the built-in function in allauth to do email verification but this what I get :
and here is my code
settings.py
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_EMAIL_REQUIRED = True
urls.py
urlpatterns = [
re_path(r'^', include('rest_auth.urls')),
re_path(r'^registration/', include('rest_auth.registration.urls')),
]
I found the solution, that I have to add URL to be able to make a post request to the backend to send email then URL with regex which has the token that will verify the account and URLs and add URL for login with name account_login and URL for register with name account_signup and be like this :
from rest_auth.registration.views import VerifyEmailView, RegisterView
urlpatterns = [
path('', include('rest_auth.urls')),
path('login/', LoginView.as_view(), name='account_login'),
path('registration/', include('rest_auth.registration.urls')),
path('registration/', RegisterView.as_view(), name='account_signup'),
re_path(r'^account-confirm-email/', VerifyEmailView.as_view(),
name='account_email_verification_sent'),
re_path(r'^account-confirm-email/(?P<key>[-:\w]+)/$', VerifyEmailView.as_view(),
name='account_confirm_email'),
]
I had the same issue but I already had set up the URL for the email confirmation but I forgot about the name parameter it is mandatory
from django.conf.urls import url, include
from dj_rest_auth.registration.views import VerifyEmailView
urlpatterns = [
url('auth/', include('dj_rest_auth.urls')),
url('auth/registration/', include('dj_rest_auth.registration.urls')),
url('auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent'),
]
ยดยดยด

Django OAuth2 Error: invalid_client and client_id=None when client_id has been provided

I am using django-social-auth for google apps authentication for my django project. I obtained the client id and secret key from Google api console for my domain. And plugged in the values in my app as follows:
**settings.py**
MIDDLEWARE_CLASSES = (
'social_auth.middleware.SocialAuthExceptionMiddleware',
)
LOGIN_URL = '/login/google-oauth2/'
LOGIN_REDIRECT_URL = '/profile'
LOGIN_ERROR_URL = '/login-error/'
AUTHENTICATION_BACKENDS = (
'social_auth.backends.google.GoogleOAuth2Backend',
'django.contrib.auth.backends.ModelBackend',
)
TEMPLATE_CONTEXT_PROCESSORS = (
"django.contrib.auth.context_processors.auth",
"social_auth.context_processors.social_auth_by_type_backends",
)
SOCIAL_AUTH_ENABLED_BACKENDS = ('google',)
SOCIAL_AUTH_DEFAULT_USERNAME = 'new_social_auth_user'
GOOGLE_OAUTH2_CLIENT_ID = '***.apps.googleusercontent.com'
GOOGLE_OAUTH2_CLIENT_SECRET = '****'
GOOGLE_WHITE_LISTED_DOMAINS = ['127.0.0.1:8000']
SOCIAL_AUTH_COMPLETE_URL_NAME = 'socialauth_complete'
SOCIAL_AUTH_ASSOCIATE_URL_NAME = 'socialauth_associate_complete'
SOCIAL_AUTH_RAISE_EXCEPTIONS = False
SOCIAL_AUTH_PROCESS_EXCEPTIONS = 'social_auth.utils.log_exceptions_to_messages'
INSTALLED_APPS = (
'social_auth', )
...
**urls.py**
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.views.generic import TemplateView
from django.contrib.auth.views import logout
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'', include('social_auth.urls')),
url(r'^$', TemplateView.as_view(template_name="login.html")),
url(r'^logout/$', logout, {'next_page': '/'}, name='gauth_logout'),
url(r'^profile/$', TemplateView.as_view(template_name="profile.html")),
)
...
**login.html**
<p>Use your work email credentials to sign in to this application:
Sign In
</p>
The problem is that when I click on sign in I am redirected to the Error: Invalid_client page with the details:
Request Details
cookie_policy_enforce=false
scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile
response_type=code
redirect_uri=http://127.0.0.1:8000/complete/google-oauth2/
state=WZWyJgDRfeW4RneRynqSZ3nSy0Bzs0v6
client_id=None
https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile&state=WZWyJgDRfeW4RneRynqSZ3nSy0Bzs0v6&redirect_uri=http://127.0.0.1:8000/complete/google-oauth2/&response_type=code&client_id=None
Even though I have provided the correct client_id in my project, the page (and as can be seen from the url) says that it has not been provided. If I plug it manually in the url, I am redirected to the permissions page though.
Also when I accept the permissions I get an AuthCanceled at /complete/google-oauth2/ error. Is it that my project is not reading the social_auth settings correctly?
Any help would be appreciated. Thanks.
i was having the same problem just change
GOOGLE_OAUTH2_CLIENT_ID = '***.apps.googleusercontent.com'
GOOGLE_OAUTH2_CLIENT_SECRET = '****'
To
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '****.apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET ='****'
in the settings.py file