Open davidism opened 3 years ago
Hmm... I think we'll need to update the documentation for this. I had entirely forgotten that the docs state that the authorization_url
and token_url
can be resolved relative to the base_url
, and it doesn't look like we have any automated tests that cover this case. Maybe it worked in the past, but doesn't work anymore... or it's entirely possible that it never actually worked this way.
However, while I'm willing to give up on relative paths for authorization_url
and token_url
, it's a different story for relative paths passed to openam.session.get()
. That sort of thing should work, and I use that pattern in several different sample Flask-Dance projects without any problems. For example, it works for GitHub, and Google, and Slack.
In the code, this resolution is handled in the flask_dance.consumer.requests.OAuth2Session.request()
function. If you're making an OAuth2ConsumerBlueprint
instance, passing base_url
, and not passing session_class
(so that it uses the default), then that should work properly. For the HTTP request you're making in your load_profile()
function, if you change that line to use a relative URL, can you confirm that it is not being resolved properly using the base_url
? Because if that's the case, I'll need to know more about your setup, so I can try to figure out why it's not working.
Looking at the docs of URLObject just using base_url.relative()
in the flask_dance_consumer.requests.OAuth2Session.request() function does not work for all cases. Look at the following example from the documentation:
>>> url = URLObject("https://github.com/zacharyvoase/urlobject?spam=eggs#foo")
>>> print(url.relative('another-project'))
https://github.com/zacharyvoase/another-project
For instance, the base_url
of the Strava API is https://www.strava.com/api/v3
. The following scenarios result in different results for base_url.relative(url)
>>> base_url = URLObject('https://www.strava.com/api/v3')
>>> base_url.relative('/routes/123')
URLObject('https://www.strava.com/routes/123')
>>> base_url.relative('routes/123')
URLObject('https://www.strava.com/api/routes/123')
>>> base_url = URLObject('https://www.strava.com/api/v3/')
>>> base_url.relative('/routes/123')
URLObject('https://www.strava.com/routes/123')
>>> base_url.relative('routes/123')
URLObject('https://www.strava.com/api/v3/routes/123')
In this case, only the last output is correct. However, I'm not sure if there is a simple way to handle all possible cases for all OAuth providers.
Edit: I guess, I should also include the example from the original post:
>>> base_url = URLObject("http://localhost:8080/openam/oauth2")
>>> base_url.relative('/userinfo')
URLObject('http://localhost:8080/userinfo')
>>> base_url.relative('userinfo')
URLObject('http://localhost:8080/openam/userinfo')
The docs say:
With
base_url="http://example.com/oauth2"
andauthorization_url="authorize"
, I get redirected tohttp://localhost:5000/auth/custom/authorize
. Using"/authorize"
with a slash at the beginning redirects tohttp://localhost:5000/authorize
. According to the docs, it should be redirecting tohttp://example.com/oauth2/authorize
.If I use full URLs in order to be able to get to the login, URLs are still not relative when making API requests. For example,
custom.session.get("userprofile")
tries to gethttp://localhost:5000/auth/custom/userprofile
. According to the docs, it should be gettinghttp://example.com/oauth2/userprofile
.I'm using OpenAM, running locally right now for testing. It's a bit involved to set up for oauth, but here's the example Flask app at least: