Refuse multi-owner factors and lock ownership during recovery
All checks were successful
Authentication acceptance / acceptance (push) Successful in 1m5s
Authentication acceptance / provider-contract (push) Successful in 13s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
This commit is contained in:
tegwick 2026-09-13 21:21:24 +02:00
parent 30cd99cad1
commit 63b3070853
2 changed files with 17 additions and 2 deletions

View file

@ -76,17 +76,24 @@ class ProviderStore:
if not identity.resolver or identity.uid in (None,''):return None
values=get_tokens(user=identity,serial=serial)
if len(values)!=1:return None
return values[0].token
from privacyidea.models import TokenOwner
token=values[0].token
if TokenOwner.query.filter_by(token_id=token.id).count()!=1:raise RecoveryError("shared_factor_not_supported")
return token
def snapshot(self,user,serial):
token=self._token(user,serial)
if token is None:return None
data=token.get_vars()
return {k:data[k] for k in ('id','serial','user_id','resolver','realms','active','rollout_state','tokentype')}
def disable(self,user,serial,expected):
from privacyidea.models import db,Token
from privacyidea.models import db,Token,TokenOwner
token=self._token(user,serial)
if token is None:raise RecoveryError('factor_not_owned_by_target')
if db.engine.dialect.name=="postgresql":
from sqlalchemy import text
db.session.execute(text("SET LOCAL lock_timeout = '5s'"))
locked=db.session.query(Token).filter(Token.id==token.id).with_for_update().one()
db.session.query(TokenOwner).filter(TokenOwner.token_id==token.id).with_for_update(of=TokenOwner).all()
db.session.refresh(locked)
if fingerprint(self.snapshot(user,serial))!=expected:
db.session.rollback();raise RecoveryError('stale_preview')