The python lib mentioned in OAuth website rauth seems to be simple and best one to use. So, I want to use it in Django and unable to actually implement it.
Here is my issue.
# I do something like this initially
from rauth.service import OAuth2Service
from django.shortcuts import render_to_response
def page(request):
service = OAuth2Service(
consumer_key = "..",
consumer_secret = "...",
.. )
url = service.get_authorize_url(redirect_uri="http://mysite.com/redired-url")
# this url is where the user accepts or not.
# which redirects with authorization code.
return HttpResponseRedirect(url)
Now, when user opens page, it directly redirects and asks user to allow or reject.. If user allows, we get authorization code at redirect-url
To get access token from authorization token,
rauth lib mentions to do so which I have to put under a different view corresponding to redirect-url
data = dict(code='foobar',
grant_type='authorization_code',
redirect_uri='http://example.com/')
token = service.get_access_token('POST', data=data)
The problem is with service object. I created service instance in one view, i need to use it in another view to get access token..
Where I am going wrong..? How to get it done.
Okay there's various ways to handle this in the context of a web app. I would highly recommend taking a look at the Facebook Flask example in the examples dir.
The basic idea is provide an authorization view and a redirect view. You want to have the provider redirect to the redirect view and therein you should do all the stuff you'd expect to be able to do assuming you've been authorized by the user. Otherwise, you should bail out and possibly inform the user as to why.
Now what I typically do is keep the service wrappers in a separate module, not in a view, and then import them into the context I need them. You can do things to initialize them dynamically and such. But reference the link I posted for a simple implementation. I think this should do what you want. I realize it's not Django, but the idioms are pretty close with the simple case of views like this.
Update - Upon further review, I saw a need for clarification. You won't get the access_token until AFTER the user clicks "Yes" on the reddit authentication page. It will then redirect, with a code and state information in the query, to the URI you provided at the beginning of your process.
To receive the OAuth2 tokens posted back in the redirect_uri's view, you will need to get the URL parameters from within the view class/method:
code = request.GET.get('code', '')
This will give you a variable containing the code generated from the first request (it's in the URI as a parameter).
Make sure you check your "state" variable as well, retrieving it the same way, otherwise your security goes out the window.
What you do from there depends on if you're using rauth or praw, but you can use the information gleaned above to generate the appropriate request to get said access token.
Basically, your callback view (redirect_uri) handles all reddit verification and processing. Your initial view, for the most part, either a generated link or a redirect to reddit.com.
Related
I'm working in Flask on creating a JMML ("Join my mailing list") widget that submits data to an email marketing platform, and the platform follows an OAuth2 flow. The basic flow is:
I create access URL using a the base API URL, an API key, and a redirect URI
The program accesses this URL, and the user of the program is redirected to the marketing platform to log in and grant access.
The marketing platform performs another redirect back to the redirect URI that I provided. The URI is appended with the access token that I need to provide with app POST requests of my JMML. Here's an example of what the returned URI looks like:
http://localhost:5000/redirect_url#access_token=2C1zxo3O0J1yo5Odolypuo9DSmcI
Here's the problem I'm having: I have no idea how, programmatically, to use that final redirect url/uri as a variable in Python.I could make the user copy/paste it into a field, but there's gotta be a better way. I honestly don't even know the terminology for a redirected-redirect like this.
It's pathetic, and I'm lost, but here's what I have so far:
#app.route('/redirect_url')
def redirect_url():
# I have no idea how to actaully get the parameter out of the redirect url.
pass
I've checked the API documentation for the email marketing company's API, but they only provide code tips for handling Oauth2 in Ruby and PHP. Help!
There is a good blog post by Miguel Grinberg, where he describes how to work with OAuth in the flask application. Though I think that workflow will stay the same with any other web application.
Based on this it seems like you should be able to get the access token by getting the variable parameter from the url. I do not have your full code so i cant test, nor have I tried it with an # in the url, but this should work
#app.route('/originalurl')
#app.route('/redirect_url#<access_token>')
def show_user_profile(access_token):
if access_token:
#do work
return redirect(url_for('Anotherview')
return render_template('template.hmtl')
Otherwise we need more info on the api you are using Oauth with
I apologize in advance for asking a rather cryptic question. However, I did not understand it despite going through a lot of material. It would be great if you could shed some light on this.
What is the purpose of a request_loader in flask-login? How does it interact with the user_loader decorator?
If I am using a token based authentication system (I am planning on sending the token to my angularJS front end, storing the token there and sending that token in the authorization-token header), will I need a request_loader or will a user_loader (where I check the auth header and see if the user exists) suffice?
From the Flask-Login documentation:
Sometimes you want to login users without using cookies, such as using
header values or an api key passed as a query argument. In these cases,
you should use the request_loader callback. This callback should
behave the same as your user_loader callback, except that it accepts
the Flask request instead of a user_id.
So, to answer your question, they both serve the same function for Flask-Login. They are both used to load the user. request_loader, however, is appropriate for custom logins.
Here's a great tutorial I found that utilizes request_loader to take advantage of token based authentication (The post is not my own, I'm merely sharing the link): http://gouthamanbalaraman.com/blog/minimal-flask-login-example.html
I need to make this clear.
This is the reason why you shoud use request_loader with flask_login.
There will be a lot of #login_required from flask_login used in your api to guard the request access.
You need to make a request to pass the check of auth.
And there will be a lot of current_user imported from flask_login,
Your app need to use them to let the request act as the identity of the current_user.
There are two ways to achieve the above with flask_login.
Using user_loader makes the request to be OK for #login_required.
It is often used for UI logins from browser.
It will store session cookies to the browser and use them to auth later.
So you need to login only once and the session will keep for a time.
Using request_loader will also be OK with #login_required.
But it is often used with api_key or basic auth.
For example used by other apps to interact with your flask app.
There will be no session cookies,
so you need to provide the auth info every time you send request.
With both user_loader and request_loader,
now you got 2 ways of auth for the same api,
protected by #login_required,
and with current_user usable,
which is really smart.
To verify users with Flask-Login's session_id for frontend requests through Angular, you must set the withCredentials configuration flag to true.
That is, if you are using Angular's $http.post(url,data [,config]) or $http.get(url [,config]), make sure the config object contains the property withCredentials set to true. This will instruct the browser to use its cookies in the same way it would for a full-on page visit.
For example,
$http.post('/api/login',{username:'myusername',password:'mypassword'},{withCredentials:true})
will post the data {username:'myusername',password:'mypassword'} to your site/app's /api/login route and, if you're using Flask-Login and are logged in, Flask will know.
You can set this behavior for all $http service requests by setting
$httpProvider.defaults.withCredentials=true
somewhere in your app. Currently, I have that line of code in my app.config block, which seems appropriate to me:
var myApp = angular.module('myApp');
myApp.config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});
(Since this post is about Flask, folks may want to send form data through Angular in such a way that it can be found in request.form, which has a similar solution, fyi.)
I am building an app to access Github api in python using django. I am new to this building this kind of app for the first time.
I specified an link to get the access of a user's account like this
Now I can access the user's account. Now the problem is, I want to use oauth2 so that it doesn't ask for username and password for each request.
my question is how to get the access_token and where to store it. How to pass post parameter of POST https://github.com/login/oauth/access_token such as client_id, scope, code in my django view. And how to link different access for different user. Please help me. I am having problem in getting the basics right.
I recommend using Python Social Auth and then leveraging their Github backend after setting it up to work with your django app.
So, you would roughly be able to pass the access token using something like:
import requests
user = User.objects.get(...)
social = user.social_auth.get(provider='github')
response = requests.get(
'https://github.com/login/oauth/authorize?
client_id=something&scope=something,something',
params={'access_token': social.extra_data['access_token']}
)
retrieved_data = response.json()['items']
You can also make the token available in your template if you'd like to continue using a link. And, you don't need to pass the scope as a query parameter, certainly, Python Social Auth can also handle that for you
I am trying to find the easiest way how to use Facebook Graph API using my favorite Requests library. The problem is, all examples I found are about getting user access token, about redirects and user interaction.
All I need is only application access token. I do not handle any non-public data, so I need no user interaction and as my final app is supposed to be command-line script, no redirects are desired.
I found something similar here, but it seems to be everything but elegant. Moreover, I would prefer something using Requests or Requests-OAuth2. Or maybe there is library for that? I found Requests-Facebook and Facepy (both Requests based), but again, all examples are with redirection, etc. Facepy does not handle authorization at all, it just accepts your token and it is up to you to get it somehow.
Could someone, please, provide a short, sane, working example how to get just the application access token?
Following https://developers.facebook.com/docs/technical-guides/opengraph/publishing-with-app-token/:
import requests
r = requests.get('https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id=123&client_secret=XXX')
access_token = r.text.split('=')[1]
print access_token
(using the correct values for client_id and client_secret) gives me something that looks like an access token.
If you just need a quick/small request, you can manually cut and paste the access token from here into you code: https://developers.facebook.com/tools/explorer
Note: Unlike Richard Barnett's answer, you'll need to regenerate the code manually from the graph api explorer every time you use it.
In a web application already using django.contrib.auth for authentication, I'm looking for the "standard" approach for restricting access to Ajax services to authenticated users only.
Using the #login_required decorator won't do, because that just redirects unauthenticated users to a login page. For a service, we should probably be sending a valid, well-formed error response back -- not some login form.
This is the first approach that comes to mind:
from django.http import HttpResponse
def some_json_service_view(request):
if not request.user.is_authenticated():
return HttpResponse('{success: false}')
return HttpResponse('{success: true}')
Taking it one step farther, if I could standardize on a single response for all "not authenticated" errors, then a decorator would be nice:
from django.http import HttpResponse
def login_required_json(f):
def new_f(request):
if not request.user.is_authenticated():
return HttpResponse('{success: false}')
return f(request)
return new_f
#login_required_json
def some_json_service_view(request):
return HttpResponse('{success: true}')
Is this how everybody else does it, or is there a more accepted way it's done? Ideally, someone could point me to the django.contrib package made for this purpose.
That's an example that will work great if the AJAX services are consumed by your front-end clients only. I do that all the time, because the same design gets used for pushing all other kinds of data to the client through the response for which the client needs to perform additional actions or otherwise provide some feedback to the user. It works great when your site has mixed users, i.e. you support both anonymous and registered users.
If your building services for 3rd party vendors though, you'll either have to use OAuth, basic HTTP access authentication or digest HTTP access authentication. You do this when you know/assume that users who are performing the requests all have registered credentials. Hence, these authentication schemes allow a user to authenticate themselves if the authentication system challenges them for credentials, which they can immediately supply at hand, without manually having to enter them at a redirected login page.
So if your services have mixed users, I'd stick with what you have. Otherwise, you'll have to take up on something more elaborate, something that assumes that unauthenticated users have and can immediately supply their credentials.
In either case, I suggest you take a look at django-piston. It's like a pretty straightforward controller for parsing AJAX requests and serializing AJAX responses. Based on the supplied model and HTTP verb, it can automatically do a lot of the heavy lifting for you when exposing model access to user agents, plus it also comes packed with OAuth and HTTP access authentication.