Implement Forgot Password/Email Verification django rest with ReactJS - python

I want to implement forgot password or email verification with django and react,
To implement forgot password I used django rest auth.Here below urls are:
url(
r'^rest-auth/password/reset/$',
PasswordResetView.as_view(),
name='password_reset',
),
url(
r'^rest-auth/password/reset/confirm/'
r'(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
PasswordResetConfirmView.as_view(),
name='password_reset_confirm'),
I have successfully hit the request to first url from my react js front end,and I also received the email with token and uid, but the link redirects me to django rest native UI however I want to be in react framework UI.
So how can I implement this? is there any suitable way to implement forgot password with react and django as it is not done by django rest auth because the flow of react front end disturbs.

So in order to obtain a token from verification link you could use a lib like query-string. Basically you pass location and go on from there, documentation is pretty reach so you should have no problem.

Related

csrf token using decorator is not working in Django DeleteView [duplicate]

I'm really stuck. Here's what I'm trying to do.
KEEP CSRF On. - please don't tell me to turn it off.
I have an API app run by Django and Django Rest Framework
I have a frontend app run by Vue
I have installed django-cors-headers to manage CORS
Everything works great localy. As soon as I move it to production, I start getting CSRF errors. Here's how everything works.
I've seen answers all over that have said everything from turning off CSRF to allowing all for all the things. I want to do this right and not just shut things off and open everything up and end up with a security hole.
So, here's what I have.
Installed:
django-cors-headers
django-rest-framework
drf-nested-routers
... and others
I have the api running at api.websitename.com and the Vue.js app is running at websitename.com.
GET requests work great.
OPTION requests seem to work.
Any risky request does not work.
For my CORS I have 'corsheaders.middleware.CorsMiddleware', installed before my other MIDDLEWARE.
Then my CORS settings are:
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
'*.websitename.com',
)
And my CSRF settings are:
CSRF_TRUSTED_ORIGINS = [
"api.websitename.com",
]
No matter how I play with these, I end up with a CSRF token error.
I've tried the approach of doing something like this in my Vue App.vue file:
mounted () {
this.getCSRFToken()
},
methods: {
getCSRFToken () {
return axios.get('token/').then(response => {
axios.defaults.headers.common['x-csrftoken'] = Cookies.get('csrftoken')
}).catch(error => {
return Promise.reject(error.response.data)
})
}
}
The idea being that I get a CSRF token as soon as the APP loads in the browser. But even with that, I'm getting failed CSRF token errors when the app tries to do anything except a GET or OPTION.
Here's the view that returns the token incase youre curios:
class CSRFTokenView(APIView):
permission_classes = (permissions.AllowAny,)
#method_decorator(ensure_csrf_cookie)
def get(self, request):
return HttpResponse()
I realize I might be mixing problems here, but any suggestions that could help me trouble shoot this are welcome.
First of all you want to use SessionAuthentication:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
)
}
This will enforce CSRF, except for anonymous users (more on this in a bit). For browser frontends the easiest solution is to have both the (browser) frontend and backend under the same domain - this lets you avoid CORS - as suggested by comments above. If you have other clients then just go with tokens (DRF tokens or JWT) - but these are not safe for browser usage due to the danger of XSS attacks (storing tokens in localStorage is inherently insecure).
As you are using axios, CSRF setup is dead easy:
import axios from 'axios'
axios.defaults.xsrfHeaderName = 'X-CSRFToken'
axios.defaults.xsrfCookieName = 'csrftoken'
So you should have safe sessions with CSRF enforced. Almost. To quote the linked page above:
Warning: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.
CSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.
This is icky - you either have to just use Django server-side views which makes your SPA design somewhat more complicated or recreate login and other auth views in DRF, with the caveat of using the #csrf_protect method decorator to enforce CSRF on these "anonymous" views. Obviously such views will break for token-using clients so you probably want to use different endpoints for these (maybe re-using the same base classes). So your browser login uses /auth/browser/login/ and your mobile login /auth/mobile/login/, the former wrapped using #csrf_protect.
Recreating login and other auth views from scratch should be done carefully after studying the contrib auth source code; for vanilla requirements I would recommend pre-existing solutions like django-rest-auth and django-all-auth. The django-rest-auth package however is not well designed for browser frontends and forces the usage of token generation, plus you would need to wrap the views as described above. On the other hand, all-auth provides AJAX responses for JS clients and might be a better bet.
By far the easiest way to resolve this is to serve everything from the same domain. You can have your CDN or proxy direct /api calls to one server and the rest to the frontend server. This way there is no need to worry about CORS at all.
To get this working, I think you're just missing withCredentials = true in AXIOS configuration. Django requires the CSRF cookie to be sent and cookies are not sent over cross origin requests when withCredentials is not set.
axios.interceptors.request.use(function (config) {
config.withCredentials = true
return config
})
Another setting that might be missing is Djano's SESSION_COOKIE_DOMAIN. You should set it like this:
SESSION_COOKIE_DOMAIN=".mywebsite.com"
That first dot is important because it tells Django and then the web browser to use the cookie for *.mywebsite.com including api.mywebsite.com.
If it all still fails, I suggest setting a breakpoint on Django's CSRF middleware to see what's missing to make it work.

django register user with django-facebook

Ok I see everyone saying use django-facebook, and it says it can do everything I want.
I have it installed on my app and the example page works, but how do I actually register a user with it?
Apart from the installation all the rest of the docs seem autogenerated and I have yet to find a step by step guide as to how to register a user on my site using django-facebook.
Here is a working example of facebook auth with django.
Facebook uses OAuth2 to federate user logins. An OAuth2 authorization step-by-step consists of
Create an authorization token by calling the request-token url with your consumer keys
Send the user to the authorize url with the token that you created and a callback url
Once authorized the user will be redirected to your callback url with an auth-token
Convert the auth-token to an access token at the request-token url
Save the access token and use it to make authorized requests

