How to implement hotlinking prevention in Google App Engine - python

My application is on GAE and I'm trying to figure out how to prevent hotlinking of images dynamically served (e.g. /image?id=E23432E) in Python. Please advise.

In Google webapp framework, you can extract the referer from the Request class:
def get(self):
referer = self.request.headers.get("Referer")
# Will be None if no referer given in header.
Note that's referer, not referrer (see this dictionary entry).

Related

Accessing cookie from another sub-domain

I have two django applications that are deployed at two different sub-domains, for example:
data.mysite.com
i.mysite.com
Both sites use the same django authentication framework and such, setting a cookie called sessionid. I can read the cookie from the current site using:
def my_view(request):
# suppose this view is within the i.mysite.com application
i_session_id = request.COOKIES['sessionid']
data_session_id = ? # how to get this?
But then how could I grab the cookies from the
If you want to have a shared authentication between your 2 subdomains then you need to set your session on .mysite.com domain. Then when you request to data.mysite.com will include this cookie, same for i.mysite.com domain. So, in settings.py:
SESSION_COOKIE_DOMAIN=".mysite.com"

Django send authenticated user to another django server with the same db

I know question sounds strange, I will explain it here.
I have two Django servers which share the same DB. One is a light front/back server and the order one takes the heavy computing part. They share the same database.
I am currently securing the web, and I have a couple of views in the light server requiring user login:
#login_required()
#permission_required('auth.can_upload', login_url='/accounts/login/')
This works nicely in the light server since the user is authenticated (request.user returns a valid user in the views).
The problem comes when I have to send the uploaded data to the other server since it is protected as I showed earlier, I do not know how to pass it the user that is already logged (user is valid since servers share the DB).
# send an upload request using requests
s = requests.Session()
r1 = s.get(upload_process_url)
csrf_token = r1.cookies['csrftoken']
a = s.post(upload_process_url, files=request.FILES,
data={'csrfmiddlewaretoken': csrf_token},
headers=dict(Referer=upload_process_url))
I cannot ask every time the user and password or save them. The thing is I want to pass the user that is already logged in a request.
The user was logged using the default django accounts/login page and authentication.
Any clues and what could I try? I think this problem cannot be as difficult as it looks to me. I just want to send an authenticated request. If I remove the decorators everything works nicely with this code
Thanks a lot
Have a look at REMOTE_USER authentication:
This document describes how to make use of external authentication sources (where the Web server sets the REMOTE_USER environment variable) in your Django applications. This type of authentication solution is typically seen on intranet sites, with single sign-on solutions such as IIS and Integrated Windows Authentication or Apache and mod_authnz_ldap, CAS, Cosign, WebAuth, mod_auth_sspi, etc.
Basically your "light" server does the authentication as it already does. When you are doing a request to your "heavy" server, you should set a Auth-User header containing the username of your user. Django will then automatically authenticates the corresponding user.
By default, Django will read an environment variable set by an authentication server. But we can make it work with a HTTP header instead:
# middlewares.py
from django.contrib.auth.middleware import RemoteUserMiddleware
class CustomHeaderMiddleware(RemoteUserMiddleware):
header = 'HTTP_AUTH_USER'
# settings.py
MIDDLEWARE = [
'...',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'my_project.middlewares.CustomHeaderMiddleware',
'...',
]
Then, you can do something like this then in your request (assuming you have your Django user at hand):
s = requests.Session()
r1 = s.get(upload_process_url)
a = s.post(
upload_process_url,
files=request.FILES,
headers={
'Auth-User': user.username,
},
)
Since you're not doing a request from a browser, you can avoid the CSRF protection by marking the called "heavy" view with #csrf_exempt decorator (as you found yourself).
Be careful though that your "heavy" server should not be accessible directly on the internet and always behind a proxy/VPN accessible only by your "light" server.

Python Social Auth - How to know if social media connect is successful?

I have installed Python Social Auth. I use it to associate user site account with his social media accounts.
Facebook connect link is:
Connect
Redirection works but how to know if social media association is successful?
If an exception is catch, I can display get_messages() function. It's perfect!
But any return if it's successful.
I have tried to custom a pipeline but I have not access to request variable to set message like it: messages.success(request, "Successful message!')
You do have access to request in your custom pipeline:
The pipeline functions will get quite a lot of arguments, ranging from the backend in use, different model instances, server requests and provider responses.
You can read more about it here.
and you can get access to request object like this:
def custom_pipeline(strategy, *args, *kwargs):
request = strategy.request
and do whatever you wanted with messages.
There is an option
SOCIAL_AUTH_LOGIN_ERROR_URL = '/error/'
in python social auth settings which redirects to the url you mention in above setting.
This way you will know whether the connect is success or not.
Hope this is helpful.

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/

Multiple authentication options with Tornado

Just started playing with Tornado and want to offer multiple methods of authentication. Currently my app is working fine with Google's hybrid OpenID/oAuth using tornado.auth.GoogleMixin and the unauthenticated users are automatically sent to Google's auth page.
If an unauthenticated user wants to use another option (ie. local auth or tornado.auth.TwitterMixin), how can I implement the logic to choose an auth mechanism within the login handler?
I added the decorator 'tornado.web.authenticated' to all of my exposed methods, and here is the my login handler class (pretty much straight from the Tornado examples) which is currently working with Google OpenID/oAuth:
class AuthLoginHandler(BaseHandler, tornado.auth.GoogleMixin):
#tornado.web.asynchronous
def get(self):
if self.get_argument('openid.mode', None):
self.get_authenticated_user(self.async_callback(self._on_auth))
return
## redirect after auth
self.authenticate_redirect()
def _on_auth(self, user):
## auth fail
if not user:
raise tornado.web.HTTPError(500, 'Google auth failed')
## auth success
identity = self.get_argument('openid.identity', None)
## set identity in cookie
self.set_secure_cookie('identity', tornado.escape.json_encode(identity))
self.redirect('/')
Appreciate any suggestions for a solution. Thanks
I think the easiest way to do it would be to change the AuthLoginHandler to something more specific, like GoogleAuthHandler, and create an appropriate route for that:
(r"/login/google/", GoogleAuthHandler),
(r"/login/facebook/", FacebookAuthHandler),
etc.
Then simply create links to each authentication provider on the page ala:
<a href="/login/google/>Login with Google</a>
Login with Facebook
If you wanted to make it fancier, you could provide the providers as a select box, or if you wanted to get REALLY fancy, you could parse their 'openid' URL (e.g., if username.google.com, self.redirect("/login/google"), but that assumes that users know their OpenID provider URLs, which is usually not the case. I'd guess if you gave them a google / facebook / twitter icon or something to click on that would confuse the least number of people.
I came upon this problem myself but in a slightly different circumstance.
One solution is actually to do something like this.
class AuthLoginHandler(BaseHandler, tornado.auth.GoogleMixin, tornado.auth.TwitterMixin):
def get(self):
if want_google:
tornado.auth.GoogleMixin.get_authenticated_user(self)
#...
elif want_twitter:
tornado.auth.TwitterMixin.get_authenticated_user(self)
#...

Categories

Resources