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

Just started throwing InvalidAccessToken exception #578

Open
ron-sass opened this issue Dec 28, 2022 · 10 comments
Open

Just started throwing InvalidAccessToken exception #578

ron-sass opened this issue Dec 28, 2022 · 10 comments

Comments

@ron-sass
Copy link

My Python scripts that are based on canvasapi have stopped
working in the last 10 days. (Definitely worked on 12/19/2022,
was not working on 12/27/2022 and hasn't worked since.)

Just in case something changed locally, I uninstalled
canvasapi-2.2.0 and installed canvasapi-3.0.0 ... removed some
cruft from Python 3.9 and generally scoured my laptop for any
other left over stuff.

Since the canvasapi package code had not changed, my best guess
is that something canvasapi depends on changed but before I
start sifting through the code, I thought I would ask if others
have experienced the same problem.

Minimum (non)working example:

#!/usr/bin/python3
from canvasapi import Canvas
URL = 'https://uncc.instructure.com/'
KEY = '999999999999999999999999999999999999999999999999999999999999999999999'
canvas = Canvas(URL,KEY)
course = canvas.get_course(182727)

Results in an exception:

canvasapi.exceptions.InvalidAccessToken: [{'message': 'user authorization required'}]

However, I've checked and double checked access key ... it is the same one
that has been working for 2+ years and it has not expired. Furthermore, I
issued the same request from the command line:

curl https://uncc.instructure.com/api/v1/courses/182727 -X GET -H 'Authorization: Bearer 999999999999999999999999999999999999999999999999999999999999999999999'

and I get a reasonable JSON response:

{"id":182727,"name":"Logic System Design","account_id":108,"uuid":"7DbizAXeda7de7vOWXO8k1B9nfLKkSsDbmUoGoFO","start_at":null,"grading_standard_id":null,"is_public":false,"created_at":"2022-04-04T10:45:13Z","course_code":"202280-ECGR-2181-001:ECGR-2181-002-XLSEO202280_Combined","default_view":"wiki",...}

I'm hoping I am not doing something embarrassingly stupid ... but I'm stumped. Plus I'm traveling so I can't test on a clean system right now.

Ron

Additional info:

rick (master *)❱ pip show canvasapi
Name: canvasapi
Version: 3.0.0
Summary: API wrapper for the Canvas LMS
Home-page: https://github.com/ucfopen/canvasapi
Author: University of Central Florida - Center for Distributed Learning
Author-email: [email protected]
License: MIT License
Location: /home/rsass/.local/lib/python3.10/site-packages
Requires: arrow, pytz, requests
Required-by:

rick (master *)❱ python3 --version
Python 3.10.6

@Thetwam
Copy link
Member

Thetwam commented Dec 28, 2022

Hey @ron-sass, sorry you're running into issues. As you mentioned, the CanvasAPI code hasn't changed so it must be something upstream.

Canvas did release an API update on the 20th, which aligns with your timeline, but there's nothing in the description that would lead me to expect it to break.

I won't be able to dive deep into this until the new year, but in the meantime you can try a few things:

  1. Ensure your URL is properly formatted. CanvasAPI does try to strip trailing slashes but maybe something weird happened, so just in case try URL = "https://uncc.instructure.com"
  2. Try with a new Access Token. I understand that the one you have is valid, but see if a freshly-created one performs differently.
  3. To validate the token, instead of grabbing a course, try to use the get_current_user function. This will check that the token is valid and working with CanvasAPI without having to worry about permission issues with the token. user = canvas.get_current_user()

Unfortunately, that's all I can offer for now. If you're still experiencing the problem next week I'd be happy to take a closer look.

@ron-sass
Copy link
Author

Thanks for the super-fast response! I tried your suggestions but no luck; details below:

  1. URL with or without the trailing slash fail with the same exception
  2. my first thought was that my token had expired but that was not the case, just to double-check, I did create a new token and got the same results
  3. to validate the token, I tried the get_current_user() method but that failed too (different exception, see below) ... I also tried from the command line and curl with the access token returned the correct JSON record with my id/information

I do appreciate the fast response and I appreciate your willingness to look into it next week. We are on break as well, so it is not a crisis this week. Have a good holiday!

Ron

Additional information .... when I used the get_current_user() method, it didn't throw the InvalidAccessToken exception. Rather it threw ResourceDoesNotExist("Not Found") exception. I verified with curl that I do exist :-) and I used the web interface to Canvas to double check as well.

@jessemcbride
Copy link
Member

@ron-sass canvasapi can be configured to output logs of the network calls it makes which might help troubleshoot this further. I have a feeling the request being prepared and sent through Python is different than the one from curl, despite the tokens being the same.

@MarkusvonStaden
Copy link

I just started using the lib, but I have the same problem. I just get
canvasapi.exceptions.InvalidAccessToken: [{'message': 'Invalid access token.'}]

@Thetwam
Copy link
Member

Thetwam commented Jan 4, 2023

Hey @MarkusvonStaden, sorry to hear you're having trouble with the library. Please test that your access key is valid via an external process, such as the Python requests library, curl, or Postman. Please also take the steps in our Troubleshooting Guide to check your url and access token.

@ron-sass @MarkusvonStaden If the issues persist, please configure logging and send us the result so we can further diagnose the issue.

This code snippet should do the trick, all you need to do is fill in your url and access token:

import logging
import sys

from canvasapi import Canvas

# logging
logger = logging.getLogger("canvasapi")
handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

API_URL = ""  # CHANGE THIS VALUE
API_KEY = ""  # CHANGE THIS VALUE

canvas = Canvas(API_URL, API_KEY)

print("BASE URL:")
print(canvas._Canvas__requester.base_url)

me = canvas.get_current_user()

print("Response:")
print(me)

@ron-sass
Copy link
Author

ron-sass commented Jan 5, 2023 via email

@ron-sass
Copy link
Author

ron-sass commented Jan 5, 2023

One more piece of information ...

I took a peek at url just before it requests.session.get() is called and it looks correct. So at this point, it would be below canvasapi in the Python requests package.

I am running the latest PopOS (an Ubuntu-like distribution). I checked to make sure I wasn't using a custom version of requests. I'm not. But it is a little bit older than what is on PyPI right now ...

Mine:

rick (master *)❱ pip show requests
Name: requests
Version: 2.25.1
Summary: Python HTTP for Humans.
Home-page: https://requests.readthedocs.io
Author: Kenneth Reitz
Author-email: [email protected]
License: Apache 2.0
Location: /usr/lib/python3/dist-packages
Requires:
Required-by: canvasapi

From [https://pypi.org/project/requests/] it appears 2.28.1 is the latest and greatest.

When I'm back in my office I can test more easily on a different machine / different distribution.

Ron

@MarkusvonStaden
Copy link

I solved my problem, it was just a regular user error. Apperently I am not smart enough to read the dokumentation... I used a developer key instead of the API Key

@ron-sass
Copy link
Author

ron-sass commented Jan 6, 2023 via email

@ron-sass
Copy link
Author

ron-sass commented Jan 7, 2023

I tracked down the problem! It was a local issue but for completeness, I'll describe what happened.

TL;DR : Python requests module always reads $(HOME)/.netrc file and it overrides authorization passed via a headers dictionary (which is what canvasapi passes to requests); simple solution is to avoid using/remove .netrc file

For those that are interested, I had to dig into the requests' session.py code and in the prepare_request method, it checks if auth was set when the session object is created. If it has not been set, then it tries the .netrc file and if finds anything then that overwrites the authorization key/value passed in the headers dictionary with the session.get method.

One solution might be for canvasapi to set the authorization (bearer access-token) when session is instantiated (and not pass it in the headers to the sessions.get call) . But, in my case, I only needed the .netrc for a while because I was developing an embedded system solution and was repeatedly ftp'ing an image. The .netrc file just saved me a lot of typing but I don't need it anymore. So just removing the .netrc solved my immediate problem, my canvas scripts are working, and I am ready to start classes on Monday!

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

4 participants