[GH-ISSUE #893] Android app: Downloading attached file fails when using basic auth #632

Closed
opened 2026-05-07 00:26:04 +02:00 by BreizhHardware · 3 comments

Originally created by @EisFrei on GitHub (Sep 22, 2023).
Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/893

🐞 Describe the bug

When using basic auth to protect the self hosted server text messaging works as expected after entering the credentials.

Those credentials appear to not being used when trying to download an attached file.

How to reproduce

  • Setup server using basic auth
  • ntfy publish --file images/image.jpg test "image test"
  • ntfy Android app shows the notification text "image test".
  • When trying to download the attached image the error message "Herunterladen fehlgeschlagen" / "Download failed" appears.
  • The Apache log show a 401 status code, suggesting that the credentials were not used correctly in the request.

💻 Components impacted
Android app

💡 Screenshots and/or logs
Device info:

ntfy: 1.16.0 (play)
OS: 4.19.157-perf-gdfc2307a5578
Android: 13 (SDK 33)
Model: alioth
Product: alioth_eea

--
Settings:
{
"autoDeleteSeconds": 2592000,
"autoDownloadMaxSize": 1048576,
"broadcastEnabled": true,
"connectionProtocol": "ws",
"darkMode": -1,
"defaultBaseUrl": "https://ntfy.xxxxx",
"lastSharedTopics": [],
"minPriority": 1,
"mutedUntil": 0,
"recordLogs": true
}

Logs

--

1695371296140 2023-09-22 10:28:16.140 D NtfyDownloadManager Enqueuing work to download attachment for notification u6ramlLx3myR, work: io.heckel.ntfy.DOWNLOAD_FILE_u6ramlLx3myR
1695371296178 2023-09-22 10:28:16.178 D NtfyAttachDownload Downloading attachment from https://ntfy.xxxxxx/file/u6ramlLx3myR.jpg
1695371296357 2023-09-22 10:28:16.357 D NtfyAttachDownload Download: headers received: Response{protocol=h2, code=401, message=, url=https://ntfy.xxxxxxxx/file/u6ramlLx3myR.jpg}
1695371296357 2023-09-22 10:28:16.357 W NtfyAttachDownload Attachment download failed
Exception:
java.lang.Exception: Unexpected response: 401
at io.heckel.ntfy.msg.DownloadAttachmentWorker.downloadAttachment(DownloadAttachmentWorker.kt:71)
at io.heckel.ntfy.msg.DownloadAttachmentWorker.doWork(DownloadAttachmentWorker.kt:48)
at androidx.work.Worker$1.run(Worker.java:86)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
at java.lang.Thread.run(Thread.java:1012)

🔮 Additional context
An Apache2 reverse proxy using basic auth is running in front of the ntfy server

Originally created by @EisFrei on GitHub (Sep 22, 2023). Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/893 :lady_beetle: **Describe the bug** When using basic auth to protect the self hosted server text messaging works as expected after entering the credentials. Those credentials appear to not being used when trying to download an attached file. How to reproduce - Setup server using basic auth - ntfy publish --file images/image.jpg test "image test" - ntfy Android app shows the notification text "image test". - When trying to download the attached image the error message "Herunterladen fehlgeschlagen" / "Download failed" appears. - The Apache log show a 401 status code, suggesting that the credentials were not used correctly in the request. :computer: **Components impacted** Android app :bulb: **Screenshots and/or logs** Device info: -- ntfy: 1.16.0 (play) OS: 4.19.157-perf-gdfc2307a5578 Android: 13 (SDK 33) Model: alioth Product: alioth_eea -- Settings: { "autoDeleteSeconds": 2592000, "autoDownloadMaxSize": 1048576, "broadcastEnabled": true, "connectionProtocol": "ws", "darkMode": -1, "defaultBaseUrl": "https://ntfy.xxxxx", "lastSharedTopics": [], "minPriority": 1, "mutedUntil": 0, "recordLogs": true } Logs -- 1695371296140 2023-09-22 10:28:16.140 D NtfyDownloadManager Enqueuing work to download attachment for notification u6ramlLx3myR, work: io.heckel.ntfy.DOWNLOAD_FILE_u6ramlLx3myR 1695371296178 2023-09-22 10:28:16.178 D NtfyAttachDownload Downloading attachment from https://ntfy.xxxxxx/file/u6ramlLx3myR.jpg 1695371296357 2023-09-22 10:28:16.357 D NtfyAttachDownload Download: headers received: Response{protocol=h2, code=401, message=, url=https://ntfy.xxxxxxxx/file/u6ramlLx3myR.jpg} 1695371296357 2023-09-22 10:28:16.357 W NtfyAttachDownload Attachment download failed Exception: java.lang.Exception: Unexpected response: 401 at io.heckel.ntfy.msg.DownloadAttachmentWorker.downloadAttachment(DownloadAttachmentWorker.kt:71) at io.heckel.ntfy.msg.DownloadAttachmentWorker.doWork(DownloadAttachmentWorker.kt:48) at androidx.work.Worker$1.run(Worker.java:86) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637) at java.lang.Thread.run(Thread.java:1012) :crystal_ball: **Additional context** An Apache2 reverse proxy using basic auth is running in front of the ntfy server
BreizhHardware 2026-05-07 00:26:04 +02:00
  • closed this issue
  • added the
    🪲 bug
    label
Author
Owner

@binwiederhier commented on GitHub (Sep 22, 2023):

The /file/ endpoint does not require a password. The message ID is randomly generated serves as a secret URL to download the file. This makes linking to the uploaded file easier and is equally secure.

You seem to be running ntfy behind a proxy that adds auth headers. This is not officially supported yet.

<!-- gh-comment-id:1731314679 --> @binwiederhier commented on GitHub (Sep 22, 2023): The /file/ endpoint does not require a password. The message ID is randomly generated serves as a secret URL to download the file. This makes linking to the uploaded file easier and is equally secure. You seem to be running ntfy behind a proxy that adds auth headers. This is not officially supported yet.
Author
Owner

@dcousens commented on GitHub (Feb 6, 2024):

@binwiederhier are you open to re-opening this as a feature request?
Maybe as attachment.headers?

<!-- gh-comment-id:1929653657 --> @dcousens commented on GitHub (Feb 6, 2024): @binwiederhier are you open to re-opening this as a feature request? Maybe as `attachment.headers`?
Author
Owner

@Torxgewinde commented on GitHub (Feb 12, 2024):

To make use of the hint @binwiederhier gave, i'd like to add a config for HAProxy that works for my personal setup quite acceptable:

/etc/haproxy/haproxy.conf:

########################################################################
#
# Configuration file for HAProxy in front of NTFY
#
# Docu: 
#  https://www.haproxy.com/documentation/hapee/latest/onepage/
#  https://www.haproxy.com/blog/websockets-load-balancing-with-haproxy
#  https://delta.blue/blog/haproxy-timeouts/
#  https://www.haproxy.com/documentation/haproxy-configuration-tutorials/authentication/basic-authentication/
#  https://www.haproxy.com/documentation/haproxy-configuration-tutorials/client-ip-preservation/add-x-forward-for-header/
#
# Testing the config:
#  haproxy -f /etc/haproxy/haproxy.cfg -d
# Restarting the service:
#  service haproxy restart
########################################################################

global
	maxconn 100
	user nobody
	group nogroup
	daemon
	nosplice

#default settings:
defaults
	mode http
	timeout connect 1s
	timeout client 60s
	timeout http-request 10s
	timeout http-keep-alive 10s
	timeout server 60s
	timeout server-fin 10s
	timeout tunnel 120s
	timeout client-fin 10s
	retries 2

# List of username and passwords we accept:
#  Plaintext Passwords: user myUsername insecure-password myPassword
#  Hash only with mkpasswd from packet "whois":
#   - Generate: mkpasswd -m sha-256 myPassword
#   - Add entry: user myUsername password myPasswordHashFromAbove
userlist mycredentials
	user Torxgewinde password $HASH_abcdefghijklmnopqrstuvwxyz_HASH$

# TCP frontend with TLS/SSL
frontend frontend_ntfy_proxy
	#
	# create combined_certs with this command:
	# cat server-cert.pem server-key.pem > combined_certs
	#
	bind [::]:443,:443 ssl crt /etc/haproxy/example.quicksrv.de.combined ssl-min-ver TLSv1.3

	# add header X-Forwarded-For:
	# This is needed or otherwise to NTFY all interactions count as a single interaction
	option forwardfor

	# try to push everything to https/wss encrypted connections:
	http-request redirect scheme https unless { ssl_fc }
	http-request redirect code 301 location https://%[hdr(host)]%[capture.req.uri] unless { ssl_fc }
	http-request deny unless { ssl_fc }

	# Everything must be authenticated except for /file/ endpoint
	# See: https://github.com/binwiederhier/ntfy/issues/893#issuecomment-1731314679
	http-request auth unless { http_auth(mycredentials) } or { path_beg /file/ }

	#is it a websocket?
	acl for_websocket hdr(Upgrade) -i websocket
	acl for_websocket hdr(Connection) -i upgrade
	use_backend backend_ntfy_ws if for_websocket

	#everything else is handled as HTTP request
	default_backend backend_ntfy_http

# Default backend to contact NTFY
backend backend_ntfy_http
	#add header to signal which backend handled the request
	http-response set-header X-Torxgewinde "backend_ntfy_http"

	#forward request to this server, this is where FHEMWEB listens
	server NTFY_SERVER_HTTP 127.0.0.1:8080

# NTFY websocket backend
backend backend_ntfy_ws
	#add header to signal which backend handled the request
	http-response set-header X-Torxgewinde "backend_ntfy_ws"

	#reject/deny if the following checks do not match
	acl hdr_connection_upgrade hdr(Connection) -i upgrade
	acl hdr_upgrade_websocket hdr(Upgrade) -i websocket
	acl hdr_websocket_key hdr_cnt(Sec-WebSocket-Key) eq 1
	acl hdr_websocket_version hdr_cnt(Sec-WebSocket-Version) eq 1
	http-request deny if !hdr_connection_upgrade !hdr_upgrade_websocket !hdr_websocket_key !hdr_websocket_version

	server NTFY_SERVER_WS 127.0.0.1:8080
<!-- gh-comment-id:1939277153 --> @Torxgewinde commented on GitHub (Feb 12, 2024): To make use of the hint @binwiederhier gave, i'd like to add a config for HAProxy that works for my personal setup quite acceptable: `/etc/haproxy/haproxy.conf`: ``` ######################################################################## # # Configuration file for HAProxy in front of NTFY # # Docu: # https://www.haproxy.com/documentation/hapee/latest/onepage/ # https://www.haproxy.com/blog/websockets-load-balancing-with-haproxy # https://delta.blue/blog/haproxy-timeouts/ # https://www.haproxy.com/documentation/haproxy-configuration-tutorials/authentication/basic-authentication/ # https://www.haproxy.com/documentation/haproxy-configuration-tutorials/client-ip-preservation/add-x-forward-for-header/ # # Testing the config: # haproxy -f /etc/haproxy/haproxy.cfg -d # Restarting the service: # service haproxy restart ######################################################################## global maxconn 100 user nobody group nogroup daemon nosplice #default settings: defaults mode http timeout connect 1s timeout client 60s timeout http-request 10s timeout http-keep-alive 10s timeout server 60s timeout server-fin 10s timeout tunnel 120s timeout client-fin 10s retries 2 # List of username and passwords we accept: # Plaintext Passwords: user myUsername insecure-password myPassword # Hash only with mkpasswd from packet "whois": # - Generate: mkpasswd -m sha-256 myPassword # - Add entry: user myUsername password myPasswordHashFromAbove userlist mycredentials user Torxgewinde password $HASH_abcdefghijklmnopqrstuvwxyz_HASH$ # TCP frontend with TLS/SSL frontend frontend_ntfy_proxy # # create combined_certs with this command: # cat server-cert.pem server-key.pem > combined_certs # bind [::]:443,:443 ssl crt /etc/haproxy/example.quicksrv.de.combined ssl-min-ver TLSv1.3 # add header X-Forwarded-For: # This is needed or otherwise to NTFY all interactions count as a single interaction option forwardfor # try to push everything to https/wss encrypted connections: http-request redirect scheme https unless { ssl_fc } http-request redirect code 301 location https://%[hdr(host)]%[capture.req.uri] unless { ssl_fc } http-request deny unless { ssl_fc } # Everything must be authenticated except for /file/ endpoint # See: https://github.com/binwiederhier/ntfy/issues/893#issuecomment-1731314679 http-request auth unless { http_auth(mycredentials) } or { path_beg /file/ } #is it a websocket? acl for_websocket hdr(Upgrade) -i websocket acl for_websocket hdr(Connection) -i upgrade use_backend backend_ntfy_ws if for_websocket #everything else is handled as HTTP request default_backend backend_ntfy_http # Default backend to contact NTFY backend backend_ntfy_http #add header to signal which backend handled the request http-response set-header X-Torxgewinde "backend_ntfy_http" #forward request to this server, this is where FHEMWEB listens server NTFY_SERVER_HTTP 127.0.0.1:8080 # NTFY websocket backend backend backend_ntfy_ws #add header to signal which backend handled the request http-response set-header X-Torxgewinde "backend_ntfy_ws" #reject/deny if the following checks do not match acl hdr_connection_upgrade hdr(Connection) -i upgrade acl hdr_upgrade_websocket hdr(Upgrade) -i websocket acl hdr_websocket_key hdr_cnt(Sec-WebSocket-Key) eq 1 acl hdr_websocket_version hdr_cnt(Sec-WebSocket-Version) eq 1 http-request deny if !hdr_connection_upgrade !hdr_upgrade_websocket !hdr_websocket_key !hdr_websocket_version server NTFY_SERVER_WS 127.0.0.1:8080 ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ntfy#632
No description provided.