Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POST methods always redirects #4

Closed
Steefkroon opened this issue Nov 20, 2013 · 13 comments
Closed

POST methods always redirects #4

Steefkroon opened this issue Nov 20, 2013 · 13 comments

Comments

@Steefkroon
Copy link

After succesfully added pmr2.oauth to a plone site for a project. Everything works perfectly except for one thing. POST methods always get redirected to the login page. I even tried it with the manage-ctsp/add function but that doenst work either.

What weird is though that if i change the post to a get request (session.post(....) to session.get(....)) then the authentication works, but breaks at the function im trying to addres because of the wrong http method. This unusual behavior looks like a bug with POST methods.

@metatoaster
Copy link
Member

Have you ensured that you have...

  1. Permitted the POST method in the scope profile you are using; and
  2. Commit that scope profile; and
  3. The client complete a request for a new token credentials as existing access tokens will not suddenly gain/lose rights.

@metatoaster
Copy link
Member

Another pitfall you need to watch out for, assuming that you have done all the steps above correctly - nearly ALL OAuth client libraries out there right now do not know how to handle redirects correctly. They would happily reuse the same Authorization header on the redirected location thus that causes signature to fail.

I typically disable redirection in my use case and handle redirects manually.

>>> r = sess.post('http://localhost:8280/pmr/workspace/+/addWorkspace',
...     data=json.dumps(make_form_request(
...          action='add', storage='mercurial', title='failure')),
...     allow_redirects=False)
>>> r
<Response [302]>
>>> r.headers.get('location')
'http://localhost:8280/pmr/workspace/192'
>>> sess.get('http://localhost:8280/pmr/workspace/192').json()
{u'url': u'http://localhost:8280/pmr/workspace/192', u'owner': u'Test User <[email protected]>', u'id': u'192', u'description': None}

On the other hand, if the redirects are enabled.

>>> r = sess.post('http://localhost:8280/pmr/workspace/+/addWorkspace',
...     data=json.dumps(make_form_request(
...          action='add', storage='mercurial', title='failure')))
>>> r
<Response [403]>

This would then cause these server logs

2013-11-21 11:03:44 INFO oauthlib [Failure] request verification failed.
2013-11-21 11:03:44 INFO oauthlib Valid client: True
2013-11-21 11:03:44 INFO oauthlib Valid token: True
2013-11-21 11:03:44 INFO oauthlib Valid realm: True
2013-11-21 11:03:44 INFO oauthlib Valid signature: False
2013-11-21 11:03:44 ERROR Zope.SiteErrorLog 1384985024.820.133130041595 http://localhost:8280/pmr/workspace/195/workspace_view
Traceback (innermost last):
  Module ZPublisher.Publish, line 127, in publish
  Module ZPublisher.BaseRequest, line 601, in traverse
  Module Products.PluggableAuthService.PluggableAuthService, line 244, in validate
  Module Products.PluggableAuthService.PluggableAuthService, line 605, in _extractUserIds
  Module pmr2.oauth.plugins.oauth, line 95, in extractCredentials
Forbidden: authorization failed

That said, I simply don't know why you are getting redirects to the login page, that should never happen

@Steefkroon
Copy link
Author

To anwser your questions. I dit set the POST in the permitted http methods and did the whole oauth dance again.

The problem is that only post methods give me a hard time, while the rest works fluently.

Also i have found in the logs that prm2.oauth always says its an invalid token, even with the get methods which works, still display that error message in the logs.

@Steefkroon
Copy link
Author

To further test POST methods, I tried the tutorial example site and went to the document view of private file, but with a post instead of a get. The get method works but the post method redirects me to the login page.

@metatoaster
Copy link
Member

As I said, you need to disable the use of automatic redirect from your HTTP library. You have not told me whether your POST request generates its own redirects, and I have verified that the OAuth PAS Plugin does not result in a redirect to the login page if a valid OAuth request was permitted. Also, lastly, what kind of signature method is your library using. I still have not enable the support for the application/x-www-form-urlencoded signature method - ensure that you have also use the Authorization header signature method for now.

Naturally, if you post your code sooner it would aid in getting this working faster. I can't even begin to reproduce your problem without knowing exactly what you did.

So from what you said there are two reasons why the requests get redirected to login page:

  1. Not using the Authorization header signature method - OAuth PAS Plugin does not see this as an OAuth request
  2. The response from your POST target generates a redirect. If your library were using a query string based signature method all credentials would then be dropped, thus the new request your library makes on the new location will not have any credentials attached to it (which then results in redirection to login page).

