mkdocs-encryptcontent-plugin icon indicating copy to clipboard operation
mkdocs-encryptcontent-plugin copied to clipboard

Users re-prompted for password when navigating between pages

Open ElliotSknr opened this issue 1 year ago • 12 comments

I have found that when navigating between different pages in my documentation with a global password enabled, that I am randomly being re-prompted for my password. A quick refresh of the page usually allows me in without having to retype the password in.

I am using a global password via the password_inventory with a list of passwords like so:

The behaviour occurs both when run via mkdocs serve, or when building and hosting in prod. Lastly I am using material for MkDocs, without any of the patches applied.

plugins:
    - encryptcontent:
        remember_password: True
        session_storage: True
        search_index: 'clear'
        inject:
            md-content: [div, class]
        encrypted_something:
            md-footer__inner: [nav, class] #Footer
            md-nav: [nav, class] #Menu and toc
            md-search: [div, class]
        title_prefix: ''
        password_inventory:
            _global:
                - password123
                - hunter2

When disabling the material theme, I no longer experience this behaviour, so it does seem to be associated with Material for MkDocs

ElliotSknr avatar Jan 17 '24 12:01 ElliotSknr

image I found that this log is printed out to the console when the issue occurs.

ElliotSknr avatar Jan 18 '24 16:01 ElliotSknr

Looks like it tries to use the CryptoJS, but it's not yet loaded. Normally this is circumvented with the "defer" attribute of "decrypt-content.js". We could try adding an additional safety net, by checking if CryptoJS is defined and recall the decryption a few milliseconds later and hope CryptJS is defined then...

Have you tried setting webcrypto: true? Using webcrypto might not cause such problems.

unverbuggt avatar Jan 19 '24 23:01 unverbuggt

One note on md-search: [div, class]: it was discussed in #52, that we currently found no way to show the search field only after decryption (for unpatched mkdocs-material with search_index: 'clear') and we should not do so (as the search index contains the whole page unencrypted). So it's better to disable the search completely or set search_index: 'encrypted' to remove encrypted pages from the index. But if you really want to do this maybe set a custom block in mkdocs-material where search is invisible by css attribute (and then use javascript to set it to visible after successful decryption).

Maybe this is related to the problem, but I couldn't reproduce said behavior (with neither crypto-js nor webcrypto). Maybe it is browser or cpu speed dependant. Or it is a bug in cryto-js, but crypto-js is pretty much dead, as all it's functionality is provided by the browser engines nowadays through webcrypto.

unverbuggt avatar Jan 21 '24 12:01 unverbuggt

No luck unfortunately with setting webcrypto: True. The behaviour seems to have changed slightly as it now always displays the password screen whenever navigating between pages, requiring a refresh after every navigation. The error message did change too after this modification

Screenshot 2024-01-23 at 15 34 10

I've gone ahead and disabled search completely too following on from your prior comment, this didn't change the password re-prompting issue behaviour either unfortunately. I've got a few different machines I can test on so I'll see if that makes any difference with a minimal reproducible example project I'll setup, will update once I get the time.

ElliotSknr avatar Jan 23 '24 17:01 ElliotSknr

Good news! I was able to track the issue down to a Material feature called navigation.instant Removing this (as well as navigation.instant.progress) from my features block has resolved the issue.

theme:
    name: material
    features:
#        - navigation.instant
#        - navigation.instant.progress

For me the above change is fine as I don't require the instant loading feature.

Update: It looks like this has been discussed & fixed before https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/18 Potentially a regression occurred since?

ElliotSknr avatar Jan 24 '24 17:01 ElliotSknr

I'll have a look on what causes the issue with navigation.instant. There have been much code changes since the possible fix from that issue.

unverbuggt avatar Jan 25 '24 13:01 unverbuggt

I don't know how exactly mkdocs-material does the instant reload. What I see is that the encryptcontent html template is being reloaded and thus the javascript part.
Sometimes (could only reproduce in chrome) the reload of CryptoJS fails somehow, breaking decryption. The webcrypto alternative was completely broken in this case (I fixed it today in the development version).
I could get it working with webcrypto enabled, but the CryptoJS bug is beyond fixable, as I don't have big insight in the cause of the problem with CryptoJS (maybe it's just the order in which CryptoJS modules are loaded?).

So either disabling navigation.instant or setting webcrypto: true should get it working. I'll release the new version soon™.

unverbuggt avatar Jan 28 '24 13:01 unverbuggt

Even after upgrading to the latest crypto-js, it behaves buggy sometimes (if used with instant navigation of material).

But I've discovered that there is a project called crypto-es which translates crypto-js to an es6 module. If you don't want to use webcrypto, then this is an alternative that works together with instant navigation without any problems (as far as I've tested).

Just activate with esm: true. This also changes the way webcrypto is being loaded and hopefully will work better with instant navigation.

unverbuggt avatar Jan 29 '24 20:01 unverbuggt

Hello. I am using material theme of mkdocs. I use global password. After entering the password, when navigating through the page, the password field appears for milliseconds and immediately disappears and loads the section. I read this thread and in the case of loading the page in localhost helped me esm: true, but when running the page on cloudflare hosting the problem reappears, even with esm: true. So far what is the solution that can help?

pdorokhov avatar Apr 13 '25 15:04 pdorokhov

have you tried setting esm: true and webcrypto: true like mentioned here? Is the navigation.instant feature active?

But these measures will only better the time in which the password field might still be visible. When the page is first loaded it will always show the password field, then it will check if decryption keys are available in storage and then it will decrypt. Depending on the machine and browser the password field might be visible.

One Idea to circumvent this is to change the html template to default all html elements to non-visble and only show them if no decryption key is available of if decryption fails... I'll add this to the todo list.

unverbuggt avatar Apr 13 '25 15:04 unverbuggt

have you tried setting esm: true and webcrypto: true like mentioned here?

Yes. Tried different variations. No changes.

Is the navigation.instant feature active?

I tried this particular option first and it didn't work even for localhost as opposed to esm = true. It also doesn't work when loading the page to the network either.

Here are the contents of the mkdocs.yml file:

 name: material
 logo: assets/logo_niisi.png
  features:
  #  - navigation.instant
      - navigation.tabs
      - content.tabs.link
  - search
  - encryptcontent:
      title_prefix: ''
      summary: ''
      global_password: '*****'
      remember_keys: true
      remember_password: true
      webcrypto: true
      esm: true

I'll add this to the todo list.

Thank you. I'll be waiting for the corrections.

pdorokhov avatar Apr 14 '25 05:04 pdorokhov

should be fixed by this commit.

The decryption mask is only displayed at the end of init_decryptior. If decryption was successful, then mask isn't shown at all.

unverbuggt avatar Jul 07 '25 19:07 unverbuggt