Closed ojhaashish13 closed 3 years ago
Hello @ojhaashish13, I'd be happy to help troubleshoot the issue you are seeing!
The "JWS signature invalid" error response generally indicates one of three things. You've already done some good debugging, so we can probably rule some of these out:
sub
in the client_assertion
does not existsub
in the client_assertion
does not have an associated public keyclient_assertion
was invalid in some way or used an unexpected algorithm.Just to be very sure, I'll run through verifying each of these potential issues.
All of these steps will require accessing the Canvas rails console. If you are running Canvas without Docker, this can be done with bundle exec rails c
in the canvas-lms
repository.If you are using Docker with your Canvas setup, this can be done with docker-compose run --rm web rails c
I'm quite sure you've already done this from the UI, but let's double-check.
Judging by the client_assertion
you provided as your example, your Developer Key ID is 10000000000001
From the Canvas Rails console, run the following:
key = DeveloperKey.find(10000000000001)
ap key
If no exception is thrown, we can conclude that the developer key exists.
It also sounds like you've confirmed this, but let's double-check
From the same Rails console, run the following:
key = DeveloperKey.find(10000000000001)
# One of the following two lines should print your public key or public key URL
key.public_jwk
key.public_jwk_url
If one of the last lines printed your public key in JWK format (or URL pointing to it) we are good to go here.
client_assertion
signature validation Canvas is working as you expect:From the same Rails console, run the following:
key = DeveloperKey.find(10000000000001)
# I'm just using the client assertion from your example, but please update with a newly created assertion so
# the iat and exp claims are within valid ranges.
client_assertion = ''eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjNPaVdic1RwQzRlZEZvSkdqbGlGemdGUVFmZ0JIblBrTGJ1RWpYS2tiaG1VbllqRHNjYWdsaEllRU1RZUpWQnYifQ.eyJpc3MiOiJodHRwczovL3N0YWdpbmcubXlkb21haW4uY29tIiwic3ViIjoiMTAwMDAwMDAwMDAwMDEiLCJhdWQiOiJodHRwczovL2NhbnZhcy5teWRvbWFpbi5jb20vbG9naW4vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNjIwNzk2OTQ4LCJleHAiOjE2MjA3OTcwMTMsImp0aSI6Imx0aS1zZXJ2aWNlLXRva2VuYmRmMzlkNTFmMDYxNmZhMWMzMGJkYTJmYTQ2YWU3NmFmZjI3YjFlMTU2YWZiNmVmYjU2MTBlMDU3ZWUwMWM3ZiJ9.bSELJ3HQSQJQpeh75x_OOfBAZIWrMprYD9bK7S6nA1NUi483Yxgk2MDT6ZYRP9-eI03HoQdr9aP2Wv121qm9SuMO0KLUZgQ01rO3GmfyZhOS9yat0AVJvOxiEyRNSJD9W4M4ZcHBPw8UJ_KnywGCKRKRiBBih2JLoquwmP9NomHNvKlW--9pUM3amGH1z9P940kJIqdcVulSTDw2VUBnsjd1J6ngkG4DKgi1BwDaldhhU0yPzkiAO-UJRJHoqrxkYnYfJ5Q_Y6SnvgsHKAMiRNnhHKcqQetWh_4mTYl0Qmh3h6B6EafjVdxIdcMiIyCJGz3cUn8_XigCu1qPXBvEwA"
key = DeveloperKey.find(10000000000001)
# Attempt to decode the JWT with signature verification:
# Note that this assumes your developer key has a public_jwk rather than a
# public_jwk_url
JSON::JWT.decode(client_assertion, JSON::JWK.new(key.public_jwk), :RS256)
The above code should not raise any exceptions. If an exception is raised, the name of that exception should help point you towards the problem.
One other thing I noticed was that the aud
claim in the client_assertion
may not be correct.
Currently, it is set to https://canvas.mydomain.com/login/oauth2/token
. The aud
claim should exactly match the URL you are making a request to when retrieving the access token.
Is https://canvas.mydomain.com
where your local Canvas is hosted? If it is not, you should update the aud
to match where your local Canvas is hosted (including port number).
Here is an example aud
for my personal Canvas development environment (Docker):
{
"iss": "ltitesttool.docker",
"sub": "10000000000005",
"aud": "http://canvas.docker/login/oauth2/token",
"iat": 1620921299,
"exp": 1620921899,
"jti": "777a1ccd-58cb-4645-8db6-a8aab6b5e7e4"
}
Thank you so much for the detailed debug instructions. I followed your suggestions and solution #2. "Verify the key has an associated public key" worked. In my case, both JWKS Url and JWKS JSON added to the tool configuration. I updated the tool configuration, kept only JWKS token; removed the JWKS Url and it worked.
No problem! I'm glad you got it sorted out.
Summary:
Oauth2 endpoint post token service "/login/oauth2/token" throwing 400 status response with "JWS signature invalid" error. I have used correct endpoint, parameters and used post method to call the URL https:///login/oauth2/token. My JWT data is valid as per jwt.io debugger when used public key to validate signature.
Steps to reproduce:
I am working on LTI 1.3 integration + Assignment grade services.
Decoded JWT: Header:
Payload:
I can verify the JWT data place inside the "client_assertion" field using my public key and as per JWT.io debugger signature is valid.
I am totally stuck and no idea how to fix this or debug it further, please suggest a solution.
Expected behavior:
It should generate the access token.
Actual behavior:
Throwing 400 header status with mentioned error
{"error":"invalid_request","error_description":"JWS signature invalid."}
Additional notes: