@@ -19,15 +19,24 @@ import { expect, use } from 'chai';
19
19
import chaiAsPromised from 'chai-as-promised' ;
20
20
21
21
import { mockEndpoint } from '../../../test/helpers/api/helper' ;
22
- import { testAuth , TestAuth } from '../../../test/helpers/mock_auth' ;
22
+ import { testAuth , TestAuth , testUser } from '../../../test/helpers/mock_auth' ;
23
23
import * as mockFetch from '../../../test/helpers/mock_fetch' ;
24
24
import { Endpoint } from '../../api' ;
25
25
import { MultiFactorSessionImpl } from '../../mfa/mfa_session' ;
26
26
import { StartTotpMfaEnrollmentResponse } from '../../api/account_management/mfa' ;
27
- import { TotpSecret } from '../../platform_browser/mfa/assertions/totp' ;
28
- import { TotpMultiFactorGenerator } from './totp' ;
29
- import { FactorId } from '../../model/public_types' ;
27
+ import { FinalizeMfaResponse } from '../../api/authentication/mfa' ;
28
+ import {
29
+ TotpMultiFactorAssertionImpl ,
30
+ TotpMultiFactorGenerator ,
31
+ TotpSecret
32
+ } from './totp' ;
33
+ import { Auth , FactorId } from '../../model/public_types' ;
30
34
import { AuthErrorCode } from '../../core/errors' ;
35
+ import { FirebaseApp , initializeApp } from '@firebase/app' ;
36
+ import { AppName } from '../../model/auth' ;
37
+ import { getAuth } from '../../platform_browser' ;
38
+ import { initializeAuth } from '../../core' ;
39
+ import { _castAuth } from '../../core/auth/auth_impl' ;
31
40
32
41
use ( chaiAsPromised ) ;
33
42
@@ -119,3 +128,168 @@ describe('core/mfa/assertions/totp/TotpMultiFactorGenerator', () => {
119
128
} ) ;
120
129
} ) ;
121
130
} ) ;
131
+
132
+ describe ( 'core/mfa/totp/assertions/TotpMultiFactorAssertionImpl' , ( ) => {
133
+ let auth : TestAuth ;
134
+ let assertion : TotpMultiFactorAssertionImpl ;
135
+ let session : MultiFactorSessionImpl ;
136
+ let secret : TotpSecret ;
137
+
138
+ const serverResponse : FinalizeMfaResponse = {
139
+ idToken : 'final-id-token' ,
140
+ refreshToken : 'refresh-token'
141
+ } ;
142
+
143
+ const startEnrollmentResponse : StartTotpMfaEnrollmentResponse = {
144
+ totpSessionInfo : {
145
+ sharedSecretKey : 'key123' ,
146
+ verificationCodeLength : 6 ,
147
+ hashingAlgorithm : 'SHA1' ,
148
+ periodSec : 30 ,
149
+ sessionInfo : 'verification-id' ,
150
+ finalizeEnrollmentTime : 1662586196
151
+ }
152
+ } ;
153
+
154
+ beforeEach ( async ( ) => {
155
+ mockFetch . setUp ( ) ;
156
+ auth = await testAuth ( ) ;
157
+ secret = TotpSecret . fromStartTotpMfaEnrollmentResponse (
158
+ startEnrollmentResponse ,
159
+ auth . name
160
+ ) ;
161
+ assertion = TotpMultiFactorAssertionImpl . _fromSecret ( secret , '123456' ) ;
162
+ } ) ;
163
+ afterEach ( mockFetch . tearDown ) ;
164
+
165
+ describe ( 'enroll' , ( ) => {
166
+ beforeEach ( ( ) => {
167
+ session = MultiFactorSessionImpl . _fromIdtoken (
168
+ 'enrollment-id-token' ,
169
+ auth
170
+ ) ;
171
+ } ) ;
172
+
173
+ it ( 'should finalize the MFA enrollment' , async ( ) => {
174
+ const mock = mockEndpoint (
175
+ Endpoint . FINALIZE_MFA_ENROLLMENT ,
176
+ serverResponse
177
+ ) ;
178
+ const response = await assertion . _process ( auth , session ) ;
179
+ expect ( response ) . to . eql ( serverResponse ) ;
180
+ expect ( mock . calls [ 0 ] . request ) . to . eql ( {
181
+ idToken : 'enrollment-id-token' ,
182
+ totpVerificationInfo : {
183
+ verificationCode : '123456' ,
184
+ sessionInfo : 'verification-id'
185
+ }
186
+ } ) ;
187
+ expect ( session . auth ) . to . eql ( auth ) ;
188
+ } ) ;
189
+
190
+ context ( 'with display name' , ( ) => {
191
+ it ( 'should set the display name' , async ( ) => {
192
+ const mock = mockEndpoint (
193
+ Endpoint . FINALIZE_MFA_ENROLLMENT ,
194
+ serverResponse
195
+ ) ;
196
+ const response = await assertion . _process (
197
+ auth ,
198
+ session ,
199
+ 'display-name'
200
+ ) ;
201
+ expect ( response ) . to . eql ( serverResponse ) ;
202
+ expect ( mock . calls [ 0 ] . request ) . to . eql ( {
203
+ idToken : 'enrollment-id-token' ,
204
+ displayName : 'display-name' ,
205
+ totpVerificationInfo : {
206
+ verificationCode : '123456' ,
207
+ sessionInfo : 'verification-id'
208
+ }
209
+ } ) ;
210
+ expect ( session . auth ) . to . eql ( auth ) ;
211
+ } ) ;
212
+ } ) ;
213
+ } ) ;
214
+ } ) ;
215
+
216
+ describe ( 'core/mfa/assertions/totp/TotpSecret' , ( ) => {
217
+ const serverResponse : StartTotpMfaEnrollmentResponse = {
218
+ totpSessionInfo : {
219
+ sharedSecretKey : 'key123' ,
220
+ verificationCodeLength : 6 ,
221
+ hashingAlgorithm : 'SHA1' ,
222
+ periodSec : 30 ,
223
+ sessionInfo : 'verification-id' ,
224
+ finalizeEnrollmentTime : 1662586196
225
+ }
226
+ } ;
227
+ const fakeAppName : AppName = 'test-app' ;
228
+ const fakeEmail : string = 'user@email' ;
229
+ const secret = TotpSecret . fromStartTotpMfaEnrollmentResponse (
230
+ serverResponse ,
231
+ fakeAppName
232
+ ) ;
233
+
234
+ describe ( 'fromStartTotpMfaEnrollmentResponse' , ( ) => {
235
+ it ( 'fields from the response are parsed correctly' , ( ) => {
236
+ expect ( secret . secretKey ) . to . eq ( 'key123' ) ;
237
+ expect ( secret . codeIntervalSeconds ) . to . eq ( 30 ) ;
238
+ expect ( secret . codeLength ) . to . eq ( 6 ) ;
239
+ expect ( secret . hashingAlgorithm ) . to . eq ( 'SHA1' ) ;
240
+ } ) ;
241
+ } ) ;
242
+ describe ( 'generateQrCodeUrl' , ( ) => {
243
+ let app : FirebaseApp ;
244
+ let auth : Auth ;
245
+
246
+ beforeEach ( async ( ) => {
247
+ app = initializeApp (
248
+ {
249
+ apiKey : 'fake-key' ,
250
+ appId : 'fake-app-id' ,
251
+ authDomain : 'fake-auth-domain'
252
+ } ,
253
+ fakeAppName
254
+ ) ;
255
+ auth = initializeAuth ( app ) ;
256
+ await auth . updateCurrentUser (
257
+ testUser ( _castAuth ( auth ) , 'uid' , fakeEmail , true )
258
+ ) ;
259
+ } ) ;
260
+
261
+ it ( 'with account name and issuer provided' , ( ) => {
262
+ const url = secret . generateQrCodeUrl ( 'user@myawesomeapp' , 'myawesomeapp' ) ;
263
+ expect ( url ) . to . eq (
264
+ 'otpauth://totp/myawesomeapp:user@myawesomeapp?secret=key123&issuer=myawesomeapp&algorithm=SHA1&digits=6'
265
+ ) ;
266
+ } ) ;
267
+ it ( 'only accountName provided' , ( ) => {
268
+ const url = secret . generateQrCodeUrl ( 'user@myawesomeapp' , '' ) ;
269
+ const auth2 = getAuth ( app ) ;
270
+ console . log ( 'Current user is ' + auth2 ) ;
271
+ expect ( url ) . to . eq (
272
+ `otpauth://totp/${ fakeAppName } :user@myawesomeapp?secret=key123&issuer=${ fakeAppName } &algorithm=SHA1&digits=6`
273
+ ) ;
274
+ } ) ;
275
+ it ( 'only issuer provided' , ( ) => {
276
+ const url = secret . generateQrCodeUrl ( '' , 'myawesomeapp' ) ;
277
+ expect ( url ) . to . eq (
278
+ `otpauth://totp/myawesomeapp:${ fakeEmail } ?secret=key123&issuer=myawesomeapp&algorithm=SHA1&digits=6`
279
+ ) ;
280
+ } ) ;
281
+ it ( 'with defaults' , ( ) => {
282
+ const url = secret . generateQrCodeUrl ( ) ;
283
+ expect ( url ) . to . eq (
284
+ `otpauth://totp/${ fakeAppName } :${ fakeEmail } ?secret=key123&issuer=${ fakeAppName } &algorithm=SHA1&digits=6`
285
+ ) ;
286
+ } ) ;
287
+ it ( 'with defaults, without currentUser' , async ( ) => {
288
+ await auth . updateCurrentUser ( null ) ;
289
+ const url = secret . generateQrCodeUrl ( ) ;
290
+ expect ( url ) . to . eq (
291
+ `otpauth://totp/${ fakeAppName } :unknownuser?secret=key123&issuer=${ fakeAppName } &algorithm=SHA1&digits=6`
292
+ ) ;
293
+ } ) ;
294
+ } ) ;
295
+ } ) ;
0 commit comments