Celebrate Excellence in Education: Nominate Outstanding Educators by April 15!
Found this content helpful? Log in or sign up to leave a like!
i have a python script that attempts to get assignments using the graphql API and replicating the request send when you klick the execute button (note we neither can nor will ever use oath2 because we do not have the resources to get verified )
#!python
import browser_cookie3
import requests
import json
cj = browser_cookie3.chromium(domain_name='iusd.instructure.com')
print(cj)
def send(cj):
token = None
for i in cj:
if "<Cookie _csrf_token=" in str(i):
token = str(i).replace("<Cookie _csrf_token=","").replace(" for iusd.instructure.com/>","")
url = "https://iusd.instructure.com/api/graphql"
headers = {
"accept": "application/json+canvas-string-ids, application/json, text/plain, */*",
"accept-language": "en-US,en;q=0.9",
"baggage": "sentry-environment=Production,sentry-release=canvas-lms@20250409.326,sentry-public_key=355a1d96717e4038ac25aa852fa79a8f,sentry-trace_id=a62f30e1b8bc4d8bbedaa00fb431462d",
"content-type": "application/json",
"priority": "u=1, i",
"sec-ch-ua": "\"Chromium\";v=\"133\", \"Not(A:Brand\";v=\"99\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Linux\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"sentry-trace": "",
"x-csrf-token": token,
"x-requested-with": "XMLHttpRequest"
}
# GraphQL query
query = """
{
allCourses {
name
_id
submissionsConnection(filter: {states: submitted}) {
nodes {
gradingStatus
submissionStatus
submittedAt
state
assignment {
_id
name
}
user {
_id
name
sisId
email
enrollments {
state
course {
_id
}
}
}
}
}
term {
sisTermId
name
}
}
}
"""
payload = json.dumps({
"query": query,
"variables": None
})
try:
response = requests.post(url, headers=headers, data=payload,cookies=cj)
print(response.request.headers)
response.raise_for_status() # Raises an HTTPError if the response code was unsuccessful
print(response.json())
return response
except requests.exceptions.HTTPError as errh:
print(f"HTTP Error: {errh}")
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
send(cj)
the current code uses browser_cookie3 to gain all the cookies from a canvas instance (in this case a institution i am part of) and then it attempts to list assignments however we get a 422 error.
i understand that the csrf token refreshes after each request but this was after the last request was in browser. we need the data to create a todolist and no asking our clients to generate devkeys is not going to cut it
HTTP Error: 422 Client Error: Unprocessable Entity for url: https://iusd.instructure.com/api/graphql
Hi @sakura_GX,
I know you're asking for technical guidance here, which I unfortunately don't have quite enough knowledge to give you.
That being said, as a Canvas Administrator, the method you're describing here concerns me. What you're describing is essentially hijacking/borrowing/stealing (depending on one's point of view) authentication from outside of your script. You mentioned oauth2 was out of the question because you don't have the resources to get verified, but that is the most accepted workflow precisely because there is an approval flow to allow schools/institutions to evaluate 3rd party tools and ensure they meet our individual standards.
You haven't quite stated the overall purpose of your tool or how you plan to market/distribute it, so I'll admit I'm making some assumptions... Since it's trying to get assignments and get a to-do, I'm guessing it's made for students, but it could also be for faculty. Since you're asking about this authentication method, I'm also guessing that you plan to distribute it direct to end users somehow. And finally, since you're using python, I'm guessing you want this to be some sort of standalone app, not a browser extension or something like that. If my guesses are correct, my honest advice would be to re-evaluate your plan. I am not a lawyer, but I could certainly see this method becoming a legal issue, and that's probably a battle you don't want to have.
The closest thing to what you're describing here is a browser extension, which is still a bit of a gray area, but generally accepted. I don't know for certain if popular extensions use the csrf cookie authentication, but my guess is that it's likely, though it could be viewed a bit differently since everything is really contained in the browser session. @Code-with-Ski may be able to comment on this if he has time and is willing.
I apologize for taking the thread off the intended track a bit, but I think this is an important discussion point, and something to consider now before you get further into development, especially if this is more than a personal project.
Others with more experience in GraphQL and authentication may be able to chime in on the technical aspects you asked about if they come across this thread.
-Chris
i am trying to list assignments to create a todo list. i have a project for my CS class to create a app for the school i decided to go with a todolist with integration for canvas (maybe gclassroom if i figure out their API).
as for the approach it is kind of questionable but i am a highschool student so i don't exactly have the resources needed to get approval (my districts IT is handled off-site so the local IT-guy could not do anything, even then it is questionable if they would let me get a App key) + i wanted it to not depend on the district (so if i went to college and they used canvas it would still work). and this is easier than requiring the end-user to download a seperate browser extension + i am not good at js.
i took the cyberforward coastline ROP class where we learned vulnerability analysis and i know that having unintended ways to access data may be a concern, i understand your concerns, even when i discovered the _csrf_ cookie used to deter cross site request forgeries i thought what i am doing is eerily similar
so then why did i choose this approach:
i needed to consider my limitations (not being able to get approval) and how i could create a todo list
i could have a browser extension but again i am not good at js,
i could ask the user to generate & input a devkey but that is both bad UX and also it would probably be
less secure, instead of needing to user to at least log-in to canvas now we have however many devkeys they generated (let's say they forgot the first one) potentially active and stored in unsafe locations
i could try to get a app-key from the district but that is unlikely to happen and would be slow todo and would expose another set of questions: given i am a student how they make sure i don't abuse it to get access to all the quizz answers for example
i could have a browser extension but i am bad at js and i want a external application (if i used some kind of extension to fetch the data from canvas and store it somewhere installation would be more complex and then it is more difficult to view the code else i could potentially hijack my instructors canvas account to give myself an A )
also the data i am trying to access is already available for the user, everyone can go to the graphql page and manually run the query, so it is not like i am doing anything unintended (i am using intended features in a weird way - yes but i am not hacking canvas nor do i possess the skills todo so )
i could even use selenium webdriver to access the canvas page and scrape it but that would be more complicated,
there is one thing i want to state to all administrators:
we need a unified secure API to get a users assignments / when they are due (maybe even grade points possible to prioritize higher point assignments or some other info like grades of user) that is easy to use and integrate with 3rd party applications (design it so we can allow every application and don't need a whitelist, so don't share sensitive data accross it, also have the user consent to every app / feature). some of my teachers just put upcoming assignments on a google doc or modules page but then i have to (ab)use the google api to copy the doc and scrape the data or the canvas api in weird ways, or klick like 7+ times to navigate to it and have a uglier-noninteractive UI. i am sure you understand,
To participate in the Instructure Community, you need to sign up or log in:
Sign In