Coverage for gws-app/gws/plugin/auth_mfa/totp/__init__.py: 0%

21 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-05 13:35 +0200

1"""Multi-factor authentication with time-based one-time passwords. 

2 

3The adapter checks TOTP codes generated by authenticator apps. The secret is 

4taken from the ``mfaSecret`` attribute of the user; users without it cannot 

5start a transaction. The client sends the code as ``{"code": ...}``. 

6``key_uri`` creates a key URI for a secret, which can be shown as a QR code to 

7set up the app. 

8 

9Example:: 

10 

11 auth.mfa+ { 

12 type "totp" 

13 uid "AUTH_MFA_TOTP" 

14 } 

15""" 

16 

17import gws 

18import gws.base.auth 

19import gws.lib.net 

20import gws.lib.otp 

21 

22 

23@gws.ext.config.authMultiFactorAdapter('totp') 

24class Config(gws.base.auth.mfa.Config): 

25 """Multi-factor authentication with time-based one-time passwords.""" 

26 

27 pass 

28 

29 

30@gws.ext.object.authMultiFactorAdapter('totp') 

31class Object(gws.base.auth.mfa.Object): 

32 """TOTP multi-factor adapter.""" 

33 

34 def start(self, user): 

35 if not user.mfaSecret: 

36 gws.log.warning(f'totp: cannot start, {user.uid=}: no secret') 

37 return 

38 

39 mfa = super().start(user) 

40 mfa.secret = user.mfaSecret 

41 

42 return mfa 

43 

44 def verify(self, mfa, payload): 

45 ok = self.check_totp(mfa, payload.get('code')) 

46 return self.verify_attempt(mfa, ok) 

47 

48 def key_uri(self, secret, issuer_name, account_name): 

49 return gws.lib.otp.totp_key_uri(secret, issuer_name, account_name, self.otpOptions)