mirror of
https://github.com/yattee/yattee.git
synced 2026-10-29 16:07:20 +00:00
Let only the adopting account retire its marker
Found on the iPad: after signing a second login into an instance, its migrated account could no longer retire the unscoped legacy item when it was deleted, and the instance was left still claiming a pre-revamp login. Storing a credential retires the adoption marker, but it matched on service, instance and identity only. An instance holds several logins, so a sibling sign-in silently withdrew the migrated account's claim on a secret it had nothing to do with. After that the legacy item outlived the account that adopted it, and could be adopted a second time. Erring that way costs nothing — an item that is not deleted is an item nobody is logged out of — but the marker already carries the account it was written for, and deletion authority already checks it. Retiring it now matches on the same thing.
This commit is contained in:
@@ -372,6 +372,33 @@ struct LegacyCredentialAdoptionTests {
|
||||
store.delete(key: KeychainCredentialStore.legacyKey(instanceID: instanceID))
|
||||
}
|
||||
|
||||
@Test("A sibling sign-in does not retire the adopter's marker")
|
||||
func siblingSignInLeavesTheAdoptionMarkerAlone() {
|
||||
let service = makeService()
|
||||
let markers = makeMarkers()
|
||||
let instanceID = UUID()
|
||||
let adopter = Account.migrated(from: instanceID)
|
||||
// A second login the user adds on the same instance.
|
||||
let sibling = Account(instanceID: instanceID)
|
||||
seedLegacyItem(service: service, instanceID: instanceID, value: "legacy-secret")
|
||||
|
||||
let credentials = makeCredentials(service: service, scope: "identity-A", markers: markers)
|
||||
#expect(credentials.adoptLegacyCredential(for: adopter) == true)
|
||||
|
||||
// Signing the sibling in says nothing about the account that adopted
|
||||
// this instance's pre-revamp secret.
|
||||
credentials.setCredential("sibling-secret", for: sibling)
|
||||
#expect(markers.hasAdopted(service: service, instanceID: instanceID, scope: "identity-A") == true)
|
||||
|
||||
// So the adopter can still retire the legacy item when it is deleted —
|
||||
// matching on the instance alone silently withdrew that claim.
|
||||
credentials.deleteLegacyCredentialIfOwned(for: adopter)
|
||||
#expect(legacyValue(service: service, instanceID: instanceID) == nil)
|
||||
|
||||
credentials.deleteCredential(for: adopter)
|
||||
credentials.deleteCredential(for: sibling)
|
||||
}
|
||||
|
||||
@Test("A login the user added themselves never inherits the legacy item")
|
||||
func onlyTheMigratedAccountAdopts() {
|
||||
let service = makeService()
|
||||
|
||||
Reference in New Issue
Block a user