pyauthenticator 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyauthenticator-0.3.0/.gitignore +13 -0
- {pyauthenticator-0.2.0/pyauthenticator.egg-info → pyauthenticator-0.3.0}/PKG-INFO +32 -10
- {pyauthenticator-0.2.0 → pyauthenticator-0.3.0}/README.md +4 -4
- pyauthenticator-0.3.0/pyproject.toml +79 -0
- pyauthenticator-0.3.0/src/pyauthenticator/__init__.py +19 -0
- pyauthenticator-0.3.0/src/pyauthenticator/__main__.py +9 -0
- pyauthenticator-0.2.0/pyauthenticator/__main__.py → pyauthenticator-0.3.0/src/pyauthenticator/_cmd.py +34 -24
- pyauthenticator-0.3.0/src/pyauthenticator/_config.py +42 -0
- pyauthenticator-0.3.0/src/pyauthenticator/_core.py +64 -0
- pyauthenticator-0.3.0/src/pyauthenticator/_user.py +65 -0
- pyauthenticator-0.3.0/src/pyauthenticator/_version.py +34 -0
- pyauthenticator-0.3.0/src/pyauthenticator/api.py +70 -0
- pyauthenticator-0.2.0/MANIFEST.in +0 -3
- pyauthenticator-0.2.0/PKG-INFO +0 -104
- pyauthenticator-0.2.0/pyauthenticator/__init__.py +0 -33
- pyauthenticator-0.2.0/pyauthenticator/_version.py +0 -21
- pyauthenticator-0.2.0/pyauthenticator/share.py +0 -166
- pyauthenticator-0.2.0/pyauthenticator.egg-info/SOURCES.txt +0 -20
- pyauthenticator-0.2.0/pyauthenticator.egg-info/dependency_links.txt +0 -1
- pyauthenticator-0.2.0/pyauthenticator.egg-info/entry_points.txt +0 -2
- pyauthenticator-0.2.0/pyauthenticator.egg-info/requires.txt +0 -4
- pyauthenticator-0.2.0/pyauthenticator.egg-info/top_level.txt +0 -1
- pyauthenticator-0.2.0/setup.cfg +0 -11
- pyauthenticator-0.2.0/setup.py +0 -31
- pyauthenticator-0.2.0/tests/test_cmd.py +0 -89
- pyauthenticator-0.2.0/tests/test_core.py +0 -55
- pyauthenticator-0.2.0/tests/test_share.py +0 -70
- pyauthenticator-0.2.0/tests/test_user_interface.py +0 -30
- pyauthenticator-0.2.0/versioneer.py +0 -1822
- {pyauthenticator-0.2.0 → pyauthenticator-0.3.0}/LICENSE +0 -0
|
@@ -1,16 +1,38 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pyauthenticator
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Similar to the Google authenticator just written in python.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Project-URL: Homepage, https://github.com/jan-janssen/pyauthenticator
|
|
6
|
+
Project-URL: Documentation, https://github.com/jan-janssen/pyauthenticator/blob/master/README.md
|
|
7
|
+
Project-URL: Source, https://github.com/jan-janssen/pyauthenticator
|
|
8
|
+
Project-URL: Tracker, https://github.com/jan-janssen/pyauthenticator/issues
|
|
9
|
+
Author-email: Jan Janssen <jan.janssen@outlook.com>
|
|
10
|
+
License: BSD-3-Clause
|
|
10
11
|
License-File: LICENSE
|
|
12
|
+
Keywords: 2FA,MFA,authenticator
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Topic :: Security
|
|
26
|
+
Classifier: Topic :: Utilities
|
|
27
|
+
Requires-Python: >=3.7
|
|
28
|
+
Requires-Dist: pillow>=11.3.0
|
|
29
|
+
Requires-Dist: pyotp>=2.9.0
|
|
30
|
+
Requires-Dist: pyzbar>=0.1.9
|
|
31
|
+
Requires-Dist: qrcode>=8.2
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
11
33
|
|
|
12
34
|
# pyauthenticator
|
|
13
|
-
[](https://github.com/jan-janssen/pyauthenticator/actions/workflows/pipeline.yml)
|
|
14
36
|
[](https://coveralls.io/github/jan-janssen/pyauthenticator?branch=main)
|
|
15
37
|
[](https://github.com/psf/black)
|
|
16
38
|
|
|
@@ -85,7 +107,7 @@ For any support requests feel free to open an [issue on Github](https://github.c
|
|
|
85
107
|
# For Developers
|
|
86
108
|
## Python Interface
|
|
87
109
|
The same functionality which is available on the command line is also available via the python interface:
|
|
88
|
-
```
|
|
110
|
+
```python
|
|
89
111
|
from pyauthenticator import get_two_factor_code
|
|
90
112
|
get_two_factor_code(service)
|
|
91
113
|
```
|
|
@@ -95,7 +117,7 @@ factor authentication.
|
|
|
95
117
|
## Configuration
|
|
96
118
|
The configuration is stored in `~/.pyauthenticator` it is written in the JSON format. For a given service like `github`
|
|
97
119
|
the config file contains:
|
|
98
|
-
```
|
|
120
|
+
```JSON
|
|
99
121
|
{"google": "otpauth://totp/Google:<username>?secret=<secret>&issuer=Google"}
|
|
100
122
|
```
|
|
101
123
|
With the Google username `<username>` and the corresponding secret `<secret>` being contained in the QR code.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# pyauthenticator
|
|
2
|
-
[](https://github.com/jan-janssen/pyauthenticator/actions/workflows/pipeline.yml)
|
|
3
3
|
[](https://coveralls.io/github/jan-janssen/pyauthenticator?branch=main)
|
|
4
4
|
[](https://github.com/psf/black)
|
|
5
5
|
|
|
@@ -74,7 +74,7 @@ For any support requests feel free to open an [issue on Github](https://github.c
|
|
|
74
74
|
# For Developers
|
|
75
75
|
## Python Interface
|
|
76
76
|
The same functionality which is available on the command line is also available via the python interface:
|
|
77
|
-
```
|
|
77
|
+
```python
|
|
78
78
|
from pyauthenticator import get_two_factor_code
|
|
79
79
|
get_two_factor_code(service)
|
|
80
80
|
```
|
|
@@ -84,10 +84,10 @@ factor authentication.
|
|
|
84
84
|
## Configuration
|
|
85
85
|
The configuration is stored in `~/.pyauthenticator` it is written in the JSON format. For a given service like `github`
|
|
86
86
|
the config file contains:
|
|
87
|
-
```
|
|
87
|
+
```JSON
|
|
88
88
|
{"google": "otpauth://totp/Google:<username>?secret=<secret>&issuer=Google"}
|
|
89
89
|
```
|
|
90
90
|
With the Google username `<username>` and the corresponding secret `<secret>` being contained in the QR code.
|
|
91
91
|
|
|
92
92
|
## License
|
|
93
|
-
The `pyauthenticator` package is licensed under the [BSD-3-Clause license](https://github.com/jan-janssen/pyauthenticator/blob/main/LICENSE).
|
|
93
|
+
The `pyauthenticator` package is licensed under the [BSD-3-Clause license](https://github.com/jan-janssen/pyauthenticator/blob/main/LICENSE).
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"hatchling>=1.27.0",
|
|
4
|
+
"hatch-vcs>=0.5.0",
|
|
5
|
+
"pyotp>=2.9.0",
|
|
6
|
+
"qrcode>=8.2",
|
|
7
|
+
"pyzbar>=0.1.9",
|
|
8
|
+
"pillow>=11.3.0",
|
|
9
|
+
]
|
|
10
|
+
build-backend = "hatchling.build"
|
|
11
|
+
|
|
12
|
+
[project]
|
|
13
|
+
name = "pyauthenticator"
|
|
14
|
+
dynamic = ["version"]
|
|
15
|
+
description = "Similar to the Google authenticator just written in python."
|
|
16
|
+
readme = "README.md"
|
|
17
|
+
requires-python = ">=3.7"
|
|
18
|
+
license = { text = "BSD-3-Clause" }
|
|
19
|
+
authors = [
|
|
20
|
+
{ name = "Jan Janssen", email = "jan.janssen@outlook.com" },
|
|
21
|
+
]
|
|
22
|
+
keywords = ["authenticator", "2FA", "MFA"]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"Development Status :: 5 - Production/Stable",
|
|
25
|
+
"Intended Audience :: Developers",
|
|
26
|
+
"License :: OSI Approved :: BSD License",
|
|
27
|
+
"Operating System :: OS Independent",
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"Programming Language :: Python :: 3.7",
|
|
30
|
+
"Programming Language :: Python :: 3.8",
|
|
31
|
+
"Programming Language :: Python :: 3.9",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Programming Language :: Python :: 3.13",
|
|
36
|
+
"Topic :: Security",
|
|
37
|
+
"Topic :: Utilities",
|
|
38
|
+
]
|
|
39
|
+
dependencies = [
|
|
40
|
+
"pyotp>=2.9.0",
|
|
41
|
+
"qrcode>=8.2",
|
|
42
|
+
"pyzbar>=0.1.9",
|
|
43
|
+
"pillow>=11.3.0",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://github.com/jan-janssen/pyauthenticator"
|
|
48
|
+
Documentation = "https://github.com/jan-janssen/pyauthenticator/blob/master/README.md"
|
|
49
|
+
Source = "https://github.com/jan-janssen/pyauthenticator"
|
|
50
|
+
Tracker = "https://github.com/jan-janssen/pyauthenticator/issues"
|
|
51
|
+
|
|
52
|
+
[project.scripts]
|
|
53
|
+
pyauthenticator = "pyauthenticator._cmd:command_line_parser"
|
|
54
|
+
|
|
55
|
+
[tool.hatch.build]
|
|
56
|
+
include = [
|
|
57
|
+
"src/pyauthenticator"
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.hatch.build.hooks.vcs]
|
|
61
|
+
version-file = "src/pyauthenticator/_version.py"
|
|
62
|
+
|
|
63
|
+
[tool.hatch.build.targets.sdist]
|
|
64
|
+
include = [
|
|
65
|
+
"src/pyauthenticator"
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
[tool.hatch.build.targets.wheel]
|
|
69
|
+
packages = [
|
|
70
|
+
"src/pyauthenticator"
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[tool.hatch.version]
|
|
74
|
+
source = "vcs"
|
|
75
|
+
path = "src/pyauthenticator/_version.py"
|
|
76
|
+
|
|
77
|
+
[tool.coverage.run]
|
|
78
|
+
source = ["pyauthenticator"]
|
|
79
|
+
command_line = "-m unittest discover tests"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generate two factor authentication codes on the command line
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from . import _version
|
|
6
|
+
from pyauthenticator._user import (
|
|
7
|
+
write_qrcode_to_file,
|
|
8
|
+
get_two_factor_code,
|
|
9
|
+
add_two_factor_provider,
|
|
10
|
+
list_two_factor_providers,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"write_qrcode_to_file",
|
|
15
|
+
"get_two_factor_code",
|
|
16
|
+
"add_two_factor_provider",
|
|
17
|
+
"list_two_factor_providers",
|
|
18
|
+
]
|
|
19
|
+
__version__: str = _version.__version__
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Generate two factor authentication codes on the command line
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
import argparse
|
|
5
6
|
import sys
|
|
7
|
+
from typing import Optional, Sequence
|
|
6
8
|
|
|
7
|
-
from pyauthenticator.
|
|
9
|
+
from pyauthenticator._config import load_config
|
|
10
|
+
from pyauthenticator.api import (
|
|
8
11
|
add_service,
|
|
9
12
|
generate_qrcode,
|
|
10
|
-
|
|
13
|
+
get_totp_for_key_in_dict,
|
|
11
14
|
list_services,
|
|
12
|
-
load_config,
|
|
13
15
|
)
|
|
14
16
|
|
|
15
17
|
|
|
16
|
-
def command_line_parser(cmd_args=None):
|
|
18
|
+
def command_line_parser(cmd_args: Optional[Sequence[str]] = None) -> None:
|
|
17
19
|
"""
|
|
18
20
|
Main function primarly used for the command line interface
|
|
19
21
|
"""
|
|
@@ -45,8 +47,14 @@ def command_line_parser(cmd_args=None):
|
|
|
45
47
|
)
|
|
46
48
|
args = parser.parse_args(args=cmd_args)
|
|
47
49
|
if args.qrcode:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
try:
|
|
51
|
+
generate_qrcode(key=args.service, config_dict=config_dict)
|
|
52
|
+
except KeyError:
|
|
53
|
+
_print_service_does_not_exists(
|
|
54
|
+
config_dict=config_dict, service=args.service
|
|
55
|
+
)
|
|
56
|
+
else:
|
|
57
|
+
print("The qrcode file <" + args.service + ".png> was generated.")
|
|
50
58
|
elif args.add:
|
|
51
59
|
add_service(
|
|
52
60
|
key=args.service, qrcode_png_file_name=args.add, config_dict=config_dict
|
|
@@ -60,23 +68,25 @@ def command_line_parser(cmd_args=None):
|
|
|
60
68
|
)
|
|
61
69
|
else:
|
|
62
70
|
try:
|
|
63
|
-
print(
|
|
64
|
-
except
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
+ args.service
|
|
69
|
-
+ '" does not exist.\n\nThe config file ~/.pyauthenticator contains the following services:'
|
|
70
|
-
)
|
|
71
|
-
for service in list_services(config_dict=config_dict):
|
|
72
|
-
print(" * " + service)
|
|
73
|
-
print("\nChoose one of these or add a new service using:")
|
|
74
|
-
else:
|
|
75
|
-
print(
|
|
76
|
-
"The config file ~/.pyauthenticator does not contain any services. To add a new service use:"
|
|
77
|
-
)
|
|
78
|
-
print(" pyauthenticator --add <qr-code.png> <servicename>\n")
|
|
71
|
+
print(get_totp_for_key_in_dict(key=args.service, config_dict=config_dict))
|
|
72
|
+
except KeyError:
|
|
73
|
+
_print_service_does_not_exists(
|
|
74
|
+
config_dict=config_dict, service=args.service
|
|
75
|
+
)
|
|
79
76
|
|
|
80
77
|
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
def _print_service_does_not_exists(config_dict: dict, service: str) -> None:
|
|
79
|
+
if len(config_dict) > 0:
|
|
80
|
+
print(
|
|
81
|
+
'The service "'
|
|
82
|
+
+ service
|
|
83
|
+
+ '" does not exist.\n\nThe config file ~/.pyauthenticator contains the following services:'
|
|
84
|
+
)
|
|
85
|
+
for service_in_config in list_services(config_dict=config_dict):
|
|
86
|
+
print(" * " + service_in_config)
|
|
87
|
+
print("\nChoose one of these or add a new service using:")
|
|
88
|
+
else:
|
|
89
|
+
print(
|
|
90
|
+
"The config file ~/.pyauthenticator does not contain any services. To add a new service use:"
|
|
91
|
+
)
|
|
92
|
+
print(" pyauthenticator --add <qr-code.png> <servicename>\n")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration file handling for pyauthenticator
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from os.path import exists, abspath, expanduser
|
|
7
|
+
from typing import Any, Dict
|
|
8
|
+
|
|
9
|
+
# default configuration file
|
|
10
|
+
default_config_file: str = "~/.pyauthenticator"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def load_config(config_file_to_load: str = default_config_file) -> Dict[str, Any]:
|
|
14
|
+
"""
|
|
15
|
+
Load configuration file
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
config_file_to_load (str): path to config file
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
dict: Dictionary with service names as keys and the otpauth url as values
|
|
22
|
+
"""
|
|
23
|
+
abs_config_path = abspath(expanduser(config_file_to_load))
|
|
24
|
+
if exists(abs_config_path):
|
|
25
|
+
with open(abs_config_path, "r") as f:
|
|
26
|
+
return json.load(f)
|
|
27
|
+
else:
|
|
28
|
+
return {}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def write_config(
|
|
32
|
+
config_dict: Dict[str, Any], config_file_to_write: str = default_config_file
|
|
33
|
+
) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Write configuration file
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
config_dict (dict): configuration dictionary
|
|
39
|
+
config_file_to_write (str): path to config file
|
|
40
|
+
"""
|
|
41
|
+
with open(abspath(expanduser(config_file_to_write)), "w") as f:
|
|
42
|
+
json.dump(config_dict, f)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core functionality to generate two factor authentication codes
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import pyotp
|
|
8
|
+
import qrcode
|
|
9
|
+
from PIL import Image
|
|
10
|
+
from pyzbar.pyzbar import decode
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def decode_qrcode(qrcode_png_file_name: str) -> str:
|
|
14
|
+
"""
|
|
15
|
+
Decode qrcode from png file
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
qrcode_png_file_name (str): path to the png file which contains the qr code
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
str: decoded otpauth string
|
|
22
|
+
"""
|
|
23
|
+
return decode(Image.open(qrcode_png_file_name))[0].data.decode("utf-8")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def encode_qrcode(otpauth_str: str, file_name: str) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Encode otpauth string into qrcode image saved as png file
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
otpauth_str (str): otpauth string
|
|
32
|
+
file_name (str): path to the png file which will contain the qr code
|
|
33
|
+
"""
|
|
34
|
+
qrcode.make(otpauth_str).save(file_name, "PNG")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_totp(otpauth_str: str) -> str:
|
|
38
|
+
"""
|
|
39
|
+
Get TOTP code for a specific service based on its otpauth dictionary
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
otpauth_str (str): otpauth string for the service
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
str: TOTP code for the service
|
|
46
|
+
"""
|
|
47
|
+
otpauth_dict = {
|
|
48
|
+
kv[0]: kv[1]
|
|
49
|
+
for kv in [
|
|
50
|
+
otpvar.split("=") for otpvar in otpauth_str.replace("?", "&").split("&")[1:]
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
kwargs: dict[str, Any] = {}
|
|
55
|
+
if "digits" in otpauth_dict.keys():
|
|
56
|
+
kwargs["digits"] = int(otpauth_dict["digits"])
|
|
57
|
+
if "period" in otpauth_dict.keys():
|
|
58
|
+
kwargs["interval"] = int(otpauth_dict["period"])
|
|
59
|
+
if "issuer" in otpauth_dict.keys():
|
|
60
|
+
kwargs["issuer"] = otpauth_dict["issuer"]
|
|
61
|
+
return pyotp.TOTP(
|
|
62
|
+
**kwargs,
|
|
63
|
+
s=otpauth_dict["secret"],
|
|
64
|
+
).now()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generate two factor authentication codes on the command line
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from pyauthenticator._config import default_config_file, load_config
|
|
7
|
+
from pyauthenticator.api import (
|
|
8
|
+
add_service,
|
|
9
|
+
generate_qrcode,
|
|
10
|
+
get_totp_for_key_in_dict,
|
|
11
|
+
list_services,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def write_qrcode_to_file(service: str, file_name: Optional[str] = None) -> None:
|
|
16
|
+
"""
|
|
17
|
+
Write qrcode to file to scan it with a mobile application
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
service (str): lower case name of the service
|
|
21
|
+
file_name (str/ None): default file name <service.png>
|
|
22
|
+
"""
|
|
23
|
+
generate_qrcode(key=service, config_dict=load_config(), file_name=file_name)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_two_factor_code(service: str) -> str:
|
|
27
|
+
"""
|
|
28
|
+
Generate two factor authentication code
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
service (str): lower case name of the service
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
str: two factor authentication code
|
|
35
|
+
"""
|
|
36
|
+
return get_totp_for_key_in_dict(
|
|
37
|
+
key=service,
|
|
38
|
+
config_dict=load_config(),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def add_two_factor_provider(service: str, qrcode_png_file_name: str) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Add new two factor authentication provider to configuration file
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
service (str): lower case name of the service
|
|
48
|
+
qrcode_png_file_name (str): path to the png file which contains the qr code
|
|
49
|
+
"""
|
|
50
|
+
add_service(
|
|
51
|
+
key=service,
|
|
52
|
+
qrcode_png_file_name=qrcode_png_file_name,
|
|
53
|
+
config_dict=load_config(),
|
|
54
|
+
config_file_to_write=default_config_file,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def list_two_factor_providers() -> list[str]:
|
|
59
|
+
"""
|
|
60
|
+
List all two factor authentication providers in the configuration file
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
list[str]: list of two factor authentication providers
|
|
64
|
+
"""
|
|
65
|
+
return list_services(config_dict=load_config())
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '0.3.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 3, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared functionality to generate two factor authentication codes
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from pyauthenticator._core import decode_qrcode, encode_qrcode, get_totp
|
|
8
|
+
from pyauthenticator._config import default_config_file, write_config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_totp_for_key_in_dict(key: str, config_dict: Dict[str, Any]) -> str:
|
|
12
|
+
"""
|
|
13
|
+
Generate the two factor authentication code
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
key (str): lower case name of the service
|
|
17
|
+
config_dict (dict): configuration dictionary
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
str: two factor authentication code as string
|
|
21
|
+
"""
|
|
22
|
+
return get_totp(otpauth_str=config_dict[key])
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def add_service(
|
|
26
|
+
key: str,
|
|
27
|
+
qrcode_png_file_name: str,
|
|
28
|
+
config_dict: Dict[str, Any],
|
|
29
|
+
config_file_to_write: str = default_config_file,
|
|
30
|
+
) -> None:
|
|
31
|
+
"""
|
|
32
|
+
Add new service to configuration file
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
key (str): lower case name of the service
|
|
36
|
+
qrcode_png_file_name (str): path to the png file which contains the qr code
|
|
37
|
+
config_dict (dict): configuration dictionary
|
|
38
|
+
config_file_to_write (str): path to config file
|
|
39
|
+
"""
|
|
40
|
+
config_dict[key] = decode_qrcode(qrcode_png_file_name=qrcode_png_file_name)
|
|
41
|
+
write_config(config_dict=config_dict, config_file_to_write=config_file_to_write)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def generate_qrcode(
|
|
45
|
+
key: str, config_dict: Dict[str, Any], file_name: Optional[str] = None
|
|
46
|
+
) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Write qrcode to file to scan it with a mobile application
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
key (str): lower case name of the service
|
|
52
|
+
config_dict (dict): configuration dictionary
|
|
53
|
+
file_name (str/ None): default file name <service.png>
|
|
54
|
+
"""
|
|
55
|
+
if file_name is None:
|
|
56
|
+
file_name = key + ".png"
|
|
57
|
+
encode_qrcode(otpauth_str=config_dict[key], file_name=file_name)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def list_services(config_dict: Dict[str, Any]) -> List[str]:
|
|
61
|
+
"""
|
|
62
|
+
List available services
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
config_dict (dict): configuration dictionary
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
list: list of available services
|
|
69
|
+
"""
|
|
70
|
+
return list(config_dict.keys())
|