Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue on TWA assetlinks acceptation causes navigation bar to appear #310

Closed
jossefaz opened this issue Sep 1, 2020 · 10 comments
Closed

Comments

@jossefaz
Copy link

jossefaz commented Sep 1, 2020

Describe the bug
I openned an issue on the PWABuilder repo , because my assetlinks is correct (sync with google sha 256 keys) but I still got the navigation bar appears when I open the app (from the play store)

To Reproduce
Steps to reproduce the behavior:

  1. Go to : https://ahavatorah.fr/.well-known/assetlinks.json to see the assetlinks.json

  2. Open Asset Links Tool and you'll see that this is the same asset links :
    screenshot

  3. However If you download and open the app from the play store, you'll see the navigation bar

Expected behavior
The navigation bar should disapear

Smartphone (please complete the following information):

  • Device: Samsung A50 and Huawei 9
  • OS: Android 10
  • Browser : chrome
  • Version 85
@applinations
Copy link

Hi, @yossefaz , these are my checklist to make the navigation bar disappear:

  • Check the CACHE of YOUR PWA by
    curl -I https://YOUR_PWA/.well-known/assetlinks.json
    MAKE SURE CACHE CONTROL: NO-cache or max-age=0;

  • Clear ALL Cache your CHROME BROWSER APP (Not your app' cache, but whole chrome) in your Android

  • Make sure you use CHROME AS DEFAULT BROWSER

  • Recheck and Use SHA256 Signing App KEY from GOOGLE PLAY

I hope this can help you out.
Regards

@jossefaz
Copy link
Author

jossefaz commented Sep 1, 2020

@applinations : Your first point sounds like a solution to my problem...
When I curl to my /.well-known/assetlinks.json, it shows that it has a Cache-Control: max-age=2592000.

I indeed added a cache in my .htaccess file but I cannot see there definition for .json file...

I have this definition :

<IfModule mod_expires.c>
  FileETag MTime Size
  AddOutputFilterByType DEFLATE text/plain text/html text/xml text/css application/xml application/xhtml+xml application/rss+xml application/javascript application/x-javascript
  ExpiresActive On
  ExpiresByType text/html "access 600 seconds"
  ExpiresByType application/xhtml+xml "access 600 seconds"
  ExpiresByType text/css "access 1 month"
  ExpiresByType text/javascript "access 1 month"
  ExpiresByType text/x-javascript "access 1 month"
  ExpiresByType application/javascript "access 1 month"
  ExpiresByType application/x-javascript "access 1 month"
  ExpiresByType application/x-shockwave-flash "access 1 month"
  ExpiresByType application/pdf "access 1 month"
  ExpiresByType image/x-icon "access 1 year"
  ExpiresByType image/jpg "access 1 year"
  ExpiresByType image/jpeg "access 1 year"
  ExpiresByType image/png "access 1 year"
  ExpiresByType image/gif "access 1 year"
  ExpiresDefault "access 1 month"

</IfModule>

and finally this one

<IfModule mod_expires.c>
  <IfModule mod_headers.c>
    <filesMatch "\.(ico|jpe?g|png|gif|swf)$">
      Header append Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(css)$">
      Header append Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(js)$">
      Header append Cache-Control "private"
    </filesMatch>
    <filesMatch "\.(x?html?|php)$">
      Header append Cache-Control "private, must-revalidate"
    </filesMatch>
  </IfModule>
</IfModule>

All those definitions are related to Cache Control, but I have not specified for .json file type....do you have any idea from where could come this cache control definition ?

@jossefaz
Copy link
Author

jossefaz commented Sep 1, 2020

@applinations I managed to remove the Cache Control on this file by adding something like :

<filesMatch "\.(json)$">
    FileETag None
    Header unset ETag
    Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
</filesMatch>

And now when I curl I got Cache-Control: max-age=0, no-cache, no-store, must-revalidate

I then:

  • remove the browser cache,
  • made sure that Chrome is the default browser
  • rechecked and Use SHA256 Signing App KEY from GOOGLE PLAY

But still see the navigation bar !

@applinations
Copy link

applinations commented Sep 1, 2020

@yossefaz honestly, I'm not quite familiar with Apache webserver.
I don't use must-revalidate and no-store flags, just no-cache in specific .well-known folder, or more specifically in .well-known/assetlinks.json.
May you post the response of your curl request?
Please make sure you get response content-type: application/json.
After that, you can re-remove your whole Chrome browser caches.
And try again to test your app.

@jossefaz
Copy link
Author

jossefaz commented Sep 2, 2020

@applinations : this is the output of the curl command :

HTTP/1.1 200 OK
Date: Wed, 02 Sep 2020 06:40:34 GMT
Server: Apache
Last-Modified: Tue, 01 Sep 2020 07:56:47 GMT
Accept-Ranges: bytes
Content-Length: 435
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Expires: Fri, 02 Oct 2020 06:40:34 GMT
Vary: Accept-Encoding,User-Agent
Pragma: no-cache
Content-Type: application/json

As you can see here :

  • no cache
  • response content-type: application/json.
  • removed Chrome browser cache

But still got the navigation bar

@andreban
Copy link
Member

andreban commented Sep 2, 2020

@yossefaz did you opt-in into App Signing on the Play Store? If you did, the store will re-sign the APK with a different key and the SHA-256 fingerprint will be different when downloaded from Play. You'll need to run the Asset Links tool on the version downloaded from Play. There's more information here: https://developers.google.com/web/android/trusted-web-activity/quick-start#play-store-signing

@jossefaz
Copy link
Author

jossefaz commented Sep 2, 2020

@andreban : thanks for your help. But unfortunately as I explain at the begining of the issue, and on the other issue I oppenned on PWABuilder repo, that was exactly my case but I already fixed this point and now the SHA256 from the App store and from the assetlinks.json (stored in the .well-known directory) are exactly the same....please refer to the begining of this thread where I show both of them.

@andreban
Copy link
Member

andreban commented Sep 2, 2020

Thanks for this information. Can you confirm if the upload to Play was using the .apk or the .aab (App Bundles) file?

This is the error I'm getting on the phone logs (this was in Chrome Canary, but I see the same in stable):

2020-09-02 09:42:51.671 12844-12844/? W/TWAConnectionPool: Could not find TWAService for fr.ahavatorah.twa
2020-09-02 09:42:51.675 12844-12844/? W/cr_TWAClient: Failed to connect to TWA to execute command
    java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: No service exists for scope
        at l8.e(chromium-TrichromeChromeGoogle.aab-canary-425100033:4)
        at l8.get(chromium-TrichromeChromeGoogle.aab-canary-425100033:42)
        at vP1.run(chromium-TrichromeChromeGoogle.aab-canary-425100033:1)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:336)
        at android.os.Looper.loop(Looper.java:174)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.lang.IllegalArgumentException: No service exists for scope
        at GP1.c(chromium-TrichromeChromeGoogle.aab-canary-425100033:10)
        at GP1.b(chromium-TrichromeChromeGoogle.aab-canary-425100033:5)
        at bR1.run(chromium-TrichromeChromeGoogle.aab-canary-425100033:51)
        at xQ1.b(chromium-TrichromeChromeGoogle.aab-canary-425100033:3)
        at uQ1.onResult(chromium-TrichromeChromeGoogle.aab-canary-425100033:7)
        at ax1.run(chromium-TrichromeChromeGoogle.aab-canary-425100033:1)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

