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

loading history from server with authentication #3031

Open
jbockle opened this issue Nov 22, 2024 · 4 comments
Open

loading history from server with authentication #3031

jbockle opened this issue Nov 22, 2024 · 4 comments

Comments

@jbockle
Copy link

jbockle commented Nov 22, 2024

using events htmx:confirm and htmx:configRequest, I'm adding an authorization header to the request and is working well.

However, when used with hx-push-url and hx-history="false", I noticed the XMLHttpRequest history restoration does not utilize the confirm/configRequest behavior, resulting in missing authorization header.

htmx/src/htmx.js

Lines 3176 to 3204 in 7415f39

function loadHistoryFromServer(path) {
const request = new XMLHttpRequest()
const details = { path, xhr: request }
triggerEvent(getDocument().body, 'htmx:historyCacheMiss', details)
request.open('GET', path, true)
request.setRequestHeader('HX-Request', 'true')
request.setRequestHeader('HX-History-Restore-Request', 'true')
request.setRequestHeader('HX-Current-URL', getDocument().location.href)
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
triggerEvent(getDocument().body, 'htmx:historyCacheMissLoad', details)
const fragment = makeFragment(this.response)
/** @type ParentNode */
const content = fragment.querySelector('[hx-history-elt],[data-hx-history-elt]') || fragment
const historyElement = getHistoryElement()
const settleInfo = makeSettleInfo(historyElement)
handleTitle(fragment.title)
handlePreservedElements(fragment)
swapInnerHTML(historyElement, content, settleInfo)
restorePreservedElements()
settleImmediately(settleInfo.tasks)
currentPathForHistory = path
triggerEvent(getDocument().body, 'htmx:historyRestore', { path, cacheMiss: true, serverResponse: this.response })
} else {
triggerErrorEvent(getDocument().body, 'htmx:historyCacheMissLoadError', details)
}
}
request.send()

Is there another way to provide this authorization header in this scenario? If not, would you be open to a contribution to handle this?

@Telroshan
Copy link
Collaborator

Hey, would binding a listener to the existing htmx:historyCacheMiss event solve your usecase here?
As it provides a reference to the XMLHTTPRequest in its details (see xhr property in the snippet you linked), I would expect you to be able to add the headers from there. Could totally be wrong though, I never used this one.
Hope this helps!

@jbockle
Copy link
Author

jbockle commented Nov 24, 2024

thanks for the suggestion - would that result in a race condition as the event listener may be called after the request is sent?

@Telroshan
Copy link
Collaborator

@jbockle events fired by htmx run synchronously, so your listener callback will complete before htmx proceeds with its next line.
(Unless you explicitly declare an async listener of course, that htmx unfortunately doesn't support for now anyway)

@MichaelWest22
Copy link
Contributor

Hopefully That callback works well. Just a note that ideally when using htmx you should prefer to use cookies for authentication instead of an authorization header. Normally in htmx the requests are not cross origin and here cookies are the ideal authentication method and have many advantages in ease of use and security compared to authorization headers. Authorization headers are normally used for accessing data api's from remote origins where cookies are not as easy to setup and use.

With htmx cookie based auth just works with no additional htmx changes required. Good security guide to understand how to use cookies well with htmx is https://htmx.org/essays/web-security-basics-with-htmx/

The loadHistoryFromServer() function you mention hitting is really almost equivalent to a full page reload when the history is missed even though it is handled by htmx in some situations. One issue is that all full page reloads of any url will not include the auth header so the user will be forced back to your login screen most likely. So while you can update the url with hx-push-url and maybe get it to handle sending auth header on some back actions using htmx:historyCacheMiss event listener you will not be able to handle the user doing a manual refresh without a lot of extra complexity. This is where moving to auth cookies can make things simpler.

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