iosamazon-web-servicesamazon-s3amazon-cloudfrontapple-app-site-associate

Apple app site association not working over AWS CloudFront and S3


Here's my setup:

My apple-app-site-association is as follows:

{
   "webcredentials": {
       "apps": [    "TeamID.BundleId1",
                    "TeamID.BundleId2" ]
    }
}

Of course the values are replaced with my team's ID and the bundle Ids of my 2 apps.

When I run

curl -i https://example.com/apple-app-site-association

or

curl -i https://example.com/.well-known/apple-app-site-association

I have the following result:

HTTP/2 200 
content-type: application/pkcs7-mime
content-length: 156
date: Wed, 18 Dec 2019 03:08:15 GMT
last-modified: Wed, 18 Dec 2019 03:04:14 GMT
etag: "redacted"
x-amz-server-side-encryption: AES256
accept-ranges: bytes
server: AmazonS3
x-cache: Miss from cloudfront
via: 1.1 redacted.cloudfront.net (CloudFront)
x-amz-cf-pop: redacted
x-amz-cf-id: redacted

{
   "webcredentials": {
       "apps": [    "TeamID.BundleId1",
                    "TeamID.BundleId2" ]
    }
}

Which tells me the file is valid and correctly hosted.

On the Xcode side, my target has the following row in Signing & Capabilities > Associated Domains:

webcredentials:example.com

So my entitlements file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>aps-environment</key>
    <string>development</string>
    <key>com.apple.developer.associated-domains</key>
    <array>
        <string>webcredentials:example.com</string>
    </array>
</dict>
</plist>

However when I go to my Sign Up screen on the app, I have the following console log:

[AutoFill] Cannot show Automatic Strong Passwords for app bundleID: BundleId due to error: Cannot save passwords for this app. Make sure you have set up Associated Domains for your app and AutoFill Passwords is enabled in Settings

I am testing on a real device on iOS 13 and AutoFill is enabled.

Note: my app is not live yet (in case I am advised to use the Apple crawler aka App Search API Validation Tool)

Thanks in advance for any help!


Solution

  • I finally managed to get it working. I did 4 different things, I think only 2 of them are important but I'll post them all here in case it helps someone with the same issue.

    1: Use my iPhone Developer ID instead of my Team ID (important)

    As I was debugging the app on dev environment, the app is signed with my iPhone Developer certificate, not my team's production certificate. So I changed my apple-app-site-association file from

    {
       "webcredentials": {
           "apps": [    "TeamID.BundleId1",
                        "TeamID.BundleId2" ]
        }
    }
    

    to

    {
       "webcredentials": {
           "apps": [    "TeamID.BundleId1",
                        "TeamID.BundleId2",
                        "iPhoneDeveloperID.BundleId1",
                        "iPhoneDeveloperID.BundleId2" ]
        }
    }
    

    2: Invalidate AWS CloudFront cache before testing (important)

    While testing, I eventually found out that I was sometimes getting an old version of my apple-app-site-association, depending on which device or software application I was using to fetch it. So I logged in to the CF console, selected my distribution, selected the Invalidations tab, and created an Invalidation with Object Path /.well-known/apple-app-site-association.

    3: Add App Links

    I'm not sure whether that made any difference for my issue, as I only invalidated the cache after I tried this, but just in case it helps someone, I decided to add App Links to my app. I added the following object after webcredentials in my apple-app-site-association

    "applinks": {
            "apps": [],
            "details": [
                {
                    "appID": "iPhoneDeveloperID.BundleId1",
                    "paths": [ "*"]
                },
                {
                    "appID": "iPhoneDeveloperID.BundleId2",
                    "paths": [ "*" ]
                },
                {
                    "appID": "TeamID.BundleId1",
                    "paths": [ "*"]
                },
                {
                    "appID": "TeamID.BundleId2",
                    "paths": [ "*" ]
                }
            ]
        }
    

    Make sure the app you're testing is at the top, as the others will get discarded (the first wildcard wins). This must obviously be changed before going to production.

    And I added the following entitlement to my app

    <string>applinks:example.com</string>
    

    4: Only use .well-known

    Again, I don't believe this is important, but instead of having to upload my file twice for each test, I stopped using the root directory, and only uploaded to /.well-known/apple-app-site-association