mirror of
https://github.com/zitadel/zitadel.git
synced 2026-08-19 01:14:48 -05:00
# Which Problems Are Solved - Native iOS/Android passkeys need OS trust files on the ZITADEL domain; without them, Associated Domains / App Links verification fails. - Operators could not configure iOS Team ID + Bundle ID or Android package name + SHA-256 fingerprints on OIDC apps. - `/.well-known/apple-app-site-association` and `/.well-known/assetlinks.json` were not served from application config. # How the Problems Are Solved - Add iOS/Android app-link fields on OIDC app create/update (Application API v2 + Management), with validation. - Persist and project those fields; query active app-link configs instance-wide. - Serve AASA (`webcredentials`) and Digital Asset Links (`get_login_creds`) from well-known paths, with configurable `Cache-Control` and fingerprint normalization at serve time. - Console UI to edit the fields, with links to the well-known endpoints. - Operator docs for configuration, endpoints, caching, and verification. # Additional Changes - Document on API fields that well-known responses may be HTTP-cached and platform verifiers may delay propagation. - Runtime config: `WellKnown.AppLinksCacheControlMaxAge` (default `5m`; `0` → `no-store`). # Additional Context - Closes #12497 - Implemented and reviewed as stack: - #12531 API contract - #12532 storage wiring - #12536 well-known endpoints - #12537 console - #12547 docs --------- Co-authored-by: Cursor <cursoragent@cursor.com>
89 lines
2.5 KiB
Go
89 lines
2.5 KiB
Go
package command
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/muhlemmer/gu"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
"github.com/zitadel/zitadel/internal/repository/project"
|
|
)
|
|
|
|
func TestOIDCApplicationWriteModel_NewChangedEvent_AppLinks(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
agg := &project.NewAggregate("project-id", "org-id").Aggregate
|
|
base := func() *OIDCApplicationWriteModel {
|
|
return &OIDCApplicationWriteModel{
|
|
WriteModel: eventstore.WriteModel{
|
|
AggregateID: "project-id",
|
|
ResourceOwner: "org-id",
|
|
},
|
|
AppID: "app-id",
|
|
IOSTeamID: "OLDTEAM",
|
|
IOSBundleID: "com.old.app",
|
|
AndroidPackageName: "com.old.app",
|
|
AndroidSHA256CertFingerprints: []string{"AA:AA"},
|
|
}
|
|
}
|
|
|
|
t.Run("omit keeps existing", func(t *testing.T) {
|
|
t.Parallel()
|
|
wm := base()
|
|
event, hasChanged, err := wm.NewChangedEvent(
|
|
context.Background(), agg, "app-id",
|
|
nil, nil, nil, nil, nil, nil, nil, nil,
|
|
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
nil, nil, nil, nil,
|
|
)
|
|
require.NoError(t, err)
|
|
assert.False(t, hasChanged)
|
|
assert.Nil(t, event)
|
|
})
|
|
|
|
t.Run("set changes fields", func(t *testing.T) {
|
|
t.Parallel()
|
|
wm := base()
|
|
event, hasChanged, err := wm.NewChangedEvent(
|
|
context.Background(), agg, "app-id",
|
|
nil, nil, nil, nil, nil, nil, nil, nil,
|
|
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
gu.Ptr("NEWTEAM"),
|
|
gu.Ptr("com.new.app"),
|
|
gu.Ptr("com.new.app"),
|
|
[]string{"BB:BB"},
|
|
)
|
|
require.NoError(t, err)
|
|
require.True(t, hasChanged)
|
|
require.NotNil(t, event)
|
|
assert.Equal(t, gu.Ptr("NEWTEAM"), event.IOSTeamID)
|
|
assert.Equal(t, gu.Ptr("com.new.app"), event.IOSBundleID)
|
|
assert.Equal(t, gu.Ptr("com.new.app"), event.AndroidPackageName)
|
|
assert.Equal(t, &[]string{"BB:BB"}, event.AndroidSHA256CertFingerprints)
|
|
})
|
|
|
|
t.Run("clear with empty values", func(t *testing.T) {
|
|
t.Parallel()
|
|
wm := base()
|
|
event, hasChanged, err := wm.NewChangedEvent(
|
|
context.Background(), agg, "app-id",
|
|
nil, nil, nil, nil, nil, nil, nil, nil,
|
|
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
gu.Ptr(""),
|
|
gu.Ptr(""),
|
|
gu.Ptr(""),
|
|
[]string{},
|
|
)
|
|
require.NoError(t, err)
|
|
require.True(t, hasChanged)
|
|
require.NotNil(t, event)
|
|
assert.Equal(t, gu.Ptr(""), event.IOSTeamID)
|
|
assert.Equal(t, gu.Ptr(""), event.IOSBundleID)
|
|
assert.Equal(t, gu.Ptr(""), event.AndroidPackageName)
|
|
assert.Equal(t, &[]string{}, event.AndroidSHA256CertFingerprints)
|
|
})
|
|
}
|