Skip to content

Issue refreshing Wix OAuth tokens - cannot send payload as JSON using refresh_token_request compliance hook #544

@skray

Description

@skray

The crux of my question below is: Am I correct that there is currently no way to use the refresh_token_request to send a JSON payload to the token request endpoint?

To explain the issue I am having, Wix's OAuth flow requires access token requests and refreshes to be made using (non-standard) JSON request bodies, instead of the standard x-www-urlformencoded body. Documentation for reference:

I am able to get the initial access token using the access_token_request compliance hook, using a hook very similar to the one described in the PR that introduced the it:

def redacted_company_compliance_fix(session):
    def _request_in_json_not_form_urlencoded(url, headers, request_kwargs):
        headers["Content-Type"] = "application/json"

        if "redirect_uri" in request_kwargs["data"]:
            del request_kwargs["data"]["redirect_uri"]

        request_kwargs["json"] = request_kwargs["data"]

        del request_kwargs["data"]

        return url, headers, request_kwargs

    session.register_compliance_hook("access_token_request", _request_in_json_not_form_urlencoded)
    return session

However, I am not able to figure out a way to use the refresh_token_request compliance hook in a similar way to send a JSON payload. The refresh logic is much more tightly coupled to sending the request payload as x-www-form-urlencoded, sending only explicit kwargs into the self.post method, including an expectation that the body returned from the refresh_token_request hook is a urlencoded string. Here is the code in question:

for hook in self.compliance_hook["refresh_token_request"]:
    log.debug("Invoking refresh_token_request hook %s.", hook)
    token_url, headers, body = hook(token_url, headers, body)

r = self.post(
    token_url,
    data=dict(urldecode(body)),
    auth=auth,
    timeout=timeout,
    headers=headers,
    verify=verify,
    withhold_token=True,
    proxies=proxies,
)

So:

  • Am I correct that there is no way to manipulate the request here to have it send JSON instead of an x-www-form-urlencoded body?
  • If so, I am happy to put up a PR, but could use guidance on how to update the refresh_token method and refresh_token_request hook to allow this in a non-breaking way. Would something like this be a good start, allowing non-x-www-form-urlencoded strings to be returned from the refresh_token_request hook?
for hook in self.compliance_hook["refresh_token_request"]:
    log.debug("Invoking refresh_token_request hook %s.", hook)
    token_url, headers, body = hook(token_url, headers, body)

try:
  # attempt to turn body into dictionary
  body = dict(urldecode(body))
except ValueError:
  # allow non-x-www-form-urlencoded bodies to be passed as strings
  pass 

r = self.post(
    token_url,
    data=body,
    auth=auth,
    timeout=timeout,
    headers=headers,
    verify=verify,
    withhold_token=True,
    proxies=proxies,
)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions