libtimed 0.6.1__tar.gz → 0.6.2__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.
- {libtimed-0.6.1 → libtimed-0.6.2}/PKG-INFO +1 -1
- {libtimed-0.6.1 → libtimed-0.6.2}/pyproject.toml +1 -1
- {libtimed-0.6.1 → libtimed-0.6.2}/src/libtimed/oidc.py +36 -2
- {libtimed-0.6.1 → libtimed-0.6.2}/LICENSE +0 -0
- {libtimed-0.6.1 → libtimed-0.6.2}/README.md +0 -0
- {libtimed-0.6.1 → libtimed-0.6.2}/src/libtimed/__init__.py +0 -0
- {libtimed-0.6.1 → libtimed-0.6.2}/src/libtimed/models.py +0 -0
- {libtimed-0.6.1 → libtimed-0.6.2}/src/libtimed/transforms.py +0 -0
|
@@ -4,6 +4,7 @@ import base64
|
|
|
4
4
|
import datetime
|
|
5
5
|
import http.server
|
|
6
6
|
import json
|
|
7
|
+
import time
|
|
7
8
|
import webbrowser
|
|
8
9
|
from urllib.parse import urlparse
|
|
9
10
|
|
|
@@ -41,18 +42,20 @@ class OIDCHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
|
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
class OIDCClient:
|
|
44
|
-
def __init__(self, client_id, sso_url, sso_realm, auth_path):
|
|
45
|
+
def __init__(self, client_id, sso_url, sso_realm, auth_path, use_device_flow=False):
|
|
45
46
|
self.client_id = client_id
|
|
46
47
|
self.sso_url = sso_url
|
|
47
48
|
self.sso_realm = sso_realm
|
|
48
49
|
self.auth_path = auth_path
|
|
50
|
+
self.use_device_flow = use_device_flow
|
|
49
51
|
|
|
50
52
|
def autoconfig(self):
|
|
51
53
|
data = requests.get(
|
|
52
|
-
f"{self.sso_url}/
|
|
54
|
+
f"{self.sso_url}/realms/{self.sso_realm}/.well-known/openid-configuration"
|
|
53
55
|
).json()
|
|
54
56
|
self.authorization_endpoint = data["authorization_endpoint"]
|
|
55
57
|
self.token_endpoint = data["token_endpoint"]
|
|
58
|
+
self.device_endpoint = data["device_authorization_endpoint"]
|
|
56
59
|
|
|
57
60
|
def start_browser_flow(self):
|
|
58
61
|
# construct the authorization request
|
|
@@ -74,6 +77,29 @@ class OIDCClient:
|
|
|
74
77
|
self.code = code
|
|
75
78
|
return True
|
|
76
79
|
|
|
80
|
+
def start_device_flow(self):
|
|
81
|
+
# construct the authorization request
|
|
82
|
+
auth_data = requests.post(self.device_endpoint, data={"client_id": self.client_id}).json()
|
|
83
|
+
verification_uri_complete = auth_data["verification_uri_complete"]
|
|
84
|
+
verification_uri = auth_data["verification_uri"]
|
|
85
|
+
device_code = auth_data["device_code"]
|
|
86
|
+
user_code = auth_data["user_code"]
|
|
87
|
+
|
|
88
|
+
# open the browser to the authorization URL
|
|
89
|
+
webbrowser.open_new(verification_uri_complete)
|
|
90
|
+
# print manual instructions
|
|
91
|
+
print(f"Please visit {verification_uri} and enter the code {user_code}")
|
|
92
|
+
time.sleep(5)
|
|
93
|
+
|
|
94
|
+
resp = {}
|
|
95
|
+
while "access_token" not in resp:
|
|
96
|
+
resp = requests.post(self.token_endpoint, data={"client_id": self.client_id, "grant_type": "urn:ietf:params:oauth:grant-type:device_code", "device_code": device_code}).json()
|
|
97
|
+
print(resp)
|
|
98
|
+
time.sleep(5)
|
|
99
|
+
access_token = resp["access_token"]
|
|
100
|
+
return access_token
|
|
101
|
+
|
|
102
|
+
|
|
77
103
|
def get_token(self):
|
|
78
104
|
# construct the token request
|
|
79
105
|
token_request = {
|
|
@@ -113,9 +139,11 @@ class OIDCClient:
|
|
|
113
139
|
return now.timestamp() < expires_at
|
|
114
140
|
|
|
115
141
|
def keyring_get(self):
|
|
142
|
+
return []
|
|
116
143
|
return keyring.get_password("system", "libtimed_token_" + self.client_id)
|
|
117
144
|
|
|
118
145
|
def keyring_set(self, token):
|
|
146
|
+
return True
|
|
119
147
|
keyring.set_password("system", "libtimed_token_" + self.client_id, token)
|
|
120
148
|
|
|
121
149
|
def authorize(self):
|
|
@@ -124,6 +152,12 @@ class OIDCClient:
|
|
|
124
152
|
return cached_token
|
|
125
153
|
|
|
126
154
|
self.autoconfig()
|
|
155
|
+
if self.use_device_flow:
|
|
156
|
+
if token:= self.start_device_flow():
|
|
157
|
+
self.keyring_set(token)
|
|
158
|
+
return token
|
|
159
|
+
return False
|
|
160
|
+
|
|
127
161
|
if self.start_browser_flow():
|
|
128
162
|
token = self.get_token()
|
|
129
163
|
if not token:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|