mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-05 13:52:15 +00:00
feat: native app links for passkeys (#12580)
# 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 <[email protected]>
This commit is contained in:
@@ -3,6 +3,7 @@ package project
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
object_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
@@ -68,6 +69,8 @@ func AppOIDCConfigToPb(app *query.OIDCApp) *app_pb.App_OidcConfig {
|
||||
SkipNativeAppSuccessPage: app.SkipNativeAppSuccessPage,
|
||||
BackChannelLogoutUri: app.BackChannelLogoutURI,
|
||||
LoginVersion: loginVersionToPb(app.LoginVersion, app.LoginBaseURI),
|
||||
Ios: iosAppLinkConfigToPb(app.IOSTeamID, app.IOSBundleID),
|
||||
Android: androidAppLinkConfigToPb(app.AndroidPackageName, app.AndroidSHA256CertFingerprints),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -345,3 +348,41 @@ func LoginVersionToDomain(version *app_pb.LoginVersion) (domain.LoginVersion, st
|
||||
return domain.LoginVersionUnspecified, "", nil
|
||||
}
|
||||
}
|
||||
|
||||
func IOSAppLinkConfigToDomain(cfg *app_pb.IOSAppLinkConfig) (teamID, bundleID *string) {
|
||||
if cfg == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return gu.Ptr(cfg.GetTeamId()), gu.Ptr(cfg.GetBundleId())
|
||||
}
|
||||
|
||||
func AndroidAppLinkConfigToDomain(cfg *app_pb.AndroidAppLinkConfig) (packageName *string, fingerprints []string) {
|
||||
if cfg == nil {
|
||||
return nil, nil
|
||||
}
|
||||
fps := cfg.GetSha256CertFingerprints()
|
||||
if fps == nil {
|
||||
fps = []string{}
|
||||
}
|
||||
return gu.Ptr(cfg.GetPackageName()), fps
|
||||
}
|
||||
|
||||
func iosAppLinkConfigToPb(teamID, bundleID string) *app_pb.IOSAppLinkConfig {
|
||||
if teamID == "" && bundleID == "" {
|
||||
return nil
|
||||
}
|
||||
return &app_pb.IOSAppLinkConfig{
|
||||
TeamId: teamID,
|
||||
BundleId: bundleID,
|
||||
}
|
||||
}
|
||||
|
||||
func androidAppLinkConfigToPb(packageName string, fingerprints []string) *app_pb.AndroidAppLinkConfig {
|
||||
if packageName == "" && len(fingerprints) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &app_pb.AndroidAppLinkConfig{
|
||||
PackageName: packageName,
|
||||
Sha256CertFingerprints: fingerprints,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user