Search code examples
roauth-2.0access-tokenhttrrefresh-token

Why does the httr package in r always give the same access token?


I have data in a Microsoft Dataverse that I'm attempting to pull into R. I don't have much background in software development / APIs / OAuth so I first used a tutorial that showed me how to work with APIs in Postman. I then used several tutorials online (most notably this one) to try to replicate what I'm doing in Postman. Doing so, I came up with the code below:

require(httr)
require(rvest)

dataverse_api = oauth_endpoint(request = NULL, 
   authorize = https://login.microsoftonline.com/REDACTED/oauth2/v2.0/authorize,
   access = https://login.microsoftonline.com/REDACTED/oauth2/v2.0/token,
   base_url = https://login.microsoftonline.com/common/oauth2/authorize?resourcehttps://org593dc393.crm4.dynamics.com)

API.Key = "REDACTED"
API.Secret = "REDACTED"

App = oauth_app("EPS Project Development", key = API.Key, secret = API.Secret)

API.token = oauth2.0_token(dataverse_api, App, scope = https://org593dc393.crm4.dynamics.com/.default)
API.AuthKey = API.token$credentials$access_token

GET.Buildings = GET(https://org593dc393.crm4.dynamics.com/api/data/v9.2/crfd0_dartbuildingses, add_headers(Authorization = paste("Bearer", API.AuthKey, sep = " ")))

The first day, the code above worked, and I was so excited! The next day, with no changes to the code, it returned a response of 401 (unauthorized). I've been going back and forth between Postman and R trying to figure out what's different, and what I realized is that every time I authenticate in Postman, I get a completely new access token (as expected); however, in R, when I keep running this code, the parameter stored in API.token$credentials$access_token is the same. I'm not really sure why this is.

Doing some more research, it seems like maybe I need a refresh token? I don't understand that because this is the same code other developers posted and no one else seems to be mentioning that it will only work once and then never again without a refresh token. Moreover, inspecting the documentation for httr makes it seem as if part of the oauth2.0_token function is to check whether or not the token needs to be refreshed. Anyway, when I look at the parameter API.token$refresh(), it tells me Error: Refresh token not available.

So now I'm attempting to get a refresh token, again without really understanding why. The documentation on the httr package details a function called oauth-refresh, but ?oauth-refresh gives an error and ?oauth_refresh says no results found. I also looked into this package by MatthewJWhittle that has a function called refresh_token, but again the help functions turn up no results after installing the package, so I guess it's no longer a valid package.

TLDR: Why is my code coming back with the same access token every time I request authorization? Did I miss a step in the code where I'm supposed to request a refresh token? Or if this is by design, how do I get a new one once this one expires?


Solution

  • It turns out I just needed to add cache = FALSE so that I'm not using cached tokens. If it's helpful to anyone, the full code is now:

    require(httr)
    require(rvest)
    
    dataverse_api = oauth_endpoint(request = NULL, 
       authorize = https://login.microsoftonline.com/REDACTED/oauth2/v2.0/authorize,
       access = https://login.microsoftonline.com/REDACTED/oauth2/v2.0/token,
       base_url = https://login.microsoftonline.com/common/oauth2/authorize?resourcehttps://org593dc393.crm4.dynamics.com)
    
    API.Key = "REDACTED"
    API.Secret = "REDACTED"
    
    App = oauth_app("EPS Project Development", key = API.Key, secret = API.Secret)
    
    API.token = oauth2.0_token(dataverse_api, App, scope = https://org593dc393.crm4.dynamics.com/user_impersonation, cache = FALSE)
    API.AuthKey = API.token$credentials$access_token
    
    GET.Buildings = GET(https://org593dc393.crm4.dynamics.com/api/data/v9.2/crfd0_dartbuildingses, add_headers(Authorization = paste("Bearer", API.AuthKey, sep = " ")))