|
4 | 4 |
|
5 | 5 | const supertest = require('supertest'); |
6 | 6 | const chai = require('chai'); |
| 7 | +const speakeasy = require('speakeasy'); |
7 | 8 |
|
8 | 9 | const expect = chai.expect; |
9 | 10 | chai.config.includeStack = true; |
@@ -301,6 +302,88 @@ describe('API Users', function () { |
301 | 302 | await server.get(`/users/me?accessToken=${token2}`).expect(403); |
302 | 303 | }); |
303 | 304 |
|
| 305 | + it('should POST /users/{user}/2fa/totp/check expect failure without a matching session', async () => { |
| 306 | + const setupResponse = await server |
| 307 | + .post(`/users/${user2}/2fa/totp/setup`) |
| 308 | + .send({ |
| 309 | + issuer: 'WildDuck' |
| 310 | + }) |
| 311 | + .expect(200); |
| 312 | + |
| 313 | + expect(setupResponse.body.success).to.be.true; |
| 314 | + expect(setupResponse.body.seed).to.exist; |
| 315 | + |
| 316 | + const enableToken = speakeasy.totp({ |
| 317 | + secret: setupResponse.body.seed, |
| 318 | + encoding: 'base32' |
| 319 | + }); |
| 320 | + |
| 321 | + const enableResponse = await server |
| 322 | + .post(`/users/${user2}/2fa/totp/enable`) |
| 323 | + .send({ |
| 324 | + token: enableToken |
| 325 | + }) |
| 326 | + .expect(200); |
| 327 | + |
| 328 | + expect(enableResponse.body.success).to.be.true; |
| 329 | + |
| 330 | + const userTokenResponse = await server |
| 331 | + .post('/authenticate') |
| 332 | + .send({ |
| 333 | + username: 'myuser2', |
| 334 | + password: 'secretvalue', |
| 335 | + token: true |
| 336 | + }) |
| 337 | + .expect(200); |
| 338 | + |
| 339 | + expect(userTokenResponse.body.success).to.be.true; |
| 340 | + expect(userTokenResponse.body.token).to.exist; |
| 341 | + |
| 342 | + const user2TokenResponse = await server |
| 343 | + .post('/authenticate') |
| 344 | + .send({ |
| 345 | + username: 'myuser2hash', |
| 346 | + password: 'test', |
| 347 | + token: true |
| 348 | + }) |
| 349 | + .expect(200); |
| 350 | + |
| 351 | + expect(user2TokenResponse.body.success).to.be.true; |
| 352 | + expect(user2TokenResponse.body.token).to.exist; |
| 353 | + |
| 354 | + const totpToken = speakeasy.totp({ |
| 355 | + secret: setupResponse.body.seed, |
| 356 | + encoding: 'base32' |
| 357 | + }); |
| 358 | + |
| 359 | + const noSessionResponse = await server |
| 360 | + .post(`/users/${user2}/2fa/totp/check`) |
| 361 | + .send({ |
| 362 | + token: totpToken |
| 363 | + }) |
| 364 | + .expect(403); |
| 365 | + |
| 366 | + expect(noSessionResponse.body.code).to.equal('InvalidToken'); |
| 367 | + |
| 368 | + const wrongSessionResponse = await server |
| 369 | + .post(`/users/${user2}/2fa/totp/check?accessToken=${userTokenResponse.body.token}`) |
| 370 | + .send({ |
| 371 | + token: totpToken |
| 372 | + }) |
| 373 | + .expect(403); |
| 374 | + |
| 375 | + expect(wrongSessionResponse.body.code).to.equal('InvalidToken'); |
| 376 | + |
| 377 | + const successResponse = await server |
| 378 | + .post(`/users/${user2}/2fa/totp/check?accessToken=${user2TokenResponse.body.token}`) |
| 379 | + .send({ |
| 380 | + token: totpToken |
| 381 | + }) |
| 382 | + .expect(200); |
| 383 | + |
| 384 | + expect(successResponse.body.success).to.be.true; |
| 385 | + }); |
| 386 | + |
304 | 387 | it('should PUT /users/{user}/logout expect success', async () => { |
305 | 388 | // request logout |
306 | 389 | const response = await server.put(`/users/${user}/logout`).send({ reason: 'Just because' }).expect(200); |
|
0 commit comments