Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion dist/Provider/Provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -639,8 +639,19 @@ class Provider {
cookieOptions.maxAge = 60 * 1000; // Adding max age to state cookie = 1min
res.cookie('state' + state, iss, cookieOptions);

// Create nonce parameter used to prevent replay attack
const nonce = encodeURIComponent([...Array(25)].map(_ => (Math.random() * 36 | 0).toString(36)).join``);
// Check if nonce is unique
while (await this.Database.Get(false, 'nonce', {
nonce: nonce
})) nonce = encodeURIComponent([...Array(25)].map(_ => (Math.random() * 36 | 0).toString(36)).join``);
//Store nonce
await this.Database.Insert(false, 'nonce', {
nonce
});

// Redirect to authentication endpoint
const query = await Request.ltiAdvantageLogin(params, platform, state);
const query = await Request.ltiAdvantageLogin(params, platform, state, nonce);
provMainDebug('Login request: ');
provMainDebug(query);
res.redirect(url.format({
Expand Down
12 changes: 8 additions & 4 deletions dist/Utils/Auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,15 @@ class Auth {
static async validateNonce(token, Database) {
provAuthDebug('Validating nonce');
provAuthDebug('Nonce: ' + token.nonce);
if (await Database.Get(false, 'nonce', {
const savedNonce = await Database.Get(false, 'nonce', {
nonce: token.nonce
})) throw new Error('NONCE_ALREADY_RECEIVED');
provAuthDebug('Storing nonce');
await Database.Insert(false, 'nonce', {
});
if (!savedNonce) {
provAuthDebug('Nonce have been Deleted Before, nonce not found in Database');
throw new Error('NONCE_ALREADY_RECEIVED');
}
provAuthDebug('Deleting validated nonce');
Database.Delete('nonce', {
nonce: token.nonce
});
return true;
Expand Down
2 changes: 1 addition & 1 deletion dist/Utils/Database.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class Database {
nonce: String,
createdAt: {
type: Date,
expires: 10,
expires: 3600,
default: Date.now
}
});
Expand Down
4 changes: 2 additions & 2 deletions dist/Utils/Request.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Request {
* @param {object} platform - Platform Object.
* @param {String} state - State parameter, used to validate the response.
*/
static async ltiAdvantageLogin(request, platform, state) {
static async ltiAdvantageLogin(request, platform, state, nonce) {
const query = {
response_type: 'id_token',
response_mode: 'form_post',
Expand All @@ -17,7 +17,7 @@ class Request {
client_id: request.client_id || (await platform.platformClientId()),
redirect_uri: request.target_link_uri,
login_hint: request.login_hint,
nonce: encodeURIComponent([...Array(25)].map(_ => (Math.random() * 36 | 0).toString(36)).join``),
nonce: nonce,
prompt: 'none',
state
};
Expand Down
9 changes: 8 additions & 1 deletion src/Provider/Provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,15 @@ class Provider {
cookieOptions.maxAge = 60 * 1000 // Adding max age to state cookie = 1min
res.cookie('state' + state, iss, cookieOptions)

// Create nonce parameter used to prevent replay attack
const nonce = encodeURIComponent([...Array(25)].map(_ => (Math.random() * 36 | 0).toString(36)).join``)
// Check if nonce is unique
while (await this.Database.Get(false, 'nonce', { nonce: nonce })) nonce = encodeURIComponent([...Array(25)].map(_ => (Math.random() * 36 | 0).toString(36)).join``)
//Store nonce
await this.Database.Insert(false, 'nonce', { nonce })

// Redirect to authentication endpoint
const query = await Request.ltiAdvantageLogin(params, platform, state)
const query = await Request.ltiAdvantageLogin(params, platform, state, nonce)
provMainDebug('Login request: ')
provMainDebug(query)
res.redirect(url.format({
Expand Down
14 changes: 9 additions & 5 deletions src/Utils/Auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,16 @@ class Auth {
* @param {Object} token - Id token you wish to validate.
*/
static async validateNonce (token, Database) {
provAuthDebug('Validating nonce')
provAuthDebug('Nonce: ' + token.nonce)
provAuthDebug('Validating nonce');
provAuthDebug('Nonce: ' + token.nonce);
const savedNonce = await Database.Get(false, 'nonce', { nonce: token.nonce })
if (!savedNonce) {
provAuthDebug('Nonce have been Deleted Before, nonce not found in Database')
throw new Error('NONCE_ALREADY_RECEIVED')
}

if (await Database.Get(false, 'nonce', { nonce: token.nonce })) throw new Error('NONCE_ALREADY_RECEIVED')
provAuthDebug('Storing nonce')
await Database.Insert(false, 'nonce', { nonce: token.nonce })
provAuthDebug('Deleting validated nonce')
Database.Delete('nonce', { nonce: token.nonce })

return true
}
Expand Down
2 changes: 1 addition & 1 deletion src/Utils/Database.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class Database {

const nonceSchema = new Schema({
nonce: String,
createdAt: { type: Date, expires: 10, default: Date.now }
createdAt: { type: Date, expires: 3600, default: Date.now }
})
nonceSchema.index({ nonce: 1 })

Expand Down
4 changes: 2 additions & 2 deletions src/Utils/Request.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Request {
* @param {object} platform - Platform Object.
* @param {String} state - State parameter, used to validate the response.
*/
static async ltiAdvantageLogin (request, platform, state) {
static async ltiAdvantageLogin (request, platform, state, nonce) {
const query = {
response_type: 'id_token',
response_mode: 'form_post',
Expand All @@ -15,7 +15,7 @@ class Request {
client_id: request.client_id || await platform.platformClientId(),
redirect_uri: request.target_link_uri,
login_hint: request.login_hint,
nonce: encodeURIComponent([...Array(25)].map(_ => (Math.random() * 36 | 0).toString(36)).join``),
nonce: nonce,
prompt: 'none',
state
}
Expand Down