diff options
| author | omnom62 <omnom62@outlook.com> | 2026-08-05 09:14:32 +1000 |
|---|---|---|
| committer | John Estabrook <jestabro@vyos.io> | 2026-08-26 13:33:34 -0500 |
| commit | f3012e652edef614d4f0ed169b320106a85d83b3 (patch) | |
| tree | a832563e49b79115497a078f98a748ef2e368113 /src/services/api/rest/libs/token_auth.py | |
| parent | d2b54b9d01aee583a80a0cd48a790843d8c85b76 (diff) | |
| download | vyos-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.py | 54 |
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') |
