dmfs/oauth2-essentials

Unauthorized Exception

Closed this issue · 6 comments

I'd like to retrieve an access token from the ERP service Odoo - their endpoints are:

image

Following the instructions of oauth2-essentials I initialize the client with the credientials and then I copy the whole URL I GET as response, which contains the authorization code to redirectUrl:

OAuth2AccessToken token = grant.withRedirect(redirectUrl).accessToken(executor);

I then get the following error message:

Exception in thread "main" org.dmfs.httpessentials.exceptions.UnauthorizedException: Authentication at my odoo domain'/restapi/1.0/common/oauth2/access_token'_ failed.
at org.dmfs.httpessentials.responsehandlers.FailResponseHandler.handleResponse(FailResponseHandler.java:74)
at org.dmfs.httpessentials.httpurlconnection.PlainHttpUrlConnectionExecutor.execute(PlainHttpUrlConnectionExecutor.java:81)
at org.dmfs.httpessentials.executors.common.decorators.BottomBranded.execute(BottomBranded.java:56)
at org.dmfs.httpessentials.executors.common.decorators.BottomBranded.execute(BottomBranded.java:56)
at org.dmfs.httpessentials.httpurlconnection.HttpUrlConnectionExecutor.execute(HttpUrlConnectionExecutor.java:69)
at org.dmfs.httpessentials.executors.useragent.Branded.execute(Branded.java:53)
at org.dmfs.oauth2.client.BasicOAuth2AuthorizationProvider.accessToken(BasicOAuth2AuthorizationProvider.java:55)
at org.dmfs.oauth2.client.BasicOAuth2Client.accessToken(BasicOAuth2Client.java:71)
at org.dmfs.oauth2.client.grants.AuthorizationCodeGrant$AuthorizedAuthorizationCodeGrant.accessToken(AuthorizationCodeGrant.java:165)

Any help? The credentials are correct and I even get an authorization code.

The response Url I put into redirectUrl looks for example something like this:
my odoo domain/?code=1npyDMbiCgGZnSgz1Tnvbc3lR060MD1m&state=RHpoZhuLaR8XW5Gd_O9D-5l5VZeXkTBNJVXgrZTgtxqdP23oGCqnTEFTcLEaWY_B

Thank youu!

dmfs commented

the redirectUrl looks ok. UnauthorizedException indicates that the server returned a 401 Unauthorized error in response to the request. I've looked at https://apps.odoo.com/apps/modules/12.0/restapi/ but they don't really tell what they expect in the request.

RFC 6749 allows two ways of authenticating the client, the mandatory HTTP authentication method (that's what this library uses) and an optional request parameter method. Is it possible they don't support that HTTP authentication method?

Hi, thank you very much for your answer! 🙏

There is a more insightful documentation for Odoo's OAuth here:
https://odoo-restapi.readthedocs.io/en/latest/connection/logging_in/oauth2_authentication.html
In there they mention HTTP, so my guess is that it luckily is supported...

But maybe I just misinterpreted the instructions? In the last step it says:

// Open the URL in a WebView and wait for the redirect to the redirect URL
// After the redirect, feed the URL to the grant to retrieve the access token
OAuth2AccessToken token = grant.withRedirect(redirectUrl).accessToken(executor);

So I manually open it in Browser - maybe that's the problem? Do I have to instead use the HttpRequestExecutor, I initialize in the beginning to execute the GET-Request?

Here's the code with the Browser call:

untitled

Cheers

dmfs commented

Thanks for the link. Looks like their implementation mixes OAuth2 and OAuth1.

This OAuth Authorization header scheme is used by OAuth1. (also see the Authentication Scheme Registry)

Authorization: OAuth client_id='uwCrAHAQbL7D9cvJLIztNaZ0bziEGMDh',
                     client_secret='FtHzOQVEs0aSEL9AXuIe9k7X6E2MekU7',

Whereas OAuth2 uses regular Basic authentication to authenticate the client, see
RFC 6749, section 4.1.3

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

Sorry, unless they fix their OAuth2 implementation this library won't help you (nor will any other standards compliant implementation).

Thank you very much again for your response. I appreciate you've taken the time to investigate my problem. All you're saying is plausible to me and reading through the documentation chapters you've provided I see what the problem is. What puzzles me though, is that I am actually able to retrieve an access token using the URLs straight up my Google Chrome Browser.

For example - putting the GET
myOdooDomain/restapi/1.0/common/oauth2/authorize?client_id=myClientId&redirect_uri=myEncodedRedirect%&response_type=code

into the URL headline will return
myOdooDomain/?code=kkd0rfhQqOOtHq35ifdkYl3UQ9WTrfv1&state=None

Using this code in the POST request:
myOdooDmain/restapi/1.0/common/oauth2/access_token?client_id=myClientId&redirect_uri=myEncodedRedirect&code=kkd0rfhQqOOtHq35ifdkYl3UQ9WTrfv1&client_secret=myClientSecret&grant_type=authorization_code

will return me an access token in JSON format:

image

Would you reckon that there is no chance for me to reproduce this behavior in code?

Edit: I realized that the GET & POST above only work in browser if I'm logged into Odoo in the current browser session. Doing these without being logged in I get a 404 as well... which of course defeats the purpose of using OAuth in the first place. After all I want my client to fetch data w/o revealing my login data. So yes... as you stated - Odoo's implementation seems to be faulty.

But thank you again for all the help!

dmfs commented

I guess your best option is to report this bug to them and hope they fix it quickly (or at least stop calling it OAuth2).

dmfs commented

Closing this issue for now.