summaryrefslogtreecommitdiff
path: root/src/services/api/rest/libs/token_auth.py
diff options
context:
space:
mode:
authoromnom62 <omnom62@outlook.com>2026-08-05 09:14:32 +1000
committerJohn Estabrook <jestabro@vyos.io>2026-08-26 13:33:34 -0500
commitf3012e652edef614d4f0ed169b320106a85d83b3 (patch)
treea832563e49b79115497a078f98a748ef2e368113 /src/services/api/rest/libs/token_auth.py
parentd2b54b9d01aee583a80a0cd48a790843d8c85b76 (diff)
downloadvyos-1x-f3012e652edef614d4f0ed169b320106a85d83b3.tar.gz
vyos-1x-f3012e652edef614d4f0ed169b320106a85d83b3.zip
http-api: T8989: add REST Bearer token authentication
Add JWT Bearer token support to the REST API, as an additional authentication method alongside the existing form-field key and X-API-Key header. - New POST /token endpoint mints a JWT for a valid API key - auth_required() accepts Authorization: Bearer <token> alongside existing key/X-API-Key auth - New config nodes: service https api rest authentication {expiration, secret-length} (defaults: 3600s / 32 bytes) - REST tokens use an independent signing secret from GraphQL's, since GraphQL may not be enabled on all deployments and the two subsystems have different expiry requirements - nginx location regex updated to allow /token - service_https.py default-value merge generalized to also apply to the rest node, not just graphql, so REST authentication defaults populate correctly on commit
Diffstat (limited to 'src/services/api/rest/libs/token_auth.py')
-rw-r--r--src/services/api/rest/libs/token_auth.py54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/services/api/rest/libs/token_auth.py b/src/services/api/rest/libs/token_auth.py
new file mode 100644
index 000000000..24c491fde
--- /dev/null
+++ b/src/services/api/rest/libs/token_auth.py
@@ -0,0 +1,54 @@
+# Copyright VyOS maintainers and contributors <maintainers@vyos.io>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+import datetime
+from secrets import token_hex
+
+import jwt
+
+from ...session import SessionState
+
+
+def init_secret():
+ state = SessionState()
+ if state.rest_secret is not None:
+ return
+ length = state.rest_secret_len or 32
+ state.rest_secret = token_hex(length)
+
+
+def generate_token(key_id: str) -> dict:
+ state = SessionState()
+ init_secret()
+ exp_interval = state.rest_token_exp or 3600
+ expiration = datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(
+ seconds=exp_interval
+ )
+ payload = {'iss': 'vyos-rest-api', 'sub': key_id, 'exp': expiration}
+ token = jwt.encode(payload=payload, key=state.rest_secret, algorithm='HS256')
+ return {'token': token, 'expires_in': exp_interval}
+
+
+def verify_token(token: str):
+ state = SessionState()
+ if state.rest_secret is None:
+ return None
+ try:
+ payload = jwt.decode(token, state.rest_secret, algorithms=['HS256'])
+ except jwt.ExpiredSignatureError:
+ return None
+ except jwt.PyJWTError:
+ return None
+ return payload.get('sub')