python-social-auth and github, I have this error "The redirect_uri MUST match the registered callback URL for this application"

I'm using python-social-auth on a project to authenticate the user with Github.
I need to redirect the user depending on the link they use. To do that I'm using the next attribute on the url, and I didn't declare any redirect url on my github app neither in my django settings.
This is the href attribute I'm using for my link : {% url 'social:begin' 'github' %}?next={% url 'apply' j.slug %}
And the first time I click on it, I'm getting redirected to my homepage with this error in the url field : http://127.0.0.1:8000/?error=redirect_uri_mismatch&error_description=The+redirect_uri+MUST+match+the+registered+callback+URL+for+this+application.&error_uri=https%3A%2F%2Fdeveloper.github.com%2Fv3%2Foauth%2F%23redirect-uri-mismatch&state=Ui1EOKTHDhOkNJESI5RTjOCDEIdfFunt
But after first time the link work.
I don't know where is the problem, I hope someone can help me. Thanks
This library uses OAuth for GitHub authentication.
You must provide a callback URL, because the OAuth process causes the user's browser to actually leave your site as part of the authentication process. The callback URL that you send to GitHub is used to redirect users back to your site.
It looks like Python Social Auth handles some of this for you, though (emphasis mine):
GitHub
Github works similar to Facebook (OAuth).
Register a new application at GitHub Developers, set the callback URL to http://example.com/complete/github/ replacing example.com with your domain.
Fill App Id and App Secret values in the settings:
SOCIAL_AUTH_GITHUB_KEY = ''
SOCIAL_AUTH_GITHUB_SECRET = ''
Also it’s possible to define extra permissions with:
SOCIAL_AUTH_GITHUB_SCOPE = [...]
The tricky bit is getting this to work on your development machine.
Setting your domain to 127.0.0.1 in your hosts file should work, something like this
127.0.0.1 example.com
but make sure to comment this like out once you move into production!
You may also want to browse GitHub's OAuth documentation. Using a library is great, but if you understand the underlying technology you'll have fewer problems.
I did solve the login redirect URI mismatch by just using http://127.0.0.1:8000/
The problem has to do with the way you've configured the urls.py locally. If you have
path('social/', include('social_django.urls', namespace='social')),
then your Authorization callback URL should be
http://localhost/social/complete/github/

How to use Django's #csrf_exempt decorator to enable an API to do PUT?

I'm building a Django application with Django-Rest-Framework APIs. I have built an API endpoint as shown below.
I want to be able to POST data from my browser. I want this POST operation to retrieve an object model from my Database that has the matching primary key as given in the URL. And I want to modify that retrieved object based on the data posted by the browser.
If I could just grab the posted data from with my ViewSet, I would be done. But when I try to execute that viewset's update() function, I get a CSRF error.
From my urls.py file:
router.register(r'replyComment', views.ReplyComment, base_name="replyComment")
From my views.py file:
class ReplyComment(viewsets.ViewSet):
def update(self,request,pk=None):
try:
origComment = Comment.objects.get(pk=pk)
# Do something here that modifies the state of origComment and saves it.
return Response(
json.dumps(True),
status=status.HTTP_200_OK,
)
except Exception as exception:
logger.error(exception)
return Response(status=status.HTTP_400_BAD_REQUEST)
I'm using the Advanced Rest Client (ARC) tool in my Chrome browser. When I point the ARC tool to http://127.0.0.1:3001/api/replyComment/2/ using the POST method, I get the following error:
{
detail: "CSRF Failed: CSRF token missing or incorrect".
}
This doc indicates that I should use the #csrf_exempt decorator. I put that decorator on my update() function above. But it seemed to make no difference.
What changes do I need to make to ensure my POST works as I intend it to?
It is highly recommended NOT to disable CSRF protection for session authentication. Doing so will make your app vulnerable to attacks. For the API, DRF enforces CSRF protection only for session authentication. If you use another authentication backend(Basic, Auth Token or OAuth) it will work with out asking for CSRF tokens since CSRF attacks happen only in browsers. Now if your API is going to be used by non-browser clients, you can enable one of the other auth backends. For example, Using Basic auth:
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
),
And enable basic auth in ARC.

Django request.user is empty

Using django, I am authenticating the user through Google. I get the initial request tokens & redirect the user to google for auth. After which google redirects the user back to my website (using the redirect_url I provide).
At this point the request.user.id is None so is request.user.username why is this happening? I need the user ID to enter the access_tokens (that google sends me) into the DB.
Under what conditions can request.user object in Django be empty?
UPDATE1: When I get redirected back from Google with the url pattern as http://mywebsite.com/lserv?s=goog control comes back to my django views function, but django gives me the request.user object user as Anonymous user with no username or id. why?
UPDATE2:
all this is running on python manage.py runserver for now...
UPDATE3: Anybody faced anythn similar to this? basically, out of no reason the user in request clears out automatically & I get assigned as Anonymous user. All this happens between url requests from the user (from browser). Why?
Django's auth mechanism has nothing to do with Google's or any other auth service. If you want to integrate third party auth service with your Django site, you should do it youself.
If you're using oauth2 library, it's README has a section named "Logging into Django w/ Twitter" may help you.
If you are using oauth api from google. To get the user you have to do something like this
from google.appengine.api import oauth
# ...
try:
# Get the db.User that represents the user on whose behalf the
# consumer is making this request.
user = oauth.get_current_user()
except oauth.OAuthRequestError, e:
# The request was not a valid OAuth request.
# ...

Categories

Resources