@Steefkroon
Copy link
Author

Alright I am going to post my code, forgive me I am new to Plone so I dont know what really is neccessary but I am going to try:

The goal of the code is to upload a file to a plone site. This plone site has some extra objects that inherits from the plone archetypes like File, Folder, etc. The get oauth methods work perfectly on the extra objects. A colleague of mine has written an API which i can talk to to do different things.

One of these methods is a POST method called upload-file which as you might have guessed it uploads a file to the plone site. The code for this API is found here:
http://pastebin.com/MFgbF7rq

On the client side we have my code. I have uploaded my test code, the real code stores and saves the access tokens, but since im in development I want new tokens every request. The client code can be found here:
http://pastebin.com/9RQWuYiF

The problem is that even before the API code is called upon. PMR2.oauth says the request is invalid, while if i change the method to a get method it works (albeit crashes at the API method). In the contenttype scope manager I have added upload-file to every type to try and make this work.

I hope you can help me with it and I would like to thank you in advance for taking time to help me with this problem, Its greatly appreciated.

@metatoaster
Copy link
Member

Please use header_auth. I did mention that the Plone PAS Plugin only detected the header base authentication method due to difficulty in ensuring that it doesn't choke on non-OAuth request as I haven't had the time figured out how to safely handle application/x-www-form-urlencoded. Attributes and flags related to the authorization really should go into the Authorization header as provided by the HTTP spec, and the OAuth spec is being too loose with this, but I digress.

Another point where I can see things go wrong is that your scope configuration is not permissive enough. I assume SF4 is the plone site, and freshdesk is a folder type of some sort and a upload-file is a review registered through zcml because you are using BrowserView. However I may be wrong because your zcml definition might be mapping things differently than this assumption, and this will change the way the path is set up significantly.

Back to application/x-www-form-urlencoded. It's pretty broken, in terms of how OAuth specification decides to handle it and how the underlying Zope architecture makes this rather fuzzy as to how signatures are generated. Can you try to see if you can modify your library to accept JSON body? Then you could do something like

rr = oauth_session.post('http://localhost:8080/Plone/content/data-endpoint',
    data=json.dumps({'title': 'Test page', 'form.button.save': 1}),
    headers={'Content-type': 'application/json'})

Of course that would require changes to the way the endpoint handle incoming requests.

Anyway, it does look like correct handling of application/x-www-form-urlencoded will need to be taken care of.

@metatoaster
Copy link
Member

Heh. Looks like the case sensitivity is a cause for all these mess. Zope/Plone doesn't really do case sensitive headers but oauthlib does. Will be making a test/fix shortly but I am not getting these two hours of sleep back. Good thing it's a weekend or something.

@Steefkroon
Copy link
Author

Wow nice find, Never thought about the case sensitive headers and again I
greatly appreciate your work. I am currently learning Plone to be more
productive in these situations and even make a couple of addons on my own.

2013/11/22 Tommy Yu [email protected]

Heh. Looks like the case sensitivity is a cause for all these mess.
Zope/Plone doesn't really do case sensitive headers but oauthlib does. Will
be making a test/fix shortly but I am not getting these two hours of sleep
back. Good thing it's a weekend or something.


Reply to this email directly or view it on GitHubhttps://github.com//issues/4#issuecomment-29071780
.

metatoaster added a commit that referenced this issue Nov 22, 2013
- Correct the case so that oauthlib can correctly handle the content-
  type of application/x-www-form-urlencoded.
@metatoaster
Copy link
Member

Again, try adding setting header_auth=True before trying again, i.e.:

response = session.post('http://testsite.net:8563/SF4/freshdesk/upload-file', data=payload,
    header_auth=True)

Oh yeah, are you using buildout for your instance along with mr.developer? If not just clone the repo and look up how to use the develop flag in buildout. I am going to bed.

@Steefkroon
Copy link
Author

Well I tested it and it works perfectly now. Thank you again for your help

@metatoaster
Copy link
Member

Glad to be of your assistance. I have to thank you very much for bringing this flaw to my attention and your patience in putting up with working with a beta level product.

metatoaster added a commit that referenced this issue Nov 22, 2013
- Correct the case so that oauthlib can correctly handle the content-
  type of application/x-www-form-urlencoded.
@metatoaster
Copy link
Member

Fix released in pmr2.oauth-0.5.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants