Skip to content

fix(identity): update last_sign_in_at on subsequent external sign-ins (fixes #2563) - #2714

Open
deepshekhardas wants to merge 2 commits into
supabase:masterfrom
deepshekhardas:fix/2563-identity-last-sign-in
Open

fix(identity): update last_sign_in_at on subsequent external sign-ins (fixes #2563)#2714
deepshekhardas wants to merge 2 commits into
supabase:masterfrom
deepshekhardas:fix/2563-identity-last-sign-in

Conversation

@deepshekhardas

Copy link
Copy Markdown

fix(identity): update last_sign_in_at on subsequent external sign-ins (fixes #2563)

createAccountFromExternalIdentity already listed last_sign_in_at in
the UpdateOnly call for the AccountExists path, but never assigned
the current time to identity.LastSignInAt first — so the column
silently kept its creation-time value. The docs describe
last_sign_in_at as "the timestamp that the identity was last used to
sign in", but it froze at identity creation.

Set identity.LastSignInAt = &now before the update so subsequent
sign-ins via the identity refresh the timestamp.

Comment thread internal/api/external.go

now := time.Now()
identity.IdentityData = identityData
identity.LastSignInAt = &now

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: LOW

An external IdP response can drive an existing, unconfirmed identity through this branch. When unverified provider email sign-ins are disallowed, the surrounding flow returns CommitWithError, which commits changes despite issuing no token; this new assignment therefore lets rejected attempts advance last_sign_in_at and poison the identity’s sign-in/audit signal.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: The fix requires changes at two separate locations in createAccountFromExternalIdentity:

  1. In the AccountExists case (around lines 370–375): Remove the identity.LastSignInAt = &now assignment (line 372) and drop "last_sign_in_at" from the UpdateOnly call so only identity_data is eagerly persisted — the call should become tx.UpdateOnly(identity, "identity_data"). This prevents the timestamp from being written to the database in the same transaction that can be committed via CommitWithError.

  2. In the confirmed-user success path (the else branch around line 440): After the audit log entry, add the deferred last_sign_in_at update that was removed above:

now := time.Now()
identity.LastSignInAt = &now
if terr = tx.UpdateOnly(identity, "last_sign_in_at"); terr != nil {
    return 0, nil, terr
}

This ensures last_sign_in_at is only persisted when the sign-in actually succeeds (i.e., a token will be issued), rather than being committed eagerly for rejected attempts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

auth.identities.last_sign_in_at not updated after subsequent sign-ins (contradicts docs)

1 participant