Open vandergav opened 3 years ago
Hello! May i ask how you are deploying these servers? The request for keysets is a simple HTTP GET, are you sure the Moodle instance is accessible from within the LTI server?
Hi Carlos, thank you for your reply. There is a proxy in front of my server so I'm not sure if that affects getting the JWT keyset from within the LTI server. Here's my Nginx configuration for reference.
server {
listen 80;
root /var/www/tite_staging/public/www;
server_name staging.tite.rdc.nie.edu.sg;
location /socket.io/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_ssl_session_reuse off;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8086/socket.io/;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_ssl_session_reuse off;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8086/;
}
error_page 500 502 503 504 /errorPages/50x.html;
location /errorPages/ {
root /var/www/tite_staging/public/www;
}
location /50x_files/ {
root /var/www/tite_staging/public/www/errorPages;
}
}
If all else fails, I will try the other methods for authConfig
:
May I check for JWK_KEY, do I use the keys from https://staging.tite.rdc.nie.edu.sg/keys or https://moodle.tite.rdc.nie.edu.sg/mod/lti/certs.php. Also wondering what the difference is between these 2 endpoints. Thanks so much again for your help.
The /keys endpoint on your LTI server contains the public keys used by the Platforms to validate messages signed by your Tool. the /certs.php endpoint on moodle contains the public keys used by your Tool to validate messages signed by Moodle.
You can try using JWK_KEY with a key from Moodle's certs.php endpoint if you know the kid of the key used to sign messages to your tool.
As a test you can try to make an http request "manually" from within your tool, after the setup, to see if the certs.php URL is reachable. You can install the 'got' package or any other you feel comfortable with and do a const res = await got.get('https://moodle.tite.rdc.nie.edu.sg/mod/lti/certs.php')
or something like it.
Hi Carlos, thank you for your reply and suggestions. I have tried making a http request, with https.get(...
, after the setup but seems like the /certs.php endpoint can't be hit for some reason.
I then tried the RSA_KEY method and it worked so I'll take this as a (temporary) workaround for the "Retrieving key from jwt_set" issue for now.
However, I am now facing an issue when using the lti.NamesAndRoles.getMembers
method. Based on the logs, the request seems to get stuck at awaiting return from the platform
I then looked into Utils/Auth.js:
/**
* @description Gets a new access token from the platform.
* @param {String} scopes - Request scopes
* @param {Platform} platform - Platform object of the platform you want to access.
*/
static async getAccessToken (scopes, platform, ENCRYPTIONKEY, Database) {
const platformUrl = await platform.platformUrl()
const clientId = await platform.platformClientId()
const confjwt = {
sub: clientId,
iss: clientId,
aud: await platform.platformAuthorizationServer(),
jti: encodeURIComponent([...Array(25)].map(_ => (Math.random() * 36 | 0).toString(36)).join``)
}
const token = jwt.sign(confjwt, await platform.platformPrivateKey(), { algorithm: 'RS256', expiresIn: 60, keyid: await platform.platformKid() })
const message = {
grant_type: 'client_credentials',
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
client_assertion: token,
scope: scopes
}
provAuthDebug('Awaiting return from the platform')
const access = await got.post(await platform.platformAccessTokenEndpoint(), { form: message }).json()
provAuthDebug('Successfully generated new access_token')
await Database.Replace(ENCRYPTIONKEY, 'accesstoken', { platformUrl: platformUrl, clientId: clientId, scopes: scopes }, { token: access }, { platformUrl: platformUrl, clientId: clientId, scopes: scopes })
return access
}
}
and Platform.js:
/**
* @description Sets/Gets the platform access token endpoint used to authenticate messages to the platform.
* @param {string} [accesstokenEndpoint] - Platform access token endpoint.
*/
async platformAccessTokenEndpoint (accesstokenEndpoint) {
if (!accesstokenEndpoint) return this.#accesstokenEndpoint
await this.#Database.Modify(false, 'platform', { platformUrl: this.#platformUrl, clientId: this.#clientId }, { accesstokenEndpoint: accesstokenEndpoint })
this.#accesstokenEndpoint = accesstokenEndpoint
return accesstokenEndpoint
}
I guess it might have to do with the accesstokenEndpoint, @param {string} accesstokenEndpoint - Access token endpoint for the platform.
I will continue looking into this and update again if theres anything
Yes, this seems to be the same issue. Moodl's endpoints not being accessible from within your Tool
Hi Carlos, may I know if the @param {string} accesstokenEndpoint - Access token endpoint for the platform
refers to the accesstokenEndpoint: 'https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php'
specified in lti.registerPlatform
for setup?
Anyway I have tried to access the keyset after setup using:
axios.get('https://moodle.tite.rdc.nie.edu.sg/mod/lti/certs.php')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
and got back the keyset. So now i'm not sure what the issue is. Thanks
I think I should mention that my tool and moodle site are running on the same server. Maybe it has something to do with this...
Hello! Yes, the accesstokenEndpoint is the token.php endpoint on moodle.
So you are now able to access the keyset? Are you able to access the https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php endpoint from within your server?
Hi, yes I was able to access the keyset but only by using axios
. I tried with the got
library and the request timeout-ed while waiting for the response. Here are the 2 ways I did the HTTP calls after setup().
axios
returned the key
axios.get('https://moodle.tite.rdc.nie.edu.sg/mod/lti/certs.php')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
got
did not
(async () => {
try {
console.log('trying got http request')
const res = await got.get('https://moodle.tite.rdc.nie.edu.sg/mod/lti/certs.php')
console.log(res);
} catch (error) {
console.log(error);
}
})();
I'm using "ltijs": "^5.7.3", "ltijs-sequelize": "^2.4.2", "got": "^11.8.2",
Thanks
To add, everything works fine on my local. It is only on my server where I am having issues with the got
library presumably.
Adding the parts of the library that use got
,
Utils/Auth.js:
const res = await got.get(keysEndpoint).json()
const access = await got.post(await platform.platformAccessTokenEndpoint(), { form: message }).json()
Found this from the got
repository. Thinking if it might be a proxy issue and if so, would need to tweak my nginx config file.
https://github.com/sindresorhus/got/issues/1678
Hello, i am unable to reproduce the error. Could you please try the fix presented in the issue you mentioned and let me know if it works?
Hi Carlos,
Hope you've been well.
I have been trying to solve the issue and so far have narrowed it down to the got
library. Somehow the got
library doesn't seem to be sending out the requests from my server to hit the proxy in front of it. So, as a workaround I am trying to change the parts of ltijs
that use got
to axios
in my node_modules folder and rebuilding my app.
So far I have only changed some files of ltijs
used by my app:
Auth.js
NamesAndRoles.js
However it seems like now it is failing at generating a new access_token when I call the getMembers()
method of the NamesAndRoles
class,
My App
Auth.js
const access = await axios.post(await platform.platformAccessTokenEndpoint(), { ...
returns a data: { error: 'invalid_request' }
and status 400 Bad Request:
Not sure if this is an issue with my axios
post request but if you have any pointers for me that'll be great (I have checked that await platform.platformAccessTokenEndpoint()
for Auth.js returns a valid url, https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php)
Looking at the logs just before the error,
NamesAndRoles.js
Platform.js
Auth.js (axios
error happens here)
Failed at const access = await axios.post(await platform.platformAccessTokenEndpoint(), { ...
Full logs:
provider:main Receiving request at path: /login +17m
provider:main Receiving a login request from: https://moodle.tite.rdc.nie.edu.sg +0ms
provider:main Redirecting to platform authentication endpoint +6ms
provider:main Target Link URI: https://staging.tite.rdc.nie.edu.sg +0ms
provider:main Login request: +1ms
provider:main {
provider:main response_type: 'id_token',
provider:main response_mode: 'form_post',
provider:main id_token_signed_response_alg: 'RS256',
provider:main scope: 'openid',
provider:main client_id: 'EVXFAyRoAkhO2Do',
provider:main redirect_uri: 'https://staging.tite.rdc.nie.edu.sg',
provider:main login_hint: '2',
provider:main nonce: 'yv1w4dege1sep0x5wfr694nf1',
provider:main prompt: 'none',
provider:main state: '9074badcaaaf9a5ca5a7f167f940a82f010c63c6fe37215b31',
provider:main lti_message_hint: '2',
provider:main lti_deployment_id: '2'
provider:main } +0ms
provider:main Receiving request at path: / +144ms
provider:main Path does not match reserved endpoints +0ms
provider:main Cookies received: +0ms
provider:main [Object: null prototype] {
provider:main 'ltiaHR0cHM6Ly9tb29kbGUudGl0ZS5yZGMubmllLmVkdS5zZ0VWWEZBeVJvQWtoTzJEbzI%3D': '2',
provider:main state9074badcaaaf9a5ca5a7f167f940a82f010c63c6fe37215b31: 'https://moodle.tite.rdc.nie.edu.sg'
provider:main } +0ms
provider:main Received idtoken for validation +0ms
provider:auth Response state: 9074badcaaaf9a5ca5a7f167f940a82f010c63c6fe37215b31 +17m
provider:auth Attempting to validate iss claim +17m
provider:auth Request Iss claim: https://moodle.tite.rdc.nie.edu.sg +0ms
provider:auth Response Iss claim: https://moodle.tite.rdc.nie.edu.sg +0ms
provider:auth Attempting to retrieve registered platform +0ms
provider:auth Retrieving key from jwk_set +3ms
provider:auth Converting JWK key to PEM key +54ms
provider:auth Attempting to verify JWT with the given key +1ms
provider:auth Token signature verified +1ms
provider:auth Initiating OIDC aditional validation steps +0ms
provider:auth Validating if aud (Audience) claim matches the value of the tool's clientId given by the platform +0ms
provider:auth Aud claim: EVXFAyRoAkhO2Do +0ms
provider:auth Checking alg claim. Alg: RS256 +0ms
provider:auth Max age parameter: 10 +0ms
provider:auth Checking iat claim to prevent old tokens from being passed. +0ms
provider:auth Iat claim: 1623317100 +0ms
provider:auth Exp claim: 1623317160 +1ms
provider:auth Current_time: 1623317100.224 +0ms
provider:auth Time passed: 0.2239999771118164 +0ms
provider:auth Validating nonce +0ms
provider:auth Nonce: yv1w4dege1sep0x5wfr694nf1 +0ms
provider:auth Tool's clientId: EVXFAyRoAkhO2Do +0ms
provider:auth Storing nonce +2ms
provider:auth Initiating LTI 1.3 core claims validation +6ms
provider:auth Checking Message type claim +0ms
provider:auth Checking Target Link Uri claim +0ms
provider:auth Checking Resource Link Id claim +0ms
provider:auth Checking LTI Version claim +0ms
provider:auth Checking Deployment Id claim +0ms
provider:auth Checking Sub claim +0ms
provider:auth Checking Roles claim +0ms
provider:auth Successfully validated token! +71ms
provider:main Generating ltik +85ms
provider:main Redirecting to endpoint with ltik +0ms
socket connected
provider:main Receiving request at path: /info +954ms
provider:main Path does not match reserved endpoints +0ms
provider:main Cookies received: +0ms
provider:main [Object: null prototype] {
provider:main 'ltiaHR0cHM6Ly9tb29kbGUudGl0ZS5yZGMubmllLmVkdS5zZ0VWWEZBeVJvQWtoTzJEbzI%3D': '2'
provider:main } +0ms
provider:main Ltik found +0ms
provider:main Ltik successfully verified +0ms
provider:main Attempting to retrieve matching session cookie +0ms
provider:auth Valid session found +968ms
provider:main Passing request to next handler +6ms
provider:main Receiving request at path: /members +64ms
provider:main Path does not match reserved endpoints +1ms
provider:main Cookies received: +0ms
provider:main [Object: null prototype] {
provider:main 'ltiaHR0cHM6Ly9tb29kbGUudGl0ZS5yZGMubmllLmVkdS5zZ0VWWEZBeVJvQWtoTzJEbzI%3D': '2'
provider:main } +0ms
provider:main Ltik found +0ms
provider:main Ltik successfully verified +0ms
provider:main Attempting to retrieve matching session cookie +0ms
provider:auth Valid session found +71ms
provider:main Passing request to next handler +7ms
provider:namesAndRolesService Attempting to retrieve memberships +17m
provider:namesAndRolesService Target platform: https://moodle.tite.rdc.nie.edu.sg +0ms
provider:namesAndRolesService Attempting to retrieve platform access_token for [https://moodle.tite.rdc.nie.edu.sg] +4ms
provider:platform Valid access_token for https://moodle.tite.rdc.nie.edu.sg not found +17m
provider:platform Attempting to generate new access_token for https://moodle.tite.rdc.nie.edu.sg +0ms
provider:platform With scopes: https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly +0ms
provider:auth Awaiting return from the platform +1s
platformAccessTokenEndpoint https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php
Error: Request failed with status code 400
at createError (/var/www/tite_staging/node_modules/axios/lib/core/createError.js:16:15)
at settle (/var/www/tite_staging/node_modules/axios/lib/core/settle.js:17:12)
at IncomingMessage.handleStreamEnd (/var/www/tite_staging/node_modules/axios/lib/adapters/http.js:260:11)
at IncomingMessage.emit (events.js:327:22)
at IncomingMessage.EventEmitter.emit (domain.js:467:12)
at endReadableNT (internal/streams/readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
config: {
url: 'https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php',
method: 'post',
data: '{"form":{"grant_type":"client_credentials","client_assertion_type":"urn:ietf:params:oauth:client-assertion-type:jwt-bearer","client_assertion":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImRhYjkyODBmNTllMDg0MWUyZWE0NjY1NjViZWFhYTBkIn0.eyJzdWIiOiJFVlhGQXlSb0FraE8yRG8iLCJpc3MiOiJFVlhGQXlSb0FraE8yRG8iLCJhdWQiOiJodHRwczovL21vb2RsZS50aXRlLnJkYy5uaWUuZWR1LnNnL21vZC9sdGkvdG9rZW4ucGhwIiwianRpIjoibGIxdWtlajd0c25qdncxZjc3eWphOHV0YyIsImlhdCI6MTYyMzMxNzEwMSwiZXhwIjoxNjIzMzE3MTYxfQ.wo2ZFzc9j_GZDiNysr6ANn2ZE0NBkxIrPnXDrWXWlpzt3Lhipsj_jIeq4XSK34kKJzbTZvg02g7K-jramQaHk6IBwL-Xij6wcKKYeqkyY9UAP396WdBO_AK4lhARUIOEJJY8xzAYgp8A9Eq4ADuPquHA9NiQkRoOLrRQdBe-nqzf_lode7bFctfG-vdtzDBl3dV0wj1A6ZY_542RRyQRtqVqjIeGNPl7SJD62Gy3cysi82ftFxy2-72F-igl_jgJ7CsvBx9CLq7csqCqE-ckT0vLxbKa2a360w27oGC7o0O_bdstgsL1n0QptQHXXDtO4-S3txkAwoVw7fas-wg7dZ8z3705-f2g1KlCNSMb889h_rLwI7biIqKnqTGlakKn-A90GfshnHHQmLq88jqyXvvuGdYq6pkRzpDsQPmf8bdsV0V17DKNRjIPiAmswqzkzqOVdfjnivEmZEL0iaE2eKDqCKYNBgS7Bg-ulqPEPWeoQMEWTuVaFgnHqj_u3OnYWMua4rAy_p5m50rwHdersgdE7q-mnOJQk4itoJlhxzxw3fJh_rmn40jq0mvj7R5GEo1VwpeGeFJUvRRtHt5-Q8or_5jslkNwn5Jn2aRDTIK0_T8A150BHqTS3in8_uC3ShviOEOUPaRbEr9mnb_z0UKXvjefN4zK7BBeIPaZlyg","scope":"https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly"}}',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json;charset=utf-8',
'User-Agent': 'axios/0.21.1',
'Content-Length': 1245,
host: 'moodle.tite.rdc.nie.edu.sg'
},
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus]
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype] {
socket: [Function (anonymous)],
abort: [Function (anonymous)],
aborted: [Function (anonymous)],
connect: [Function (anonymous)],
error: [Function (anonymous)],
timeout: [Function (anonymous)],
prefinish: [Function: requestOnPrefinish]
},
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 9,
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
parser: null,
_httpMessage: [Circular *1],
write: [Function: writeAfterFIN],
[Symbol(async_id_symbol)]: 2994,
[Symbol(kHandle)]: null,
[Symbol(kSetNoDelay)]: false,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 389,
[Symbol(kBytesWritten)]: 1505,
[Symbol(RequestTimeout)]: undefined
},
_header: 'POST https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Content-Type: application/json;charset=utf-8\r\n' +
'User-Agent: axios/0.21.1\r\n' +
'Content-Length: 1245\r\n' +
'host: moodle.tite.rdc.nie.edu.sg\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: noopPendingOutput],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 80,
protocol: 'http:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'fifo',
maxTotalSockets: Infinity,
totalSocketCount: 1,
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: 'https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php',
_ended: true,
res: IncomingMessage {
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
socket: [Socket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 400,
statusMessage: 'Bad Request',
client: [Socket],
_consuming: true,
_dumped: false,
req: [Circular *1],
responseUrl: 'http://10.55.99.61:3128/https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php',
redirects: [],
[Symbol(kCapture)]: false,
[Symbol(RequestTimeout)]: undefined
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: '10.55.99.61',
protocol: 'http:',
_redirectable: Writable {
_writableState: [WritableState],
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 1245,
_requestBodyBuffers: [],
_onNativeResponse: [Function (anonymous)],
_currentRequest: [Circular *1],
_currentUrl: 'http://10.55.99.61:3128/https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php',
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
'content-type': [Array],
'user-agent': [Array],
'content-length': [Array],
host: [Array]
}
},
response: {
status: 400,
statusText: 'Bad Request',
headers: {
server: 'nginx/1.16.1',
date: 'Thu, 10 Jun 2021 09:25:01 GMT',
'content-type': 'text/html; charset=utf-8',
'x-powered-by': 'PHP/7.3.28',
'strict-transport-security': 'max-age=16000000; includeSubDomains; preload;',
'x-cache': 'MISS from rchinfra01',
'x-cache-lookup': 'MISS from rchinfra01:3128',
via: '1.1 rchinfra01 (squid/3.5.20)',
connection: 'close'
},
config: {
url: 'https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php',
method: 'post',
data: '{"form":{"grant_type":"client_credentials","client_assertion_type":"urn:ietf:params:oauth:client-assertion-type:jwt-bearer","client_assertion":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImRhYjkyODBmNTllMDg0MWUyZWE0NjY1NjViZWFhYTBkIn0.eyJzdWIiOiJFVlhGQXlSb0FraE8yRG8iLCJpc3MiOiJFVlhGQXlSb0FraE8yRG8iLCJhdWQiOiJodHRwczovL21vb2RsZS50aXRlLnJkYy5uaWUuZWR1LnNnL21vZC9sdGkvdG9rZW4ucGhwIiwianRpIjoibGIxdWtlajd0c25qdncxZjc3eWphOHV0YyIsImlhdCI6MTYyMzMxNzEwMSwiZXhwIjoxNjIzMzE3MTYxfQ.wo2ZFzc9j_GZDiNysr6ANn2ZE0NBkxIrPnXDrWXWlpzt3Lhipsj_jIeq4XSK34kKJzbTZvg02g7K-jramQaHk6IBwL-Xij6wcKKYeqkyY9UAP396WdBO_AK4lhARUIOEJJY8xzAYgp8A9Eq4ADuPquHA9NiQkRoOLrRQdBe-nqzf_lode7bFctfG-vdtzDBl3dV0wj1A6ZY_542RRyQRtqVqjIeGNPl7SJD62Gy3cysi82ftFxy2-72F-igl_jgJ7CsvBx9CLq7csqCqE-ckT0vLxbKa2a360w27oGC7o0O_bdstgsL1n0QptQHXXDtO4-S3txkAwoVw7fas-wg7dZ8z3705-f2g1KlCNSMb889h_rLwI7biIqKnqTGlakKn-A90GfshnHHQmLq88jqyXvvuGdYq6pkRzpDsQPmf8bdsV0V17DKNRjIPiAmswqzkzqOVdfjnivEmZEL0iaE2eKDqCKYNBgS7Bg-ulqPEPWeoQMEWTuVaFgnHqj_u3OnYWMua4rAy_p5m50rwHdersgdE7q-mnOJQk4itoJlhxzxw3fJh_rmn40jq0mvj7R5GEo1VwpeGeFJUvRRtHt5-Q8or_5jslkNwn5Jn2aRDTIK0_T8A150BHqTS3in8_uC3ShviOEOUPaRbEr9mnb_z0UKXvjefN4zK7BBeIPaZlyg","scope":"https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly"}}',
headers: [Object],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus]
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Socket],
_header: 'POST https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Content-Type: application/json;charset=utf-8\r\n' +
'User-Agent: axios/0.21.1\r\n' +
'Content-Length: 1245\r\n' +
'host: moodle.tite.rdc.nie.edu.sg\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: 'https://moodle.tite.rdc.nie.edu.sg/mod/lti/token.php',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: '10.55.99.61',
protocol: 'http:',
_redirectable: [Writable],
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
data: { error: 'invalid_request' }
},
isAxiosError: true,
toJSON: [Function: toJSON]
}
Tried on my local and thought I'll just add the expected logs here (successful generation of access_token)
As always, thanks so much for the help!
Hi Carlos,
Could you help me with setting up ltijs for production?
I have an external tool web app with these ltijs configurations:
And in Moodle:
After getting dev for ltijs to work locally, I am now trying to get ltijs to work for production but it seems like there is an issue with my login. Here are the logs just before the error (gets stuck at Retrieving key from jwt_set before timing out):
I have tried deleting the platforms and also played around with the secure and samesite cookie settings for lti.setup but still faced the same issue.
As always, thanks so much for the help in advance :)
To add: i tried to the urls for keys and they seem to work: https://staging.tite.rdc.nie.edu.sg/keys https://moodle.tite.rdc.nie.edu.sg/mod/lti/certs.php