What does the apple-app-site-association file contain, and how does the system verify a domain?

6.7.3 · L3 · Learning

Predict first

Which paths are excluded from opening the app, and what is the team ID?

import Foundation

struct AASA: Decodable {
    struct AppLinks: Decodable {
        struct Detail: Decodable {
            struct Component: Decodable {
                let path: String
                let exclude: Bool?
                enum CodingKeys: String, CodingKey { case path = "/", exclude }
            }
            let appIDs: [String]
            let components: [Component]
        }
        let details: [Detail]
    }
    let applinks: AppLinks
}

let json = #"{"applinks":{"details":[{"appIDs":["ABCDE12345.com.example.app"],"components":[{"/":"/products/*"},{"/":"/admin/*","exclude":true}]}]}}"#
let file = try JSONDecoder().decode(AASA.self, from: Data(json.utf8))
let detail = file.applinks.details[0]
print(detail.appIDs[0].split(separator: ".", maxSplits: 1).map(String.init), detail.components.filter { $0.exclude == true }.map(\.path))
  • ["ABCDE12345", "com.example.app"] ["/admin/*"]
  • ["com", "example"] ["/products/*"]
  • [] []

Mental model. The app says “I handle links for this site”, and the site answers with a signed list of which app and which paths. Both must match for the shortcut to be honoured.

You host a JSON file, the apple-app-site-association (AASA), at https://example.com/.well-known/apple-app-site-association, served over HTTPS with no redirects. Its applinks section lists, per app, the app ID (the team ID and bundle ID, like ABCDE12345.com.example.app) and which URL paths the app handles, with patterns such as /products/* and exclude rules for paths that must stay on the web. The app declares the domain in the associated-domains entitlement as applinks:example.com (similar entries exist for webcredentials: and activitycontinuation:).

Verification is two-way: the app claims the domain, and the domain’s file names the app. The system fetches the file through Apple’s CDN when the app is installed or updated (not on every tap), so changes to the file can take time to propagate. Practical points: the path patterns decide which links open the app, so be explicit about exclusions; use the developer mode of the associated-domains entry while testing to bypass the CDN cache; and a wrong team ID or an HTTP redirect silently disables the link. The same file mechanism backs shared web credentials and Handoff.

The app ID is the team ID followed by the bundle ID, and the component with "exclude": true is the path that stays on the web.

Common traps

  • Serving the file behind a redirect or with a wrong content type. The system will not follow it and the link stays in Safari.
  • Editing the file and testing immediately. The CDN and install-time fetch delay the effect. Use developer mode in the entitlement.

They might follow up with

  • Where does the team ID come from? Your Apple Developer account; the app ID is that prefix plus the bundle identifier.
  • How do you keep a path on the web only? Add an exclude component for it in the file.

Related questions

  • 6.7.2 What is the difference between a custom URL scheme and a universal link, and which do you use?
  • 6.1.3 What are entitlements, and what happens when they do not match the provisioning profile?

← What is the difference between a custom URL scheme and a universal…