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

OAuth 2.0 resource owner authentication #564

Closed
hongooi73 opened this issue Jan 10, 2019 · 8 comments
Closed

OAuth 2.0 resource owner authentication #564

hongooi73 opened this issue Jan 10, 2019 · 8 comments
Labels
feature a feature request or enhancement oauth 🏓

Comments

@hongooi73
Copy link

(As opposed to http basic authentication, which is what authenticate does.)

Does httr support this? This is authenticating via a username and password, as opposed to a client secret:

https://tools.ietf.org/html/rfc6749#section-4.3.2

4.3.2.  Access Token Request

   The client makes a request to the token endpoint by adding the
   following parameters using the "application/x-www-form-urlencoded"
   format per Appendix B with a character encoding of UTF-8 in the HTTP
   request entity-body:

   grant_type
         REQUIRED.  Value MUST be set to "password".

   username
         REQUIRED.  The resource owner username.

   password
         REQUIRED.  The resource owner password.

   scope
         OPTIONAL.  The scope of the access request as described by
         Section 3.3.

   If the client type is confidential or the client was issued client
   credentials (or assigned other authentication requirements), the
   client MUST authenticate with the authorization server as described
   in Section 3.2.1.

   For example, the client makes the following HTTP request using
   transport-layer security (with extra line breaks for display purposes
   only):

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

     grant_type=password&username=johndoe&password=A3ddj3w
@cderv
Copy link
Contributor

cderv commented Jan 10, 2019

There is a use_basic_auth argument in oauth2_* function. This passes the key and secret from the app as basic authentication. Did you try ?

What you linked to is specific to Resource Owner Password Credentials Grant and may need a grand_type=password to work. So, I am not sure there is already a full integration with that but is possible by also using user_params= to customize the request.

Do you have an API in mind so that this could be tested further ? it would help to have an example of such an api. thanks!

@hongooi73
Copy link
Author

hongooi73 commented Jan 10, 2019

There is a use_basic_auth argument in oauth2_* function. This passes the key and secret from the app as basic authentication. Did you try ?

Yes, the use_basic_auth arg refers to http basic authentication via authenticate().

@hongooi73 hongooi73 changed the title OAuth 2.0 basic authentication OAuth 2.0 resource owner authentication Jan 10, 2019
@cderv
Copy link
Contributor

cderv commented Jan 10, 2019

Ok, so if you tried, with which API ?
I can't help if you can't provide something to test with. I don't have this kind of API at hand. Thank you.

@hongooi73
Copy link
Author

By the cunning stratagem of reading the source, I have determined that httr does not support this.

@cderv
Copy link
Contributor

cderv commented Jan 10, 2019

So this is a feature request.

I really thing that already all the tools are there to make it work, and there is not so much to do to support this grant.

I built a dummy example using httpbin to see the POST request that is sent to the server.
I believe only the grant_type is wrong here (because overridden) when using existing tool.

url <- "https://httpbin.org/post"
library(httr)

api_endpoint <- oauth_endpoint(
  authorize = NULL,
  access = "https://httpbin.org/post" # for demo
)

api_app <- oauth_app(
  appname = "app_dummy",
  key = "clientid",
  secret = "clientsecret"
)


json_res <- oauth2.0_access_token(
  endpoint = api_endpoint,
  app = api_app, 
  user_params = list(grant_type = "password", username = "username", password = "password"),
  code = NULL,
  use_basic_auth = TRUE,
  type = "text"
)
#> No encoding supplied: defaulting to UTF-8.

jsonlite::prettify(json_res)
#> {
#>     "args": {
#> 
#>     },
#>     "data": "",
#>     "files": {
#> 
#>     },
#>     "form": {
#>         "client_id": "clientid",
#>         "grant_type": "authorization_code",
#>         "password": "password",
#>         "redirect_uri": "http://localhost:1410/",
#>         "username": "username"
#>     },
#>     "headers": {
#>         "Accept": "application/json, text/xml, application/xml, */*",
#>         "Accept-Encoding": "gzip, deflate",
#>         "Authorization": "Basic Y2xpZW50aWQ6Y2xpZW50c2VjcmV0",
#>         "Connection": "close",
#>         "Content-Length": "130",
#>         "Content-Type": "application/x-www-form-urlencoded",
#>         "Host": "httpbin.org",
#>         "User-Agent": "libcurl/7.59.0 r-curl/3.2 httr/1.4.0"
#>     },
#>     "json": null,
#>     "origin": "176.183.22.128",
#>     "url": "https://httpbin.org/post"
#> }
#> 

In all case it should work using a POST call that will return you the token in response.
The POST request is correct here.

res <- POST(url, 
     body = list(grant_type = "password", username = "username", password = "password"),
     authenticate("clientid", "clientsecret"),
     encode = "form"
     )
jsonlite::prettify(content(res, "text"))
#> No encoding supplied: defaulting to UTF-8.
#> {
#>     "args": {
#> 
#>     },
#>     "data": "",
#>     "files": {
#> 
#>     },
#>     "form": {
#>         "grant_type": "password",
#>         "password": "password",
#>         "username": "username"
#>     },
#>     "headers": {
#>         "Accept": "application/json, text/xml, application/xml, */*",
#>         "Accept-Encoding": "gzip, deflate",
#>         "Authorization": "Basic Y2xpZW50aWQ6Y2xpZW50c2VjcmV0",
#>         "Connection": "close",
#>         "Content-Length": "55",
#>         "Content-Type": "application/x-www-form-urlencoded",
#>         "Host": "httpbin.org",
#>         "User-Agent": "libcurl/7.59.0 r-curl/3.2 httr/1.4.0"
#>     },
#>     "json": null,
#>     "url": "https://httpbin.org/post"
#> }
#> 

So I think this 📦 allows it to work, but not supported in an httr oauth dance flow yet, but could easily be.

However, I don't have example to test to see how an API of this type respond.
You can either work on something for a PR or provide enough elements for us to see what could be done. Thank you !

Hope it helps.

@hongooi73
Copy link
Author

hongooi73 commented Jan 11, 2019

Anyway, this is now implemented in AzureRMR along with device code auth: https://github.com/cloudyr/AzureRMR/blob/master/R/AzureToken.R

Feel free to steal implementation details for httr/httr2. Caveat: not heavily tested yet.

@cderv
Copy link
Contributor

cderv commented Jan 11, 2019

From the code you linked to, you used a function to wrap the POST call I showed above and extend the Token class. At the end, as expected, it was not so difficult to extend based on existing tools. I believe this ok for you now. It would be nice to have some PR to add the feature into httr too. At least, there is an example to linked too now. Thanks.

For reference as it is not precise, the example API is Azure which have several auth mechanisms, including resource owner grant type and it has been implemented in cloudyr/AzureRMR#5

@hadley
Copy link
Member

hadley commented Oct 31, 2023

Implemented in httr2: https://httr2.r-lib.org/reference/req_oauth_password.html

@hadley hadley closed this as completed Oct 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement oauth 🏓
Projects
None yet
Development

No branches or pull requests

3 participants