I have a django app with an endpoint that kicks off a long running task. I want to do this in the background. I know I could do this with celery or django-q, but I wanted to try something simpler first.
First thing I tried was ajax. In the python code I did this:
cookie = request.META.get('HTTP_COOKIE')
csrf_cookie = request.META.get('CSRF_COOKIE')
host = '{}://{}'.format(request.scheme, request.META['HTTP_HOST'])
data = {...}
resp = requests.post('{}/report/TASKS/Work/ajax/run.json'.format(host),
headers={'COOKIE': cookie, 'X-CSRFToken': csrf_cookie, 'referer': host}, data=data)
The function being called has the #login_required decorator, and when that runs it does the auth as the anonymous user, which fails so it redirects to the login page. The thread sending in the request is logged in and I have verified the cookies are all correct. Why would it use the anonymous user? How can I get it to auth using the logged in user?
Tried something else next - instead of using ajax I call it with multiprocessing.Process. This fails because the thread does not have a database connection.
Anyone have any thought on how I could make this work?
Related
So I'm able to create aa JWT on login using flask-jwt-extended
I set the expiration to 5 minutes.
So I have routes in my VueJS app and when they are called(beforeeach) I make a call to "/api/check" to make sure that the token is valid.
All other API calls are via axios to the backend.
What I'm not understanding that since the cookie is HTTP only I can't check the expiation with javascript...does that mean I have to ping the backend every X minutes along with with every axios call to refresh the cookie then make the actual API call?
Seems like a lot of overhead.
Lots of code out there on the nuts and bolts however not much on the actual steps behind the issue I'm having...understanding...
Thanks
You could have the backend automatically refresh the cookie if it is close to expiring without having to do anything extra on the frontend. Something like this (untested)
#app.after_request
def refresh_jwt_if_near_expiring(response):
expires_time = get_raw_jwt().get('exp')
if not expires_time:
return response
# Change the time delta based on your app and exp config.
target_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
if (target_time > expires_time):
access_token = create_access_token(identity=get_jwt_identity())
set_access_cookies(response, access_token)
return response
Then if the user is inactive for X many minutes they get logged out, otherwise they keep getting a new token as needed. If they do wait too long and get logged out, the backend returns a 401 and your frontend can prompt them to log in again.
A backend service which decomposes the jwt and returns the expiration time would do the trick.
in my opinion you don't need route "/api/check" to make sure tokens are valid. just add a decorator #jwt_required
#api.route('/api/user')
#jwt_required
def api_user():
result = #your logic
return jsonify(result), 200
I am trying to create an admin command that will simulate some api calls associated with a view but I don't want to hard code the url, for example like that url='http://127.0.0.1:8000/api/viewname', in order to send the request.
If I use the reverse option I can obtain half the url /api/viewname.
If I try to post the request that way
url = reverse('name-of-view')
requests.post(url, data=some_data)
I get
requests.exceptions.MissingSchema: Invalid URL '/api/viewname/': No schema supplied. Perhaps you meant http:///api/viewname/?
Do I have to look whether the server is running on the localhost or is there a more generic way?
requests module needs the absolute url to post to. you need
url = 'http://%s%s' % (request.META['HTTP_HOST'], reverse('name-of-view'))
requests.post(url, data=some_data)
I'm using Django 1.6.
I want to set session id.
When I use web browser, I can watch "sessionid" logs.
But, when I used other application like Unity3d,
I can't watch "sessionid" logs.
Could you tell me how to get a session id?
I've create the view
But, I'm accessing application like unity
it returns.
def get_token(request):
# request_cookies = OrderedDict(request.COOKIES)
context = {}
context.update(csrf(request))
context['csrf_token'] = force_text(context['csrf_token'])
session_key = request.session.session_key
context['sessionid'] = session_key
return HttpResponse(json.dumps(context), content_type="application/json")
But, session id is null. however web broweser is okey.
jsonText: {"csrf_token": "xma9Dtmv46va5uomZiZ9dcjjfCB9E2Gw", "sessionid": null}
Sessions are set using cookies. Cookies are implemented by the vast majority of browser but not by other http clients.
Since you mention Unity, I guess what you are building with Django is an api. I suggest you take a look at http://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication as an alternative to relying on cookies.
I was creating a twitter application with Django. I used the twitter lib from http://github.com/henriklied/django-twitter-oauth for OAuth , as specified in the twitter example pages .
But I am not too sure how to redirect user to my application home page once the authentication with twitter is over .
The code for
oauth_request = oauth.OAuthRequest.from_consumer_and_token(
consumer, http_url=REQUEST_TOKEN_URL
)
oauth_request.sign_request(signature_method, consumer, None)
resp = fetch_response(oauth_request, connection)
token = oauth.OAuthToken.from_string(resp)
oauth_request = oauth.OAuthRequest.from_consumer_and_token(
consumer, token=token, http_url=AUTHORIZATION_URL
)
print(oauth_request.to_url());
oauth_request.sign_request(signature_method, consumer, token)
return oauth_request.to_url()
response = HttpResponseRedirect(auth_url)
request.session['unauthed_token'] = token.to_string()
I even tried passing a "oauth_callback" parameter along with "auth_url" .
But after the authentication , it's not redirecting back to my application which is at
"http://localhost:8000/myApp/twitter/"
Any clues ? Any pointers ?
Thanks
Jijoy
The callback needs to be something like http://local.dev:8080. Twitter doesn't recognize localhost. One thing you probably need to do is go to your etc/hosts file and make sure you add the line 127.0.0.l local.dev
Check if you have enter the callback url in the details of your Twitter App in http://dev.twitter.com/apps.
First off, if there is a true, official way of having flash/flex's NetConnections usurp the session/cookie state of the surrounding web page, so that if the user has already logged in, they don't need to provide credentials again just to set up an AMF connection, please stop me now and post the official answer.
Barring that, I'm assuming there is not, as I have searched and it seems to not exist. I've concocted a means of doing this, but want some feedback as to whether it is secure.
Accessing a wrapper-page for a flash object will always go to secure https due to django middleware
When the page view is loaded in Django, it creates a "session alias" object with a unique key that points to the current session in play (in which someone ostensibly logged in)
That session alias model is saved, and that key is placed into a cookie whose key is another random string, call it randomcookie
That randomcookie key name is passed as a context variable and written into the html as a flashvar to the swf
The swf is also loaded only via https
The flash application uses ExternalInterface to call java to grab the value at that randomcookie location, and also deletes the cookie
It then creates a NetConnection to a secure server https location, passing that randomcookie as an argument (data, not in the url) to a login-using-cookie rpc
At the gateway side, pyamf looks up the session alias and gets the session it points to, and logs in the user based on that (and deletes the alias, so it can't be reused)
(And the gateway request could also set the session cookie and session.session_key to the known session ID, but I could let it make a whole new session key... I'm assuming that doing so should affect the response properly so that it contains the correct session key)
At this point, the returned cookie values on the flash side should stick to the NetConnection so that further calls are authenticated (if a connection is authenticated using username and password the normal way, this definitely works, so I think this is a safe bet, testing will soon prove or disprove this)
So, is this unsafe, or will this work properly? As far as I know, since the html page is guaranteed to be over ssl, the key and cookie data should be encrypted and not steal-able. Then, the info therein should be safe to use one-time as basically a temporary password, sent again over ssl because the gateway is also https. After that, it's using the normal pyAMF system over https and not doing anything out of the ordinary.
No responses on this so far, so the best I can do is confirm that it does in fact physically work. For details on how to set up Flex Builder to write html-wrappers that communicate with Django pages templates, see my other post. The above was accomplished using a combination of the aforementioned, plus:
Made a SessionAlias model:
class SessionAlias(models.Model):
alias = models.CharField( max_length=40, primary_key=True )
session = models.ForeignKey( Session )
created = models.DateTimeField( auto_now_add=True )
Flex points to a Django page that loads via a view containing:
s = SessionAlias()
s.alias = SessionStore().session_key // generates new 40-char random
s.session = Session.objects.get( session_key=request.session.session_key )
s.save();
randomcookie = SessionStore().session_key // generates new 40-char random
kwargs['extra_context']['randomcookie'] = randomcookie
response = direct_to_template( request, **kwargs )
response.set_cookie( randomcookie, value=alias )
In the flex html-wrapper, where randomcookie is the location to look for the alias:
<param name="flashVars" value="randomcookie={{randomcookie}}" />
In applicationComplete, where we get randomcookie and find the alias, and log on using that:
var randomcookie:String = this.parameters["randomcookie"];
// randomcookie is something like "abc123"
var js:String = "function get_cookie(){return document.cookie;}";
var cookies:String = ExternalInterface.call(js).toString();
// cookies looks like "abc123=def456; sessionid=ghi789; ..."
var alias:String = // strip out the "def456"
mynetconnection.call( "loginByAlias", alias, successFunc, failureFunc );
Which in turn access this pyamf gateway rpc:
from django.contrib.auth import SESSION_KEY, load_backend
from django.contrib.auth.models import User
from django.contrib import auth
from django.conf import settings
def loginByAlias( request, alias ):
a = SessionAlias.objects.get( alias=alias )
session_engine = __import__( settings.SESSION_ENGINE, {}, {}, [''] )
session_wrapper = session_engine.SessionStore( a.session.session_key )
user_id = session_wrapper.get( SESSION_KEY )
user = User.objects.get( id=user_id )
user.backend='django.contrib.auth.backends.ModelBackend'
auth.login( request, user )
a.delete()
return whateverToFlash
And at that point, on the flash/flex side, that particular mynetconnection retains the session cookie state that can make future calls such that, inside the gateway, request.user is the properly-authenticated user that logged onto the webpage in the first place.
Note again that the run/debug settings for flex must use https, as well as the gateway settings for NetConnection. And when releasing this, I have to make sure that authenticated users stay on https.
Any further info from people would be appreciated, especially if there's real feedback on the security aspects of this...
IE doesn't give access to cookies in local development but if you publish the SWF and put on a domain, it should pickup the session just like ever other browser. Use Firefox 3.6 to build your flex apps locally.
Tested in IE8, Firefox using a pyamf gateway on Flex 3 with NetConnection. The gateway function was decorated with #login_required