unverbuggt / mkdocs-encryptcontent-plugin

A MkDocs plugin that encrypt/decrypt markdown content with AES
https://unverbuggt.github.io/mkdocs-encryptcontent-plugin/
MIT License
123 stars 15 forks source link

Users re-prompted for password when navigating between pages #61

Closed ElliotSknr closed 6 months ago

ElliotSknr commented 7 months ago

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 commented 7 months ago

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

unverbuggt commented 7 months ago

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 commented 7 months ago

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.

ElliotSknr commented 7 months ago

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 commented 7 months ago

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?

unverbuggt commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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.