Skip to content

Commit

Permalink
v3: Drop support for legacy_api_key_v1 (#999)
Browse files Browse the repository at this point in the history
  • Loading branch information
psrok1 authored Dec 12, 2024
1 parent 803c316 commit 8d29bcd
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 38 deletions.
6 changes: 0 additions & 6 deletions mwdb/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from mwdb.core.app import api, app
from mwdb.core.config import app_config
from mwdb.core.deprecated import DeprecatedFeature, uses_deprecated_api
from mwdb.core.log import getLogger, setup_logger
from mwdb.core.metrics import metric_api_requests, metrics_enabled
from mwdb.core.plugins import PluginAppContext, load_plugins
Expand Down Expand Up @@ -204,11 +203,6 @@ def require_auth():
# Not a session token? Maybe APIKey token
if g.auth_user is None:
g.auth_user = APIKey.verify_token(token)
# Still nothing? Maybe legacy API key
if g.auth_user is None:
g.auth_user = User.verify_legacy_token(token)
if g.auth_user is not None:
uses_deprecated_api(DeprecatedFeature.legacy_api_key_v1)

if g.auth_user:
if (
Expand Down
6 changes: 3 additions & 3 deletions mwdb/core/auth.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import datetime
from enum import Enum
from typing import Any, Set
from typing import Any

import jwt

Expand Down Expand Up @@ -52,14 +52,14 @@ def verify_token(token: str, scope: AuthScope) -> Any:
return data


def verify_legacy_token(token: str, required_fields: Set[str]) -> Any:
def verify_legacy_api_key(token: str) -> Any:
try:
data = jwt.decode(
token,
key=app_config.mwdb.secret_key,
algorithms=["HS512"],
)
if set(data.keys()) != required_fields:
if set(data.keys()) != {"login", "api_key_id"}:
return None

except jwt.InvalidTokenError:
Expand Down
2 changes: 0 additions & 2 deletions mwdb/core/deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@


class DeprecatedFeature(Enum):
# Unmanageable API keys, deprecated in v2.0.0
legacy_api_key_v1 = "legacy_api_key_v1"
# API keys non-complaint with RFC7519
# Deprecated in v2.7.0
legacy_api_key_v2 = "legacy_api_key_v2"
Expand Down
9 changes: 7 additions & 2 deletions mwdb/model/api_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm.exc import NoResultFound

from mwdb.core.auth import AuthScope, generate_token, verify_legacy_token, verify_token
from mwdb.core.auth import (
AuthScope,
generate_token,
verify_legacy_api_key,
verify_token,
)
from mwdb.core.deprecated import DeprecatedFeature, uses_deprecated_api

from . import db
Expand Down Expand Up @@ -35,7 +40,7 @@ def verify_token(token):

if data is None:
# check for legacy API Token
data = verify_legacy_token(token, required_fields={"login", "api_key_id"})
data = verify_legacy_api_key(token)
if data is None:
return None
else:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Removed User.version_uid column
Revision ID: 56adf974831e
Revises: 52bb55f76ef3
Create Date: 2024-12-11 18:21:42.442984
"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "56adf974831e"
down_revision = "52bb55f76ef3"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("user", "version_uid")
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"user",
sa.Column(
"version_uid", sa.VARCHAR(length=16), autoincrement=False, nullable=True
),
)
# ### end Alembic commands ###
20 changes: 1 addition & 19 deletions mwdb/model/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm.exc import NoResultFound

from mwdb.core.auth import AuthScope, generate_token, verify_legacy_token, verify_token
from mwdb.core.auth import AuthScope, generate_token, verify_token
from mwdb.core.capabilities import Capabilities

from . import db
Expand All @@ -25,8 +25,6 @@ class User(db.Model):
email = db.Column(db.String(128), nullable=False)

password_hash = db.Column(db.String(128))
# Legacy "version_uid", todo: remove it when users are ready
version_uid = db.Column(db.String(16))
# Password version (set password link and session token validation)
# Invalidates set password link or session when password has been changes
password_ver = db.Column(db.String(16))
Expand Down Expand Up @@ -224,22 +222,6 @@ def verify_set_password_token(token) -> Optional["User"]:
)
return None if result is None else result[0]

@staticmethod
def verify_legacy_token(token):
data = verify_legacy_token(token, required_fields={"login", "version_uid"})
if data is None:
return None

try:
user_obj = User.query.filter(User.login == data["login"]).one()
except NoResultFound:
return None

if user_obj.version_uid != data["version_uid"]:
return None

return user_obj

def is_member(self, group_id):
groups = db.session.query(Member.group_id).filter(Member.user_id == self.id)
return group_id.in_(groups)
Expand Down
6 changes: 0 additions & 6 deletions tests/backend/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,20 +120,14 @@ def test_jwt_legacy_api_keys(admin_session):
secret_key = "e2e-testing-key"
api_key_id = admin_session.api_key_create("admin", "testing-key").json()["id"]

pre2_0_payload = {"login": "admin", "version_uid": None}
pre2_7_payload = {"login": "admin", "api_key_id": api_key_id}

pre2_0_token = jwt.encode(pre2_0_payload, secret_key, algorithm="HS512")
pre2_7_token = jwt.encode(pre2_7_payload, secret_key, algorithm="HS512")

session = MwdbTest()
response = session.request("get", "/server")
assert not response["is_authenticated"]

session.set_auth_token(pre2_0_token)
response = session.request("get", "/server")
assert response["is_authenticated"]

session.set_auth_token(pre2_7_token)
response = session.request("get", "/server")
assert response["is_authenticated"]
Expand Down

0 comments on commit 8d29bcd

Please sign in to comment.