@andreban
Copy link
Member

andreban commented Sep 2, 2020

Taking a deeper look into the application:

The initial URL to be launched is defined as https://ahavatorah.fr/, which is correctly reflected on the asset_statements markup in the Android app:

[{ "relation": ["delegate_permission/common.handle_all_urls"],"target": {"namespace": "web", "site": "https://ahavatorah.fr"}}] 

But, when the URL is opened, it redirects to https://www.ahavatorah.fr/, which is a different origin. Here's the result of running curl:

❯ curl -v https://ahavatorah.fr/
*   Trying 185.2.4.98...
* TCP_NODELAY set
* Connected to ahavatorah.fr (185.2.4.98) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=ahavatorah.fr
*  start date: Jun 15 13:34:19 2020 GMT
*  expire date: Sep 13 13:34:19 2020 GMT
*  subjectAltName: host "ahavatorah.fr" matched cert's "ahavatorah.fr"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: ahavatorah.fr
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Date: Wed, 02 Sep 2020 09:23:54 GMT
< Server: Apache
< X-Powered-By: PHP/7.3.9
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Pragma: no-cache
< X-Redirect-By: WordPress
< Set-Cookie: wordpress_google_apps_login=583c6c33d8efda0c3a099af06c614add; path=/; secure; HttpOnly
< Set-Cookie: PHPSESSID=c2c0885513ea95caf020011c83201d8f; path=/
< Location: https://www.ahavatorah.fr/
< Vary: User-Agent
< Strict-Transport-Security: max-age=31536000; preload
< Cache-Control: private, must-revalidate
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8
< 
* Connection #0 to host ahavatorah.fr left intact
* Closing connection 0

We can see the 301 redirect with Location: https://www.ahavatorah.fr/ there. Since this location is not declared on the Android side, the Digital Asset Links validation fails. If you generate a 2nd version of the app using https://www.ahavatorah.fr/ as the launchUrl, this issue will likely be fixed.

Overall, I see your server answers to both https://www.ahavatorah.fr/superpwa-manifest.json and https://ahavatorah.fr/superpwa-manifest.json. Technically, those are different PWAs and you'll want to redirect the 2nd to the first to avoid that.

@jossefaz
Copy link
Author

jossefaz commented Sep 2, 2020

@andreban : You pointed out the real problem. I fixed it and now it works ! Many thanks for your help !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants