oidc: send the change from the user update in the callback

This commit is contained in:
Kristoffer Dalby committed 2026-10-27 21:32:34 +00:00
1 parent 12f6b6f10f
commit 48e6fc0c73
2 files changed
+55 -1

No files matched your search

+3 -1
View File
@@ -339,7 +339,7 @@ func (a *AuthProviderOIDC) OIDCCallbackHandler(
return
}
user, _, err := a.createOrUpdateUserFromClaim(&claims)
user, userChange, err := a.createOrUpdateUserFromClaim(&claims)
if err != nil {
httpUserError(writer, NewHTTPError(
http.StatusInternalServerError,
@@ -350,6 +350,8 @@ func (a *AuthProviderOIDC) OIDCCallbackHandler(
return
}
a.h.Change(userChange)
// TODO(kradalby): Is this comment right?
// If the node exists, then the node should be reauthenticated,
// if the node does not exist, and the machine key exists, then
+52
View File
@@ -17,6 +17,7 @@ import (
"github.com/oauth2-proxy/mockoidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
)
@@ -739,3 +740,54 @@ func TestOIDCLoginClearsUnverifiedEmail(t *testing.T) {
require.NoError(t, err)
assert.Empty(t, stored.Email)
}
func TestOIDCCallbackDispatchesUserIdentityChange(t *testing.T) {
b := newOIDCBrowser(t)
provider, ok := b.app.authProvider.(*AuthProviderOIDC)
require.True(t, ok)
provider.cfg.EmailVerifiedRequired = true
user, _, err := provider.createOrUpdateUserFromClaim(&types.OIDCClaims{
Iss: b.idp.Issuer(), Sub: "identity-change", Username: "alice",
Email: "alice@old.example", EmailVerified: true,
})
require.NoError(t, err)
node := b.app.state.CreateRegisteredNodeForTest(user, "identity-node")
node.User = user.Clone()
b.app.state.PutNodeInStoreForTest(*node)
require.NoError(t, b.app.state.UpdatePolicyManagerNodesForTest())
_, err = b.app.state.SetPolicy([]byte(`{
"acls": [{"action": "accept", "src": ["alice@old.example"], "dst": ["*:*"]}]
}`))
require.NoError(t, err)
responses := make(chan *tailcfg.MapResponse, 8)
require.NoError(t, b.app.mapBatcher.AddNode(node.ID, responses, tailcfg.CurrentCapabilityVersion, nil))
t.Cleanup(func() { b.app.mapBatcher.RemoveNode(node.ID, responses) })
initial := <-responses
require.NotEmpty(t, initial.PacketFilters["base"])
b.idp.QueueUser(&mockoidc.MockUser{
Subject: "identity-change", PreferredUsername: "alice",
Email: "alice@new.example", EmailVerified: true,
})
_, registerURL := b.pendingNode(t)
status, _, _ := b.get(t, registerURL)
require.Equal(t, http.StatusOK, status)
stored, err := b.app.state.GetUserByID(types.UserID(user.ID))
require.NoError(t, err)
require.Equal(t, "alice@new.example", stored.Email)
assert.Eventually(t, func() bool {
select {
case response := <-responses:
filters, present := response.PacketFilters["base"]
return present && len(filters) == 0
default:
return false
}
}, 3*time.Second, 20*time.Millisecond, "the connected node must receive the updated filter before registration confirmation")
}