fix(auth): reject stale provider authority recovery

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-07-30 17:40:11 +08:00
parent c71828f980
commit 9ef272e32b
2 changed files with 67 additions and 0 deletions

View file

@ -106,6 +106,20 @@ class ProviderAuthorityStateTransaction {
.orElse(new AuthorityLockEvaluation(
IdentityProviderStatus.MISCONFIGURED,
null));
if (authority.ready()
&& !expectedFingerprint.equals(
authority.persistedFingerprint())) {
stateRepository.markAuthorityMismatch(
descriptor.providerCode(),
descriptor.protocol(),
expectedFingerprint);
authority = stateRepository
.findById(descriptor.providerCode())
.map(this::evaluation)
.orElse(new AuthorityLockEvaluation(
IdentityProviderStatus.MISCONFIGURED,
null));
}
boolean recovered = updated == 1
&& authority.ready()
&& expectedFingerprint.equals(

View file

@ -346,6 +346,59 @@ class ProviderAuthorityStateTransactionTest {
org.mockito.ArgumentMatchers.any());
}
@Test
void readyStateWithDifferentFingerprintIsPersistedAsMismatch() {
String differentFingerprint = "a".repeat(64);
IdentityProviderState staleReady = IdentityProviderState.ready(
"github",
"oauth2-github",
"https://github.example",
differentFingerprint,
NOW);
IdentityProviderState mismatch =
IdentityProviderState.authorityMismatch(
"github",
"oauth2-github",
"https://github.example",
differentFingerprint,
NOW);
when(stateRepository.recoverSameAuthority(
"github",
"oauth2-github",
FINGERPRINT)).thenReturn(0);
when(stateRepository.findById("github"))
.thenReturn(
Optional.of(staleReady),
Optional.of(mismatch));
when(stateRepository.markAuthorityMismatch(
"github",
"oauth2-github",
FINGERPRINT)).thenReturn(1);
SameAuthorityRecoveryEvaluation recovery =
transaction.recoverSameAuthority(
GITHUB,
FINGERPRINT,
recoveryContext());
assertThat(recovery.recovered()).isFalse();
assertThat(recovery.authority().state())
.isEqualTo(IdentityProviderStatus.AUTHORITY_MISMATCH);
verify(stateRepository).markAuthorityMismatch(
"github",
"oauth2-github",
FINGERPRINT);
verify(auditLogService, never()).record(
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any());
}
private static ProviderDescriptor githubDescriptor() {
return new ProviderDescriptor(
"github",