401 Error with LTI 1.3 Service Tokens

Jump to solution
william_diehl
Community Novice

Greetings all,

I'm writing an LTI 1.3 implementation and have the basics up and running but no matter what I do I cannot get service tokens to work.

I can successfully generate a token by POSTing a request to /login/oauth2/token with a grant_type of client_credentials and a properly formed JWT signed with my private key. The server returns what looks like a legitimate token - the response has valid token_type, expires_in, scope, and of course access_token values. The access_token is itself a HS256 JWT that has what look like the expected values for things (but that doesn't matter as the token content is supposed to be opaque to an LTI tool).

The problem is no matter where I try to use the thing I get a 401 Unauthenticated "user authorization required" error with a WWW-Authenticate: Bearer realm="canvas-lms" header. I'm adding the generated access_token value as an "Authorization: Bearer xxxxxx" HTTP header (I've also tried it as a URL parameter with the same result).

I've tried the token with the Line Items, Scores, Results, and Names and Roles /lti/ APIs but all with the same result. There's so little documentation out there (which is mind boggling to me) but as far as I can tell by picking apart the IMS LTI 1.3 standards and OAuth docs I'm doing things right... but of course I must not be.

I realize this is a really basic error question without a lot of additional details, but the error response doesn't tell me if the token is invalid, expired, or if I have insufficient permissions - it's almost like it's not seeing it at all. But I've replayed the same request in fiddler to other, non-LTI REST API calls and it tells me the token is invalid (as it's a different kind than the normal OAuth2 tokens used by the rest of the API) so my HTTP requests are at least formed properly.

Here's the token I get back:

{
access_token = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2NhbnZhcy5iZXRhLmluc3RydWN0dXJlLmNvbSIsInN1YiI6IjExMzY4MDAwMDAwMDAwMDAzOCIsImF1ZCI6Imh0dHBzOi8vY2FudmFzLmJldGEuaW5zdHJ1Y3R1cmUuY29tL2xvZ2luL29hdXRoMi90b2tlbiIsImlhdCI6MTU2MzkwODQwMiwiZXhwIjoxNTYzOTEyMDAyLCJqdGkiOiI3MjI4MDk0MC1lMzk3LTRhNmEtYmFiMy1jMjUxZGM5MTFmZGQiLCJzY29wZXMiOiJodHRwczovL3B1cmwuaW1zZ2xvYmFsLm9yZy9zcGVjL2x0aS1hZ3Mvc2NvcGUvbGluZWl0ZW0gaHR0cHM6Ly9wdXJsLmltc2dsb2JhbC5vcmcvc3BlYy9sdGktYWdzL3Njb3BlL3Jlc3VsdC5yZWFkb25seSBodHRwczovL3B1cmwuaW1zZ2xvYmFsLm9yZy9zcGVjL2x0aS1hZ3Mvc2NvcGUvc2NvcmUifQ.RXOV4UfmcDWafLBQ5M2VZcmWFPww1Htd966ajLF2jzY,
token_type = Bearer,
expires_in = 3600,
scope = https: //purl.imsglobal.org/spec/lti-ags/scope/lineitem https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly https://purl.imsglobal.org/spec/lti-ags/scope/score
}‍‍‍‍‍‍‍‍‍‍‍‍

All I can think of is that I'm either getting the token from the wrong endpoint (I'm using canvas.beta.instructure.com which is the initial iss value in the Canvas signed JWT I get from the authentication process. I've also used our own beta instance but the tokens appear identical so I just used the iss value since it seemed safer), I'm using the token wrong, or I'm calling the /lti/ APIs wrong in the Canvas REST endpoints.

Any advice?

Thanks very much!!

Labels (1)
0 Likes
1 Solution
william_diehl
Community Novice
Author

Think I might have found it, thanks to whatever wonderful soul posted this google doc:

LTI 1.3 Quick Start - Google Docs 

... found in this also very helpful thread:

LTI 1.3 & LTI Advantage Documentation 

6/4/2019:

Current bug with Advantage services: Please enable the “Beta and Test Access For Students” if you want to use AGS or NRPS in beta. Tools working in beta/test will get a 401 error when attempting to use a client_credetials grant token if the “Beta and Test Access For Students” setting is disabled in the account. Canvas attempts to check this setting against a user, but since the client_credentials grant has no user, the check for this setting fails, giving a 401.

Now I just have to figure out how to enable student access in our account to verify...

View solution in original post