Apple app site association not working over AWS CloudFront and S3

4.8k views Asked by At

Here's my setup:

  • I have an AWS CloudFront distribution with custom and valid SSL certificate (from ACM)
  • the CF distribution points to an S3 bucket
  • My domain example.com is a A record with alias to my CF distribution
  • I uploaded apple-app-site-association and .well-known/apple-app-site-association to my bucket with the following parameters: Public Read, Content-Type=application/pkcs7-mime

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!

3

There are 3 answers

0
APE On BEST ANSWER

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

4
Gereon On

From the docs:

Note
If your app runs in iOS 9 or later and you use HTTPS to serve the apple-app-site-association file, you can create a plain text file that uses the application/json MIME type and you don’t need to sign it. If you support Handoff and Shared Web Credentials in iOS 8, you still need to sign the file as described in Shared Web Credentials Reference.

So the content-type: application/pkcs7-mime in your response seems wrong, try changing that to application/json.

0
Ciryon On

In case it helps someone else I had similar problem with the file not being valid with correct content type header. I re-uploaded the file using the following:

aws s3 cp --content-type "application/pkcs7-mime" public/.well-known/apple-app-site-association s3://mywebsite/.well-known/