I have the django view to set the value in cookies 'no_show_dialog' when a user clicks 'Don't remind me anymore' in the modal dialog.
Now i changed that dialog completely and want to reset that cookie for all users, so they will have to see it again at least once.
I know there is a way to delete the cookie in a view for a particular user:
response.delete_cookie('no_show_dialog')
But how to loop over all users and remove that cookie once?
You can't do that. Cookies are stored on the client; the only time you have access to them is when the particular browser makes a request and receives the response.
The best thing to do here is to simply use a different name for the cookie from now on. This will ensure that no users will have it set initially. Alternatively you might consider using the session for future settings.
As Daniel said you cannot delete all cookies in response as they are stored on client side.
In Django you create a response object for a particular request object in your views. Which means that you can only delete a cookie for that particular request and not for all the requests that was served by your Django server.
What you can do here is set expiry time for a cookie by using max_age as keyword argument in set_cookie method For Example :
response = HttpResponse('your response')
response.set_cookie('user_id', user_id, max_age=30)
return response
This will expire the cookie after the specified time for every client.
Related
I have my api behind a third party OAuth (ex. google, twitter, etc). When a user hits /api/login, they are redirected into the OAuth flow and then sent back to my callback /api/login/callback. I store their login info and then send back a same-site http only session cookie to validate their user id. On subsequent requests, I retrieve that session cookie to get their user info and then perform requests using the OAuth token stored earlier.
Now, I want to create a frontend to go with my backend REST api. When a user goes to my / route they get a generic about page along with a sign in button. The sign in button redirects to my /api/login route and eventually back to my /api/login/callback. Now, the callback will redirect again to the / route. Subsequent requests made will have the session cookie attached and will go through.
My problem arises in that I don't know how to communicate to my frontend that my user is logged in. Because my session cookie is http only I can't access the cookie on page load to render a different UI for logged in users.
Some ideas I've had:
Hit up a /api/me URL that returns 401 or 200 depending on if the session cookie was sent. The problem with this is that this will leave the frontend in a limbo while the request is resolving.
Make the cookie not https only. However, I've read online that this makes it vulnerable to XSS attacks.
Send a second, non https only cookie as well to show that the session cookie exists. If this cookie is tampered with the worst that can happen is that a user will receive a 401 error later down the road when they make an API call without the session cookie.
Put something in local storage or in a cookie before the request to signify a user hit log in and check for it on page load. However, I won't know if the login succeeded or not.
Create a second page specifically for unsigned in users on the / route. Then, the callback can redirect to /signed-in. However, how will my /signed-in route know if a user navigated there or if the server redirected them? (ex. if the user autocomplete's the browser bar to the /signed-in route after their session expires)
Out of all these the third approach seems the most viable (the second cookie). However, this seems like a very trivial problem that someone has solved before. What am I missing here?
Note: I don't want to use ssr here. If I was using ssr I could simply just check for the session cookie server-side on the / route and reply with a different HTML template.
Edit: I could combine ideas 3 and 4. Put something in a store before sign in. If sign in fails, have my server redirect to a /fail page. If not, redirect to /. Then, / can reload the store on page load. /fail would also delete the stored item so that a user who failed can't just immediately go back to / and see they are logged in. The only unauthorized people who would see my user ui on / would be
Users who close out of the page during their login (never finish their login so never redirected to /fail to delete the store)
Users who revoke their OAuth token. This will have to be caught later down the road when my server receives a 401.
I could also add in a third "authorizing" state. I would set this before login. On page load with the authorizing state, I'd make a request in the background to validate that the user finished signing in. If I get a 401 from my server I'd have to move the user out of the authorized page. It wouldn't be nice but it'd occur less often than if I didn't use the store.
Before hitting sign in set a temporary loading value inside a store (cookie, framework store, localstorage, etc).
If the callback URL receives a failure value, redirect to the /fail route. /fail will set a failure value inside the store and redirect to /.
If the callback URl receives a success value, redirect to the /success route. /success will replace the temporary value with a success value.
On page load, read the store.
If the store is empty its a new user.
If the store has a temporary value, they never get redirected after the callback. Show a toast about an error and then display the sign in page.
If the store has a failure value, they failed the OAuth. Again, show a toast and display the sign in page.
If the store has a success value, everything went right. Show the user UI.
Eventually, the user may want to revoke their token. If they do, my app will not know until I make a request to a protected api endpoint with their token. If so, just pass the 401 to my frontend. I can show a modal saying they are unauthorized and then replace the success store value with an empty value.
In my application I have filter that sets cookie:
HttpContext.Response.Cookies.Append("myCookie", "value")
When I print cookie value in my view:
HttpContext.Request.Cookies["myCookie"];
it is not there. If I refresh page cookie is set. This happens because using Response.Cookies.Append does not update Request.Cookies collection. Is there way to view current cookies with changes made during request?
In my web application I have IAsyncActionFilter, that updates cookie, however corrected value is visible only after page is refreshed, and I would like to finish current request with new value. I know that it will be set by browser when response finishes, but I already know that I have new value for that cookie, and I would like to propagate this value to views reading cookies.
No. This is how cookies work. They are sourced from the client. In other words, the cookie is set by the client after it receives the response from the server with the Set-Cookie header. It's then only after the client makes another request, sending the cookie back, that it exists server-side. It's not clear what you're trying to achieve ultimately here, but you need to force a new request after setting a cookie, to access that cookie, even if that's simply returning a redirect to the same page.
I see you can set the expiration using CookieOptions when appending a new cookie to the response. However, HttpContext.Request.Cookies returns an IRequestCookieCollection, which only seems to give you key/value pairs.
Is there a way to read the CookieOptions (specifically the Expiration) for request cookies?
I'm using .Net Core (1.0.0-preview2-003131)
NOTE: I need to read the expiration of an arbitrary cookie in request processing, not the expiration of the framework generated auth cookie.
I'm getting that by reacting to the event "OnValidatePrincipal"
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
...
Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = CookieAuthenticationEventHandler.ValidatePrincipalAsync
}
});
And then I can access, once the principal is validated, when the cookie will expire in my ValidatePrincipalAsync with the property context.Properties.ExpiresUtc
To be able to get that expires property later in my controller, I'm adding it in my HttpContext this way:
context.Request.HttpContext.Items.Add("ExpiresUTC", context.Properties.ExpiresUtc);
But I'm not really happy with that part, maybe someone can give you a better way to access it directly in the controller without having to get it from the OnValidatePrincipal.
No, HTTP does not include any details about cookies sent on requests, only their name and value. The auth cookie workaround only works because the expiration is also embedded in the value.
Django: Cookie set to expire in 30 seconds is actually expiring in 30 minutes? does
hr = HttpResponse('ok')
hr.set_cookie('user_id', user_id, max_age=30)
while https://stackoverflow.com/a/25179642/433570 does
request.session[user_id] = True
And both says we are setting cookie.
What's the difference between the two?
Can I set the expiration with the request.session method?
In short, cookies are intended to be stored in client side while sessions are stored in server-side (unless you're using cookie based session).
Users can clear http cookies from their browsers but they can't do anything about the sessions on your server. Clearing sessions is up you and your settings. There are some django settings you can use to determine their age like SESSION_COOKIE_AGE. For http cookies it's possible to set attributes like max_age, expires.
Choosing which one to use depends on your requirements; are you going to store sensitive data, is permanence important etc.
References:
Django sessions
Django request-response methods including set_cookie
Wikipedia HTTP cookies
I want to crawl a website which has a strong security protocol and want to crawl data as fast as possible. Thus I thought I need a multi-login-cookie, multi-user-agent, and multi-proxy crawler.
I have tens of usernames and passwords and I can login using each one and get all the cookies. To hide the identity of my crawler I thought I should also replace the user-agent setting and my IP. I have found many user agents and proxies.
I learned that the cookie is needed each time I send a request to the server, and that cookie should be of the same identity and contain the information of the previous request and the corresponding response. I've gained the knowledge of how to pass it through requests without logging in from this answer. And I know two ways to login in, one outside the scrapy(by passing the cookie to the cookiesmiddleware in the middleware.py file:
from cookies import cookies # script written to login some accounts and return the cookies
import random
class CookiesMiddleware(object):
def process_request(self, request, spider):
cookie = random.choice(cookies)
request.cookies = cookie
) and another inside it.
What's more in the middleware.py file I passed the user agents randomly in the same as for cookies to the scrapy requests.
My question is: if I pass the cookies randomly as aforementioned, will one spider get the same cookie each time it sends a request? If not the server side will detect me as a bot and block me. What's worse, the same applies to the user-agents and proxies. How to bond each trinity(login cookie, user-agent and proxy) starting from the login, extending the aforesaid answer both in the horizontal and vertical dimension?
To be more precise, should I pass the login cookie in the form of {cookies= user1_cookie} or { meta={'cookiejar': user1_cookie},? And should I pass the user agent and proxy in the meta parameter?
Thanks. Please kindly point me in the right direction, and any suggestions will be highly received and appreciated.
Seems like you are looking for cookiejar. It will allow you to store multiple cookie sessions in single spider session.
Using middleware for random cookies is a bad idea since cookies in most cases store your whole browsing sessions.