Hey bertscjn1 I'm so glad you asked this question! I went through a similar period of watching videos, studying others' shared solutions in GitHub, teaching myself as much as I could, meticulously following the documentation... yet no matter what I did, the Canvas API would only return a CORS error saying the Access-Control-Allow-Origin header is missing. I began to suspect the whole Canvas API was a big useless joke, or something, because it seemed impossible. Good thing I didn't give up hope! 😂
I'll explain my situation and what worked for me, in case it helps someone else.
So I have a java web application that is connected to our Canvas using LTI 1.3. Until now, I got everything I needed through the Custom Fields in our LTI Key under Additional Settings (i.e. as variable substitutions, documented here: https://canvas.instructure.com/doc/api/file.tools_variable_substitutions.html). However, my latest application requires a list of individual assignment submissions and grades. It didn't seem like I could get that from the LTI variable substitutions, and I thought, it really seems like I need a Canvas API call.
For my first attempt at making a Canvas API call, which failed, I tried accessing a test endpoint using javascript (ex: /api/vi/courses). I had hoped I could leverage the Oauth2 flow I had already configured for the LTI 1.3 setup, but after much fiddling I determined that wouldn't work. I concluded I'd have to replicate the Oauth2 flow all over again separately for the Canvas API. So in javascript, I carefully followed the Oauth2 flow described in the documentation (https://canvas.instructure.com/doc/api/file.oauth.html) and sent all my GET and POSTs using $.ajax() and fetch() calls. I followed Step 1, Redirect users to request Canvas access, and sucessfully received the "special code" back in my application's request_uri. However, I got stuck on Step 3. Whenever I tried to send the POST request with this code back to the specified URL. i.e. https://MYINSTITUTION.test.instructure.com/login/oauth2/token, it would give me the CORS error, saying the Access-Control-Allow-Origin header is missing. It didn't seem to matter that my application was already set up with a correct LTI 1.3 connection, and that I had a valid code: it didn't work, and I was stuck at step 3 like an impassable brick wall!
The solution that worked for me was is that I had to ditch the javascript approach, and instead, I realized I had to send my Canvas API calls from my application's server side. For Step 3, I ended up using Java Spring's WebClient (https://docs.spring.io/spring-framework/reference/web/webflux-webclient/client-body.html), like this:
//this is step 3, done in my application's server side java code
WebClient webClient = WebClient.create();
String myJSONresponse = webClient.post()
.uri("https://MYINSTITUTION.test.instructure.com/login/oauth2/token",
uri -> uri
//for an explanation of needed parameters, see: https://canvas.instructure.com/doc/api/file.oauth_endpoints.html#post-login-oauth2-token
.queryParam("grant_type", "authorization_code")
.queryParam("client_id", <MY_CLIENT_ID>)
.queryParam("client_secret", <MY_SECRET>)
.queryParam("redirect_uri", <URL_TO_MY_APPLICATION>)
.queryParam("code", <CODE_RECEIVED_FROM_STEP_2>)
.build())
.retrieve()
.bodyToMono(String.class)
.block();
//continue to parse result from JSON and do what you need...
To get the above client id, secret, etc. I had to create a new key in Canvas Admin, and this time it has to be a "API Key". So I don't know if this is correct, but, for my case I have both that as well as the "LTI Key" I already have. In the setup of the API Key, the "Redirect URIs" must match the above <URL_TO_MY_APPLICATION>. For <MY_CLIENT_ID>, it's what appears in the "Details" column, and, <MY_SECRET> is the long hidden string that appears when you press the "Show Key" button.
Anyway, the lesson I learned is that I have to make calls to the Canvas API from the server side of my LTI 1.3 application, and NOT from javascript!