How to disable intermediate signout page in Django allauth - django

How to disable the intermediate signout page from django allauth. When the user clicks on the signout link on my site I want him to logout right away, I want to remove this intermediate page

Set ACCOUNT_LOGOUT_ON_GET to True in your settings.
Also see the documentation

Using a GET request is probably a bad idea due to browsers prefetching urls from the URL bar. Chrome (as of right now) is pretty bad for this; it'll send a GET request to pages it think you'll hit enter on when typing in your URL bar.
Plus, people can add a link such as <img src="https://example.com/account/logout/"> and you'll be logged out. That's not a security risk since it's logging you out, but it is certainly annoying for your users.
Instead, you should consider using a POST request using a form with CSRF. Django Allauth already comes with this. Here's the <form> from the intermediate signout page:
<form method="post" action="{% url 'account_logout' %}">
{% csrf_token %}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/>
{% endif %}
<button class="STYLE_ME" type="submit">Logout</button>
</form>
In my case, I just added this to the site header and made the submit <button> look like every other link using CSS so it feels the same to them, but the form will use a POST request.
But if that's not a solution you can implement for any reason, open your settings.py file (or your main settings file) and set:
ACCOUNT_LOGOUT_ON_GET = True
^ The above setting will do what you need. For further Django Allauth settings, check out their configuration page.

Here's another shortcut for preserving the POST request, if you don't want to mess with styling the form button with something like this:
Hide the form:
<form style='display: none;' method="post" action="{% url 'account_logout' %}">
{% csrf_token %}
<input type="hidden" name="next" value="/redirect_target/"/>
<button id="signOutBtn" type="submit">Logout</button>
</form>
Submit with a click event attached to whatever element you've already styled:
$(document).on('click', '#signOutLink', function() {
$('#signOutBtn').click()
});

Related

Django - What happens when a csrf_token is NOT re-submitted to the server?

Hello, Everybody.
I was wondering about... What happens when a csrf_token is submitted by the server-side application to the browser in an HTML form, and that form was not submitted with the post by the browser?
Because I was thinking... Django makes the csrf_token and relates it to the user or to the session, I am not sure, to check it when it comes back. And then I think it deletes it, right? So what if it wasn't back?
Will it stay there waiting until the session ends or It is a mistake that causes vulnerability or what?
For Example, I want to make a form for Comments under the details of the object. But it is not a must to comment. You can comment if you need, and you can do not so. So I put a form like this under those details :
<div class="container">
<!-- Here is the object data -->
</div>
<div class="container comments">
<ul>
<li>
<form action="{% url 'ads:newcomment' %}" method="POST">
{% csrf_token %}
<input id="comment_txt" name="comment" type="text" value="Type a comment..." class="comment_txt"/>
</form>
</li>
{% for comment in comments %}
<li class="comment">{{comment}}</li>
{% endfor %}
</ul>
</div>
The CSRF token data lives in the request session or in the cookies depending on your settings.
When you do {% csrf_token %} the same token is put into a hidden field on your form so that it get's POSTed back to the server.
The server will just compare that it matches what it in the sesssion/cookie.
A similar thing is done for AJAX requests, but rather than including it in the body, it is part of the headers.
If you use CSRF_USE_SESSIONS = True or CSRF_COOKIE_HTTPONLY = True the token cannot be accessed via JavaScript so it's pretty safe.
The token itself is randomly generated and used throughout a user's session (i.e if they logout and login again a different token will be generated).
So to answer your question, if the form is not submitted nothing happens. The CSRF token will continue to exist in the session/cookies as long as the user is logged in.
Refer to the Django Docs for more details

Custom `password_reset_confirm.html` template won't redirect to `password_reset_complete` view

I made a custom password_reset_confirm.html template. But when a user enters a new password and hits submit, the browser does not redirect to the admin view password_reset_complete.
Here's the form I made in the custom password_reset_confirm.html template:
<div ng-app="app" ng-controller="Ctrl">
<form id="reset-pw-confirm-form" name="newPWForm" method="post" action="">
{% csrf_token %}
<input
id="id_new_password1"
type="[[[ newPW.showPW ? 'text' : 'password' ]]]"
name="new_password1"
ng-model="newPW.pw"
ng-minlength="8"
ng-maxlength="32"
required>
<button class="btn btn-primary" type="submit" ng-disabled="!newPW.pw">Submit</button>
<input
id="id_new_password2"
type="hidden"
value="[[[ newPW ]]]"
name="new_password2"
ng-model="newPW"
ng-minlength="8"
ng-maxlength="32"
required>
</form>
</div>
When I fill out the password and hit submit, the browser sends a POST request to the same URL it landed on, but the page seems to just refresh with nothing changed. The user's password remains unchanged. It seems Django's auth/views.py did not execute properly.
In that view, there's this code:
if post_reset_redirect is None:
post_reset_redirect = reverse('password_reset_complete')
else:
post_reset_redirect = resolve_url(post_reset_redirect)
When I have the view print post_reset_redirect, it prints None. Could this be the issue?
How can I make my custom template compatible with Django's password_reset_confirm view?
When you specifies "action" attribute for the form it will be used as your link for data sending so probably your logic isn't handled. Try to remove it and check you js files that the data is sent to the the specified link.
Also please check all required parameters for the password_reset_confirm
https://docs.djangoproject.com/en/1.8/_modules/django/contrib/auth/views/
My hidden input's value and ng-model attributes needed to be set to newPW.pw.

