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

Unable to Test OAuth2 Workflow Locally Due to Fixed redirect_uri Constraint #174

Open
kunfang98927 opened this issue Jan 10, 2025 · 12 comments

Comments

@kunfang98927
Copy link
Contributor

Description

I am working on integrating the OAuth2 workflow for publishing new instrument names/images to Wikidata. While implementing the workflow, I encountered an issue with the redirect_uri:

  • The application is currently developing locally (e.g., http://localhost:8000).
  • Wikidata cannot redirect to localhost, as it requires a publicly accessible URL for the redirect_uri, which is https://vim.simssa.ca/oauth/callback. (This uri was registered when I applied for the OAuth2 consumer, and can not be changed.) Here is the screenshot of the approved OAuth2 consumer:
image

Steps to Reproduce

  1. In UMIL's instrument list page, when users try to add new instrument names directly to wikidata, they will click on a Authorize button.
  2. Initiate the OAuth2 flow to redirect users to the Wikidata authorization endpoint.
  3. After granting permission, Wikidata attempts to redirect to the fixed redirect_uri (https://vim.simssa.ca/oauth/callback), which is inaccessible when developing locally.

Questions

  • Are there any recommended ways to test the OAuth2 workflow locally without modifying the fixed redirect_uri?
  • Is there a development-friendly approach to handle this situation?
@kunfang98927
Copy link
Contributor Author

Current Solution after Scrum meeting this morning (2025-01-10): push the code directly to production server and test this workflow, but quickly revert changes if something goes wrong.

@dchiller
Copy link
Contributor

dchiller commented Jan 10, 2025

When you attempt this workflow locally, are you being redirected to vim.simssa.ca after successful authentication? If so, then isn't this working as expected? In other words, if you are being redirected correctly by the service, then there really isn't anything else to test. It may be that when you are developing locally you are getting redirected to vim.simssa.ca rather than the local version, but that's not really a problem, right? Just navigate back to localhost....

@kunfang98927
Copy link
Contributor Author

Thank you for the comments. @dchiller Maybe I didn't describe it clearly. Let me try to clarify. If I'm still not clear enough, or if I'm doing anything which is obviously wrong, please let me know.

image
  • After I click the "Allow" button, it will take me to https://vim.simssa.ca/oauth/callback?code=<a_temporary_code>, as shown in this screenshot. This code will only send to https://vim.simssa.ca/oauth/callback because this was registered as the OAuth "callback URL", which means I can't get such a code to localhost.
image
  • When developing, I need to fetch this code, back to local, in order to send a POST request to oauth2/access_token using code as query parameter. The response of this POST request will contain an access_token, which I need to make the consequent API calls (e.g., APIs for publishing names/images). That's where I got stuck.

@dchiller
Copy link
Contributor

dchiller commented Jan 10, 2025

Gotcha! So what I'm suggesting is that, in that last screenschot, you manually change vim.simssa.ca to localhost in your address bar, you're replicating the workflow for local development. (1) You know that the oauth process sends you to the right place (vim.simssa.ca/oauth/callback?code=....) and (2) once you change vim.simssa.ca to localhost in the address bar you'll be able to see how UMIL does or does not handle the callback in development.

If your local site doesn't work when you make that manual change, then, if I'm understanding the issue correctly, the production site won't either.

@kunfang98927
Copy link
Contributor Author

Thank you for the suggestion! I changed the vim.simssa.ca to localhost and got this error message...

image

I should ask ChatGPT for troubleshooting.

@kunfang98927
Copy link
Contributor Author

The following is from ChatGPT

Verify the redirect_uri
The redirect_uri in your POST request must match exactly the redirect_uri registered in your Wikidata OAuth2 consumer settings.
Registered URL: https://vim.simssa.ca/oauth/callback
If you're testing locally, manually changing it to http://localhost:8000 in the address bar won't work because it's not registered with Wikidata.
Solution: The only way to test locally without modifying the registered redirect_uri is to use a tunneling tool (e.g., ngrok) or test directly on the production server where the redirect_uri matches.

@ahankinson
Copy link
Member

Make your local machine vim.simssa.ca by editing the hosts file on your machine? Since it’s all client side your browser won’t know that it’s not communicating with the “real” service.

@kunfang98927
Copy link
Contributor Author

Make your local machine vim.simssa.ca by editing the hosts file on your machine? Since it’s all client side your browser won’t know that it’s not communicating with the “real” service.

Thank you for the suggestion! I'll try to learn how to edit hosts file on my machine.

@dchiller
Copy link
Contributor

@kunfang98927 RE: the discussion in meeting

Did you map vim.simssa.ca to 127.0.0.1? And then what port is the vim server listening on your local machine? Are you trying to access that port?

And then, can you share where the code is that handles the redirect?

@kunfang98927
Copy link
Contributor Author

kunfang98927 commented Jan 17, 2025

@kunfang98927 RE: the discussion in meeting

Did you map vim.simssa.ca to 127.0.0.1? And then what port is the vim server listening on your local machine? Are you trying to access that port?

And then, can you share where the code is that handles the redirect?

@dchiller Yes, I add 127.0.0.1 vim.simssa.ca in my hosts file as administrator. And when I run ping vim.simssa.ca, I got "Pinging vim.simssa.ca [127.0.0.1] with 32 bytes of data: ...", which means that the mapping does work.

When developing, the vim server is running on localhost:8000.

After I add this line (127.0.0.1 vim.simssa.ca), when I run the redirecting code, it will go to vim.simmsa.ca/oauth/callback?code=<...> but I got this:

Image

Same if I go to vim.simssa.ca:8000

Image

Here's the code of how I implement the redirecting:

  1. addNameModal.html
<button type="button" class="btn btn-primary" id="confirmPublishBtn">
  Publish
</button>
  1. The listener of the above button (in AddName.js)
document
  .getElementById('confirmPublishBtn')
  .addEventListener('click', function () {
    ...
    // Send the request to publish
    fetch('/publish_name/', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]')
              .value,
      },
        body: JSON.stringify({
            wikidata_id: wikidataId,
            entries: entries,
            publish_to_wikidata: publishToWikidata,
            account_option: accountOption,
        }),
    })
    .then((response) => response.json())
    ...
...
  1. urls.py
...
    path("oauth/authorize/", wikidata_authorize, name="wikidata_authorize"),
    path("oauth/callback/", wikidata_callback, name="wikidata_callback"),
    path("publish_name/", publish_name, name="publish_name"),
...
  1. views/publish_name.py
@login_required
def publish_name(request):
...
      access_token = request.session.get("wikidata_access_token")
      if not access_token:
          redirect_url = (
              f"{reverse('wikidata_authorize')}?next={request.path}"
          )
          return redirect(redirect_url)
...
  1. views/wiki_apis.py
WIKIDATA_OAUTH_URL = "https://www.wikidata.org/w/rest.php/oauth2"
WIKIDATA_REDIRECT_URI = "https://vim.simssa.ca/oauth/callback"

def wikidata_authorize(request):
    # Get the current target URL from the request
    next_url = request.GET.get("next", "/")
    request.session["next"] = next_url
    # Construct the authorization URL
    base_url = f"{WIKIDATA_OAUTH_URL}/authorize"
    params = {
        "response_type": "code",
        "client_id": WIKIDATA_CLIENT_ID,
        "redirect_uri": WIKIDATA_REDIRECT_URI,
    }
    authorization_url = f"{base_url}?{urllib.parse.urlencode(params)}"
    return redirect(authorization_url)

def wikidata_callback(request):
    authorization_code = request.GET.get("code")
    if not authorization_code:
        return JsonResponse({"error": "Authorization code not provided"}, status=400)

    # Exchange the authorization code for an access token
    base_url = f"{WIKIDATA_OAUTH_URL}/access_token"
    data = {
        "grant_type": "authorization_code",
        "code": authorization_code,
        "client_id": WIKIDATA_CLIENT_ID,
        "redirect_uri": WIKIDATA_REDIRECT_URI,
    }

    response = requests.post(base_url, data=data, timeout=50)
    if response.status_code == 200:
        access_token = response.json().get("access_token")
        request.session["wikidata_access_token"] = access_token
        next_url = request.session.get("next", "/")
        return redirect(next_url)
    else:
        return JsonResponse({"error": response.json()}, status=response.status_code)

@kunfang98927
Copy link
Contributor Author

What I want to add is that I think the wikidata_authorize is successfully called, as it will generate the correct url https://www.wikidata.org/w/rest.php/oauth2/authorize?response_type=code&client_id=4b8617100ef01f44476115fb787d9d18

I think where we are stuck is that the wikidata_callback wasn't called properly.

@ahankinson
Copy link
Member

You need a web server to proxy your Django app from port 443 to port 8000 on your local machine.

You will also probably need the SSL certificates locally so that ssl works. You could also do a self signed certificate.

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

No branches or pull requests

3 participants