1
+ /**
2
+ * @license
3
+ * Copyright 2020 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ import { expect , use } from 'chai' ;
19
+ import chaiAsPromised from 'chai-as-promised' ;
20
+ import * as sinon from 'sinon' ;
21
+ import sinonChai from 'sinon-chai' ;
22
+
23
+ //import { mockTotp } from '../../helpers/integration/helpers';
24
+ import { Auth , createUserWithEmailAndPassword , multiFactor , signInAnonymously , signInWithEmailAndPassword , UserCredential } from '@firebase/auth' ;
25
+
26
+ import {
27
+ cleanUpTestInstance ,
28
+ getTestInstance ,
29
+ mockTotp ,
30
+ randomEmail
31
+ } from '../../helpers/integration/helpers' ;
32
+ import { MultiFactorAssertionImpl } from '../../../src/mfa/mfa_assertion' ;
33
+
34
+ import { MultiFactorSessionImpl } from '../../../src/mfa/mfa_session' ;
35
+ import { TotpMultiFactorAssertionImpl , TotpMultiFactorGenerator , TotpSecret } from '../../../src/mfa/assertions/totp' ;
36
+ import * as MFA from '../../../src/api/account_management/mfa' ;
37
+ import { FirebaseError } from '@firebase/util' ;
38
+
39
+
40
+
41
+ use ( chaiAsPromised ) ;
42
+ use ( sinonChai ) ;
43
+
44
+ const TOTP_COMB_A = {
45
+
46
+ response : { sharedSecretKey : 'secretKey3' ,
47
+ verificationCodeLength : 30 ,
48
+ hashingAlgorithm : 'sha1' ,
49
+ periodSec :30 ,
50
+ sessionInfo : 'testsSessionInfo' ,
51
+ finalizeEnrollmentTime : Date . now ( )
52
+ } ,
53
+ code : '...'
54
+ } ;
55
+
56
+ const TOTP_COMB_B = {
57
+
58
+ response : { sharedSecretKey : 'secretKey2' ,
59
+ verificationCodeLength : 30 ,
60
+ hashingAlgorithm : 'sha1' ,
61
+ periodSec : 30 ,
62
+ sessionInfo : 'testsSessionInfo' ,
63
+ finalizeEnrollmentTime : Date . now ( )
64
+ } ,
65
+ code : '...'
66
+ } ;
67
+
68
+ describe ( ' Integration tests: Mfa TOTP' , ( ) => {
69
+ let auth : Auth ;
70
+ let idToken : string ;
71
+ let signUpCred : UserCredential ;
72
+ let email : string ;
73
+ let assertion : MultiFactorAssertionImpl ;
74
+ let _request : MFA . StartTotpMfaEnrollmentRequest ;
75
+ let startMfaResponse : MFA . StartTotpMfaEnrollmentResponse ;
76
+ let displayName : string ;
77
+ beforeEach ( async ( ) => {
78
+ auth = getTestInstance ( ) ;
79
+ email = randomEmail ( ) ;
80
+ idToken = 'testIdToken' ;
81
+ signUpCred = await createUserWithEmailAndPassword (
82
+ auth ,
83
+ email ,
84
+ 'password'
85
+ ) ;
86
+ await auth . signOut ( ) ;
87
+ } ) ;
88
+
89
+ afterEach ( async ( ) => {
90
+ await cleanUpTestInstance ( auth ) ;
91
+
92
+ } ) ;
93
+ it ( 'should verify using otp' , async ( ) => {
94
+
95
+ console . log ( email ) ;
96
+ const cr = await signInWithEmailAndPassword ( auth , email , 'password' ) ;
97
+
98
+ startMfaResponse = { totpSessionInfo : TOTP_COMB_A . response }
99
+
100
+
101
+
102
+ const mfaUser = multiFactor ( cr . user ) ;
103
+ sinon . spy ( MultiFactorSessionImpl , '_fromIdtoken' ) ;
104
+
105
+ sinon . stub ( mfaUser , 'getSession' ) . returns (
106
+ Promise . resolve ( MultiFactorSessionImpl . _fromIdtoken ( idToken , auth as any ) ) ) ;
107
+
108
+ sinon . stub ( MFA , 'startEnrollTotpMfa' ) . callsFake ( ( _auth , _request ) => {
109
+
110
+ return Promise . resolve ( startMfaResponse )
111
+ } )
112
+
113
+
114
+
115
+ const session = await mfaUser . getSession ( ) ;
116
+
117
+ console . log ( session ) ;
118
+
119
+ const totpSecret = await TotpMultiFactorGenerator . generateSecret (
120
+ session
121
+ ) ;
122
+
123
+ console . log ( "**** totpSecret" + totpSecret ) ;
124
+ // https://stackoverflow.com/questions/48931815/sinon-stub-not-replacing-function
125
+ // https://stackoverflow.com/questions/61051247/chai-spies-expect-to-have-been-called-is-failing-on-local-methods
126
+ expect ( MultiFactorSessionImpl . _fromIdtoken ) . to . have . been . calledOnce ;
127
+ //expect(TotpSecret._fromStartTotpMfaEnrollmentResponse).to.have.been.calledOnce;
128
+ expect ( MFA . startEnrollTotpMfa ) . to . have . been . calledOnce ;
129
+
130
+ expect ( await MFA . startEnrollTotpMfa ( auth as any , _request ) ) . to . eql ( startMfaResponse )
131
+
132
+ expect ( totpSecret . secretKey ) . to . eql ( startMfaResponse . totpSessionInfo . sharedSecretKey )
133
+ expect ( totpSecret . codeLength ) . to . eql ( startMfaResponse . totpSessionInfo . verificationCodeLength )
134
+
135
+ const totpVerificationCode = await mockTotp ( totpSecret . secretKey , totpSecret . codeLength , totpSecret . codeIntervalSeconds ) ;
136
+
137
+ const multiFactorAssertion = TotpMultiFactorGenerator . assertionForEnrollment (
138
+ totpSecret ,
139
+ totpVerificationCode
140
+ ) ;
141
+ console . log ( totpVerificationCode ) ;
142
+ // auth/invalid-idToken
143
+ await expect ( mfaUser . enroll ( multiFactorAssertion , displayName ) ) . to . be . rejectedWith ( FirebaseError , 'auth/invalid-id-token' )
144
+
145
+
146
+ } )
147
+ } )
0 commit comments