How to send data from django template to views method in post request or in a way data is not visible in the URL

I have a django template which has multiple <a> tags.
<a class="label label-success" href="get_status/?token={{book.token}}">Update</a>
On click of it, a method from views is called where I can access the token from the url as
tkn = request.GET.get('token')
But now I want not to send the token in the url.
I searched for this and get to know about forms but I did not clearly understand them. Can anyone please help here.
For future ref: I created a form and added a hidden input field in it.
on click of submit button it will send the token value.
<form action="get_Status/" method="post">
{% csrf_token %}
{{ form }}
<input type="hidden" name="book_token" value="{{book.token}}">
<input type="submit" class="submit_btn btn label-success" value="Update" />
</form>
Ans in the views.py
book_token=request.POST.get("book_token"," ")
You can use the basic HTML form concept here.
Please check the link:
How to submit a form with JavaScript by clicking a link?
Use javascript/Jquery to submit the form.
Insert the token value in a hidden field and use form to submit it to views.
Then in the views,you can get the value as :request.POST['token']

Django Form Submission Error

I have this recurring problem with form submission in Django, and the frustrating part is that I'm not sure how to interpret what's happening. Essentially I have different pages with form submissions on them. Some of them work as following
localhost/page/formpage--> localhost/page/receivingpage
which is what I expect. Othertimes, it goes to a page like this
localhost/page/formpage--> localhost/page/formpage/recevingpage
and the screen shows a blank form page, which is not what I expect. I'm not sure how to interpret this, and I'm not sure where to look for errors in my code. I think I don't fully understand what's going on when I submit a form, how does it generate a URL after I press 'submit'?
Edit: here is my html form:
<!DOCTYPE HTML>
<html>
<div>
<p>Entry Form</p>
<form action= "user" method="post" >
{% csrf_token %}
<p><label for="id_username">Username:</label>
<input id="id_username" type="text" name="username"" /></p>
<p><label for="id_password">Password</label>
<input type="password" name="password" id="id_password" /></p>
<input type="submit" value="Submit" />
</form>
</div>
</html>
I suspect it isn't the form, I have it on another application and it works... the trouble is I don't know if it's the view, the template, or w/e, so I'll update the post with info as people request it.
I'd recommend putting in an action using the url template tag. With that, you will know for certain where the form is going to end up:
<form action="{% url 'user-url-name' %}" method="post">
The url tag will be an absolute url. Without this, you're going to end up at a relative url depending on where in your application the user submits the form, which can be quite confusing during development and not entirely correct.
Using {% url %} tag is the proper way to do. Your problem can also be solved by adding a forward slash / to the action attribute like this:
<form action="/user" method="post" >
Hope this helps!

How to properly use the django built-in login view

I'm just getting started with Django, and I'm trying to use built-in features as much as possible. As such, for user login, I'm using the built-in login view, and assigning it to the base url of my site:
urlpatterns=patterns('django.contrib.auth.views',
url(r'^/$','login',{'template':'mytemplate.html'}),
mytemplate.html looks something like this:
<!DOCTYPE html>
<html>
<body>
{%if form.errors %}
<p> Invalid username/password combination, please try again </p>
{% endif %}
<h1>Welcome to My Site!</h1>
<form action="{% url django.contrib.auth.views.login %}" method="post">
{% csrf_token %}
{{form.username.label_tag}}{{form.username}}
{{form.password.label_tag}}{{form.password}}
<input type="submit" id="submit" name="submit" value="Sign in" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
forgot username/password<br />
new user
</body>
</html>
my problem is, the template doesn't appear to be getting passed any of the context it's supposed to. In the rendered HTML, all of my variable tags simply disappear (i.e. rather than being replaced by the appropriate values, thay are replaced with nothing).
I imagine I'm skipping some critical step, but I can't figure out what it is. Any ideas?
You need to change from 'template' to 'template_name'
urlpatterns=patterns('django.contrib.auth.views',
url(r'^/$','login',{'template_name':'mytemplate.html'}),
https://docs.djangoproject.com/en/1.4/topics/auth/#django.contrib.auth.views.login
Try removing the template name from your url configuration. Django will then fall back to a standard template, that way you can see if you screwed up the template somehow or if something else is wrong.
My next guess would be to check your settings for the TEMPLATE_CONTEXT_PROCESSORS. If you have defined any of them, be sure to include
"django.contrib.auth.context_processors.auth",
If you haven't defined any, django will use a standard tuple, which allready includes the auth processor.