@@ -2445,9 +2445,9 @@ describe('OTP TOTP auth adatper', () => {
2445
2445
const response = user . get ( 'authDataResponse' ) ;
2446
2446
expect ( response . mfa ) . toBeDefined ( ) ;
2447
2447
expect ( response . mfa . recovery ) . toBeDefined ( ) ;
2448
- expect ( response . mfa . recovery . length ) . toEqual ( 2 ) ;
2448
+ expect ( response . mfa . recovery . split ( ',' ) . length ) . toEqual ( 2 ) ;
2449
2449
await user . fetch ( ) ;
2450
- expect ( user . get ( 'authData' ) . mfa ) . toEqual ( { enabled : true } ) ;
2450
+ expect ( user . get ( 'authData' ) . mfa ) . toEqual ( { status : 'enabled' } ) ;
2451
2451
} ) ;
2452
2452
2453
2453
it ( 'can login with valid token' , async ( ) => {
@@ -2473,13 +2473,15 @@ describe('OTP TOTP auth adatper', () => {
2473
2473
username : 'username' ,
2474
2474
password : 'password' ,
2475
2475
authData : {
2476
- mfa : totp . generate ( ) ,
2476
+ mfa : {
2477
+ token : totp . generate ( ) ,
2478
+ } ,
2477
2479
} ,
2478
2480
} ) ,
2479
2481
} ) . then ( res => res . data ) ;
2480
2482
expect ( response . objectId ) . toEqual ( user . id ) ;
2481
2483
expect ( response . sessionToken ) . toBeDefined ( ) ;
2482
- expect ( response . authData ) . toEqual ( { mfa : { enabled : true } } ) ;
2484
+ expect ( response . authData ) . toEqual ( { mfa : { status : 'enabled' } } ) ;
2483
2485
expect ( Object . keys ( response ) . sort ( ) ) . toEqual (
2484
2486
[
2485
2487
'objectId' ,
@@ -2528,6 +2530,42 @@ describe('OTP TOTP auth adatper', () => {
2528
2530
expect ( user . get ( 'authData' ) . mfa . secret ) . toEqual ( new_secret . base32 ) ;
2529
2531
} ) ;
2530
2532
2533
+ it ( 'cannot change OTP with invalid token' , async ( ) => {
2534
+ const user = await Parse . User . signUp ( 'username' , 'password' ) ;
2535
+ const OTPAuth = require ( 'otpauth' ) ;
2536
+ const secret = new OTPAuth . Secret ( ) ;
2537
+ const totp = new OTPAuth . TOTP ( {
2538
+ algorithm : 'SHA1' ,
2539
+ digits : 6 ,
2540
+ period : 30 ,
2541
+ secret,
2542
+ } ) ;
2543
+ const token = totp . generate ( ) ;
2544
+ await user . save (
2545
+ { authData : { mfa : { secret : secret . base32 , token } } } ,
2546
+ { sessionToken : user . getSessionToken ( ) }
2547
+ ) ;
2548
+
2549
+ const new_secret = new OTPAuth . Secret ( ) ;
2550
+ const new_totp = new OTPAuth . TOTP ( {
2551
+ algorithm : 'SHA1' ,
2552
+ digits : 6 ,
2553
+ period : 30 ,
2554
+ secret : new_secret ,
2555
+ } ) ;
2556
+ const new_token = new_totp . generate ( ) ;
2557
+ await expectAsync (
2558
+ user . save (
2559
+ {
2560
+ authData : { mfa : { secret : new_secret . base32 , token : new_token , old : '123' } } ,
2561
+ } ,
2562
+ { sessionToken : user . getSessionToken ( ) }
2563
+ )
2564
+ ) . toBeRejectedWith ( new Parse . Error ( Parse . Error . OTHER_CAUSE , 'Invalid MFA token' ) ) ;
2565
+ await user . fetch ( { useMasterKey : true } ) ;
2566
+ expect ( user . get ( 'authData' ) . mfa . secret ) . toEqual ( secret . base32 ) ;
2567
+ } ) ;
2568
+
2531
2569
it ( 'future logins require TOTP token' , async ( ) => {
2532
2570
const user = await Parse . User . signUp ( 'username' , 'password' ) ;
2533
2571
const OTPAuth = require ( 'otpauth' ) ;
@@ -2572,7 +2610,9 @@ describe('OTP TOTP auth adatper', () => {
2572
2610
username : 'username' ,
2573
2611
password : 'password' ,
2574
2612
authData : {
2575
- mfa : 'abcd' ,
2613
+ mfa : {
2614
+ token : 'abcd' ,
2615
+ } ,
2576
2616
} ,
2577
2617
} ) ,
2578
2618
} ) . catch ( e => {
@@ -2619,7 +2659,7 @@ describe('OTP SMS auth adatper', () => {
2619
2659
const spy = spyOn ( mfa , 'sendSMS' ) . and . callThrough ( ) ;
2620
2660
await user . save ( { authData : { mfa : { mobile : '+11111111111' } } } , { sessionToken } ) ;
2621
2661
await user . fetch ( { sessionToken } ) ;
2622
- expect ( user . get ( 'authData' ) ) . toEqual ( { mfa : { enabled : false } } ) ;
2662
+ expect ( user . get ( 'authData' ) ) . toEqual ( { mfa : { status : 'disabled' } } ) ;
2623
2663
expect ( spy ) . toHaveBeenCalledWith ( code , '+11111111111' ) ;
2624
2664
await user . fetch ( { useMasterKey : true } ) ;
2625
2665
const authData = user . get ( 'authData' ) . mfa ?. pending ;
@@ -2629,7 +2669,7 @@ describe('OTP SMS auth adatper', () => {
2629
2669
2630
2670
await user . save ( { authData : { mfa : { mobile, token : code } } } , { sessionToken } ) ;
2631
2671
await user . fetch ( { sessionToken } ) ;
2632
- expect ( user . get ( 'authData' ) ) . toEqual ( { mfa : { enabled : true } } ) ;
2672
+ expect ( user . get ( 'authData' ) ) . toEqual ( { mfa : { status : 'enabled' } } ) ;
2633
2673
} ) ;
2634
2674
2635
2675
it ( 'future logins require SMS code' , async ( ) => {
@@ -2658,7 +2698,9 @@ describe('OTP SMS auth adatper', () => {
2658
2698
username : 'username' ,
2659
2699
password : 'password' ,
2660
2700
authData : {
2661
- mfa : true ,
2701
+ mfa : {
2702
+ token : 'request' ,
2703
+ } ,
2662
2704
} ,
2663
2705
} ) ,
2664
2706
} ) . catch ( e => e . data ) ;
@@ -2672,13 +2714,15 @@ describe('OTP SMS auth adatper', () => {
2672
2714
username : 'username' ,
2673
2715
password : 'password' ,
2674
2716
authData : {
2675
- mfa : code ,
2717
+ mfa : {
2718
+ token : code ,
2719
+ } ,
2676
2720
} ,
2677
2721
} ) ,
2678
2722
} ) . then ( res => res . data ) ;
2679
2723
expect ( response . objectId ) . toEqual ( user . id ) ;
2680
2724
expect ( response . sessionToken ) . toBeDefined ( ) ;
2681
- expect ( response . authData ) . toEqual ( { mfa : { enabled : true } } ) ;
2725
+ expect ( response . authData ) . toEqual ( { mfa : { status : 'enabled' } } ) ;
2682
2726
expect ( Object . keys ( response ) . sort ( ) ) . toEqual (
2683
2727
[
2684
2728
'objectId' ,
0 commit comments