···7979 ; pending_2fa_token= None
8080 ; two_fa_methods= None }
8181 | Some pending -> (
8282- (* try TOTP, then backup code, then email *)
8382 let%lwt result =
8484- let%lwt totp_result =
8585- Two_factor.verify_totp_code ~session_token:token ~code
8686- ctx.db
8787- in
8888- match totp_result with
8989- | Ok did ->
9090- Lwt.return_ok did
9191- | Error _ -> (
9292- let%lwt backup_result =
9393- Two_factor.verify_backup_code ~session_token:token ~code
9494- ctx.db
9595- in
9696- match backup_result with
9797- | Ok did ->
9898- Lwt.return_ok did
9999- | Error _ ->
100100- Two_factor.verify_email_code_by_token
101101- ~session_token:token ~code ctx.db )
8383+ Two_factor.verify_code_with_pending_session ~pending ~code
8484+ ctx.db
10285 in
10386 match result with
10487 | Ok did ->
+1-20
pegasus/lib/api/server/createSession.ml
···2525 ; status
2626 ; did_doc= None }
27272828-let verify_2fa_code ~(actor : Data_store.Types.actor) ~code db =
2929- let did = actor.did in
3030- let%lwt sk_valid = Security_key.verify_login ~did ~code db in
3131- if sk_valid then Lwt.return_ok ()
3232- else
3333- let%lwt totp_valid = Totp.verify_login_code ~did ~code db in
3434- if totp_valid then Lwt.return_ok ()
3535- else
3636- let%lwt backup_valid =
3737- Totp.Backup_codes.verify_and_consume ~did ~code db
3838- in
3939- if backup_valid then Lwt.return_ok ()
4040- else
4141- match%lwt Two_factor.verify_email_code_by_did ~did ~code db with
4242- | Ok _ ->
4343- Lwt.return_ok ()
4444- | Error e ->
4545- Lwt.return_error e
4646-4728let handler =
4829 Xrpc.handler (fun {req; db; _} ->
4930 let%lwt {identifier; password; auth_factor_token; _} =
···7152 else
7253 match auth_factor_token with
7354 | Some token when token <> "" -> (
7474- match%lwt verify_2fa_code ~actor ~code:token db with
5555+ match%lwt Two_factor.verify_code ~did:actor.did ~code:token db with
7556 | Ok () ->
7657 complete_login actor
7758 | Error msg ->
+44
pegasus/lib/two_factor.ml
···242242 Lwt.return_true
243243 | _ ->
244244 Lwt.return_false
245245+246246+let verify_code ~did ~code db =
247247+ let%lwt sk_valid = Security_key.verify_login ~did ~code db in
248248+ if sk_valid then Lwt.return_ok ()
249249+ else
250250+ let%lwt totp_valid = Totp.verify_login_code ~did ~code db in
251251+ if totp_valid then Lwt.return_ok ()
252252+ else
253253+ let%lwt backup_valid =
254254+ Totp.Backup_codes.verify_and_consume ~did ~code db
255255+ in
256256+ if backup_valid then Lwt.return_ok ()
257257+ else
258258+ match%lwt verify_email_code_by_did ~did ~code db with
259259+ | Ok _ ->
260260+ Lwt.return_ok ()
261261+ | Error e ->
262262+ Lwt.return_error e
263263+264264+let verify_code_with_pending_session ~(pending : Types.pending_2fa) ~code db =
265265+ let did = pending.did in
266266+ let%lwt sk_valid = Security_key.verify_login ~did ~code db in
267267+ if sk_valid then Lwt.return_ok did
268268+ else
269269+ let%lwt totp_valid = Totp.verify_login_code ~did ~code db in
270270+ if totp_valid then Lwt.return_ok did
271271+ else
272272+ let%lwt backup_valid =
273273+ Totp.Backup_codes.verify_and_consume ~did ~code db
274274+ in
275275+ if backup_valid then Lwt.return_ok did
276276+ else
277277+ match%lwt _verify_email_code ~code ~session:pending with
278278+ | Ok did ->
279279+ Lwt.return_ok did
280280+ | Error e ->
281281+ Lwt.return_error e
282282+283283+let verify_code_by_session_token ~session_token ~code db =
284284+ match%lwt get_pending_session ~session_token db with
285285+ | None ->
286286+ Lwt.return_error "Invalid or expired session"
287287+ | Some pending ->
288288+ verify_code_with_pending_session ~pending ~code db