Feed of "Readeck" https://codeberg.org/readeck Mon, 13 Apr 2026 08:44:00 +0200 hickey commented on pull request readeck/readeck#1182 https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13043013 WIP: Add OIDC authentication to Readeck <p dir="auto">Sorry, maybe standard was the wrong word to use. I was not using standard in a sense that go-oidc is part of the core Go lang modules or an x module. I was referring to that go-oidc would be the go-to module for implementing an OIDC client. I know that there are a few others like Goth which was interesting as it &#34;supported&#34; a lot of OIDC endpoints. Probably just has pre-configured settings for most of the endpoints, but I was not sure it would actually add any real value.</p> <p dir="auto">I do agree that OIDC is not a terribly complicated standard, but with any standard there are always little gotchas that are not apparent. I too am not a security expert and don&#39;t want to put something out there that people think is a secure piece of code and have it compromised because of something I never thought would be a problem.</p> Sorry, maybe standard was the wrong word to use. I was not using standard in a sense that go-oidc is part of the core Go lang modules or an x module. I was referring to that go-oidc would be the go-to module for implementing an OIDC client. I know that there are a few others like Goth which was interesting as it "supported" a lot of OIDC endpoints. Probably just has pre-configured settings for most of the endpoints, but I was not sure it would actually add any real value.

I do agree that OIDC is not a terribly complicated standard, but with any standard there are always little gotchas that are not apparent. I too am not a security expert and don't want to put something out there that people think is a secure piece of code and have it compromised because of something I never thought would be a problem.

]]>
hickey 122267832: https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13043013 Sun, 12 Apr 2026 21:57:51 +0200
hickey commented on pull request readeck/readeck#1182 https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13034067 WIP: Add OIDC authentication to Readeck <p dir="auto">If I understand what you are saying here (that you want to eliminate the go-oidc module and reimplement the module in native Go code) then I have to say that is a non-start for me. I am not looking to build another go-oidc module that probably will have errors in it and miss edge cases. The go-oidc module takes into account the differences between v1 and v2 of the OIDC specification. I am sure that there are other things done in the module that may accommodate specific OIDC servers or servers that are not (pre-v1) fully v1 compliant (but hopefully they are not in use any more).</p> <p dir="auto">Writing security code is not really a trivial matter as you probably already know and making a requirement that the standard OIDC module can not be used in favor of reimplementing it is just lunacy to me. But if that is your intent, then we can go ahead and close this PR and I will keep the branch for myself and merge it will future versions of Readeck for my use.</p> If I understand what you are saying here (that you want to eliminate the go-oidc module and reimplement the module in native Go code) then I have to say that is a non-start for me. I am not looking to build another go-oidc module that probably will have errors in it and miss edge cases. The go-oidc module takes into account the differences between v1 and v2 of the OIDC specification. I am sure that there are other things done in the module that may accommodate specific OIDC servers or servers that are not (pre-v1) fully v1 compliant (but hopefully they are not in use any more).

Writing security code is not really a trivial matter as you probably already know and making a requirement that the standard OIDC module can not be used in favor of reimplementing it is just lunacy to me. But if that is your intent, then we can go ahead and close this PR and I will keep the branch for myself and merge it will future versions of Readeck for my use.

]]>
hickey 122179998: https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13034067 Sun, 12 Apr 2026 18:20:29 +0200
hickey commented on pull request readeck/readeck#1182 https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13033734 WIP: Add OIDC authentication to Readeck <p dir="auto">See below for why the state needs to be stored in the session to validate the origin of the authentication request and the access token will probably be used to renew the token when it expires. It may also be necessary to store the expiration time of the access token, but I have not determined that yet.</p> See below for why the state needs to be stored in the session to validate the origin of the authentication request and the access token will probably be used to renew the token when it expires. It may also be necessary to store the expiration time of the access token, but I have not determined that yet.

]]>
hickey 122173575: https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13033734 Sun, 12 Apr 2026 18:06:05 +0200
hickey commented on pull request readeck/readeck#1182 https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13033626 WIP: Add OIDC authentication to Readeck <p dir="auto">I am not sure I understand why you say that this is a non-starter. The HTTP request is not calling to the Readeck instance itself but to the OIDC authentication server to retrieve the configuration for the OIDC application settings.</p> <p dir="auto">This will probably be pulled out anyways as it appears that when the <code>NewProvisioner()</code> function in the go-oidc module retrieves the JSON document stored on the authentication server to configure the client.</p> I am not sure I understand why you say that this is a non-starter. The HTTP request is not calling to the Readeck instance itself but to the OIDC authentication server to retrieve the configuration for the OIDC application settings.

This will probably be pulled out anyways as it appears that when the NewProvisioner() function in the go-oidc module retrieves the JSON document stored on the authentication server to configure the client.

]]>
hickey 122172717: https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13033626 Sun, 12 Apr 2026 18:03:16 +0200
hickey commented on pull request readeck/readeck#1182 https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13033491 WIP: Add OIDC authentication to Readeck <p dir="auto">One of my first comments described the flow from the user&#39;s standpoint which is pretty simple as far as the user interface. For the backend flow it is a bit more in depth and I will to my best to describe it as I understand it.</p> <p dir="auto">Once the OIDC authentication flow is initiated by the user pressing the OIDC login button, a random string is generated and sent to the OIDC authentication server. This is usually referred to as the state in the OIDC flow and is really used to validate that the authentication request was initiated from the application is really just a CSRF token. The application upon receiving a login request, will perform an HTTP redirect (GET) to the authentication server with a <code>state</code>, <code>client_id</code>, <code>scope</code>, <code>response_type</code> and <code>request_uri</code> parameters.</p> <p dir="auto">The <code>client_id</code> is generated on the authentication server to identify which application is requesting authentication. This is a static token that is stored in the application&#39;s configuration. The <code>scope</code> tells the authentication server what claims are requested by the application in the authentication response. This is commonly set to &#39;openid profile email&#39;. openid is require and the profile requests items such as username and UID and of course email requests the user&#39;s email address. <code>response_type</code> is set to &#39;code&#39; to (I believe) request an access token in the response. Finally the <code>redirect_uri</code> is the URL that the authentication server needs to send the response.</p> <p dir="auto">The user will then authenticate to the OIDC authentication server if necessary and the authentication server will return to the application using the <code>redirect_uri</code> which will be called with the <code>state</code> and <code>code</code> parameters. Again the <code>state</code> is used to validate that the request originated from the application so the returned state value needs to be compared to the stored state value when the authentication request was initiated. The <code>code</code> (which depending upon the OIDC implementation could be a string or a JWT) is then exchanged for the access and ID tokens. This is done by calling the OIDC token endpoint with the <code>code</code> value. The response will be a JSON document that contains these tokens and a few other items such as expiration time for the tokens.</p> <p dir="auto">The ID token is used to authenticate the user and should be used to validate the user. The access token is used for authorization and provides information as to what the user has access to. In my case I am using Authentik and both the ID and access tokens are very similar, but that may be because I don&#39;t have a lot of settings in Authentik that would provide different authorizations.</p> <p dir="auto">The payload for the ID token asserts the following claims:</p> <pre class="code-block"><code class="chroma language-json display"><span class="p">{</span> <span class="nt">&#34;iss&#34;</span><span class="p">:</span> <span class="s2">&#34;https://auth.wt0f.com/application/o/readeck/&#34;</span><span class="p">,</span> <span class="nt">&#34;sub&#34;</span><span class="p">:</span> <span class="s2">&#34;hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;aud&#34;</span><span class="p">:</span> <span class="s2">&#34;H9uYxz2H6czUt08O0gZroxIAAUYj5hy0lgaM2IRg&#34;</span><span class="p">,</span> <span class="nt">&#34;exp&#34;</span><span class="p">:</span> <span class="mi">1775680621</span><span class="p">,</span> <span class="nt">&#34;iat&#34;</span><span class="p">:</span> <span class="mi">1775680321</span><span class="p">,</span> <span class="nt">&#34;auth_time&#34;</span><span class="p">:</span> <span class="mi">1775666408</span><span class="p">,</span> <span class="nt">&#34;acr&#34;</span><span class="p">:</span> <span class="s2">&#34;goauthentik.io/providers/oauth2/default&#34;</span><span class="p">,</span> <span class="nt">&#34;amr&#34;</span><span class="p">:</span> <span class="p">[</span> <span class="s2">&#34;pwd&#34;</span> <span class="p">],</span> <span class="nt">&#34;sid&#34;</span><span class="p">:</span> <span class="s2">&#34;d582cf9de4038d38e8dd095b1d892b83efa6fab7ced7b9e004f58b5d1ffbc6c3&#34;</span><span class="p">,</span> <span class="nt">&#34;jti&#34;</span><span class="p">:</span> <span class="s2">&#34;FFG2mtCp0Py1wVdKT8SUIt294yqZ9jAzePXEYkOK&#34;</span><span class="p">,</span> <span class="nt">&#34;email&#34;</span><span class="p">:</span> <span class="s2">&#34;hickey@kinetic-compute.com&#34;</span><span class="p">,</span> <span class="nt">&#34;email_verified&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;Gerard Hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;given_name&#34;</span><span class="p">:</span> <span class="s2">&#34;Gerard Hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;preferred_username&#34;</span><span class="p">:</span> <span class="s2">&#34;hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;nickname&#34;</span><span class="p">:</span> <span class="s2">&#34;hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;groups&#34;</span><span class="p">:</span> <span class="p">[</span> <span class="s2">&#34;authentik Admins&#34;</span><span class="p">,</span> <span class="s2">&#34;NextCloud Admins&#34;</span><span class="p">,</span> <span class="s2">&#34;Grafana Admins&#34;</span><span class="p">,</span> <span class="s2">&#34;Proxmox-Admins&#34;</span><span class="p">,</span> <span class="s2">&#34;Authentik Admin Tools&#34;</span><span class="p">,</span> <span class="s2">&#34;Authentik Backend Services&#34;</span> <span class="p">]</span> <span class="p">}</span> </code></pre><p dir="auto">The claims in the access token is as follows:</p> <pre class="code-block"><code class="chroma language-json display"><span class="p">{</span> <span class="nt">&#34;iss&#34;</span><span class="p">:</span> <span class="s2">&#34;https://auth.wt0f.com/application/o/readeck/&#34;</span><span class="p">,</span> <span class="nt">&#34;sub&#34;</span><span class="p">:</span> <span class="s2">&#34;hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;aud&#34;</span><span class="p">:</span> <span class="s2">&#34;H9uYxz2H6czUt08O0gZroxIAAUYj5hy0lgaM2IRg&#34;</span><span class="p">,</span> <span class="nt">&#34;exp&#34;</span><span class="p">:</span> <span class="mi">1775667590</span><span class="p">,</span> <span class="nt">&#34;iat&#34;</span><span class="p">:</span> <span class="mi">1775667290</span><span class="p">,</span> <span class="nt">&#34;auth_time&#34;</span><span class="p">:</span> <span class="mi">1775666408</span><span class="p">,</span> <span class="nt">&#34;acr&#34;</span><span class="p">:</span> <span class="s2">&#34;goauthentik.io/providers/oauth2/default&#34;</span><span class="p">,</span> <span class="nt">&#34;amr&#34;</span><span class="p">:</span> <span class="p">[</span> <span class="s2">&#34;pwd&#34;</span> <span class="p">],</span> <span class="nt">&#34;sid&#34;</span><span class="p">:</span> <span class="s2">&#34;d582cf9de4038d38e8dd095b1d892b83efa6fab7ced7b9e004f58b5d1ffbc6c3&#34;</span><span class="p">,</span> <span class="nt">&#34;jti&#34;</span><span class="p">:</span> <span class="s2">&#34;mGOpPVJBVBXyz5DTQvyEct54NOcHXX1OFyw398YR&#34;</span><span class="p">,</span> <span class="nt">&#34;email&#34;</span><span class="p">:</span> <span class="s2">&#34;hickey@kinetic-compute.com&#34;</span><span class="p">,</span> <span class="nt">&#34;email_verified&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;Gerard Hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;given_name&#34;</span><span class="p">:</span> <span class="s2">&#34;Gerard Hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;preferred_username&#34;</span><span class="p">:</span> <span class="s2">&#34;hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;nickname&#34;</span><span class="p">:</span> <span class="s2">&#34;hickey&#34;</span><span class="p">,</span> <span class="nt">&#34;groups&#34;</span><span class="p">:</span> <span class="p">[</span> <span class="s2">&#34;authentik Admins&#34;</span><span class="p">,</span> <span class="s2">&#34;NextCloud Admins&#34;</span><span class="p">,</span> <span class="s2">&#34;Grafana Admins&#34;</span><span class="p">,</span> <span class="s2">&#34;Proxmox-Admins&#34;</span><span class="p">,</span> <span class="s2">&#34;Authentik Admin Tools&#34;</span><span class="p">,</span> <span class="s2">&#34;Authentik Backend Services&#34;</span> <span class="p">],</span> <span class="nt">&#34;azp&#34;</span><span class="p">:</span> <span class="s2">&#34;H9uYxz2H6czUt08O0gZroxIAAUYj5hy0lgaM2IRg&#34;</span><span class="p">,</span> <span class="nt">&#34;uid&#34;</span><span class="p">:</span> <span class="s2">&#34;bADM3vh0ws6dp2s5f8fb46fh8i2tawMGToExAL3T&#34;</span><span class="p">,</span> <span class="nt">&#34;scope&#34;</span><span class="p">:</span> <span class="s2">&#34;profile email openid&#34;</span> <span class="p">}</span> </code></pre><p dir="auto">As one can see, both of these tokens are very similar but they are representing different needs for the application. Both JWTs are signed by the private key of the authorization server and gets verified by retrieving the public key from the authorization server.</p> <p dir="auto">At this point the application can continue with the authenticated user as if the user had logged in with another method. At some point in the future the access token will expire and a new access token will need to be retrieved from the authorization server. This aspect I don&#39;t have as much visibility into yet. There are references to a <code>refresh_token</code> that is included in the response that provides the access and ID tokens, but I am not receiving this from my Authentik server. It could be that Authentik does not provide a <code>refresh_token</code> or it is a matter of the configuration I have in the Authentik for the application. I am not sure which. Once I have the user being created/loaded I will be able to experiment and learn what needs to be done to generate new access tokens.</p> One of my first comments described the flow from the user's standpoint which is pretty simple as far as the user interface. For the backend flow it is a bit more in depth and I will to my best to describe it as I understand it.

Once the OIDC authentication flow is initiated by the user pressing the OIDC login button, a random string is generated and sent to the OIDC authentication server. This is usually referred to as the state in the OIDC flow and is really used to validate that the authentication request was initiated from the application is really just a CSRF token. The application upon receiving a login request, will perform an HTTP redirect (GET) to the authentication server with a state, client_id, scope, response_type and request_uri parameters.

The client_id is generated on the authentication server to identify which application is requesting authentication. This is a static token that is stored in the application's configuration. The scope tells the authentication server what claims are requested by the application in the authentication response. This is commonly set to 'openid profile email'. openid is require and the profile requests items such as username and UID and of course email requests the user's email address. response_type is set to 'code' to (I believe) request an access token in the response. Finally the redirect_uri is the URL that the authentication server needs to send the response.

The user will then authenticate to the OIDC authentication server if necessary and the authentication server will return to the application using the redirect_uri which will be called with the state and code parameters. Again the state is used to validate that the request originated from the application so the returned state value needs to be compared to the stored state value when the authentication request was initiated. The code (which depending upon the OIDC implementation could be a string or a JWT) is then exchanged for the access and ID tokens. This is done by calling the OIDC token endpoint with the code value. The response will be a JSON document that contains these tokens and a few other items such as expiration time for the tokens.

The ID token is used to authenticate the user and should be used to validate the user. The access token is used for authorization and provides information as to what the user has access to. In my case I am using Authentik and both the ID and access tokens are very similar, but that may be because I don't have a lot of settings in Authentik that would provide different authorizations.

The payload for the ID token asserts the following claims:

{
  "iss": "https://auth.wt0f.com/application/o/readeck/",
  "sub": "hickey",
  "aud": "H9uYxz2H6czUt08O0gZroxIAAUYj5hy0lgaM2IRg",
  "exp": 1775680621,
  "iat": 1775680321,
  "auth_time": 1775666408,
  "acr": "goauthentik.io/providers/oauth2/default",
  "amr": [
    "pwd"
  ],
  "sid": "d582cf9de4038d38e8dd095b1d892b83efa6fab7ced7b9e004f58b5d1ffbc6c3",
  "jti": "FFG2mtCp0Py1wVdKT8SUIt294yqZ9jAzePXEYkOK",
  "email": "hickey@kinetic-compute.com",
  "email_verified": false,
  "name": "Gerard Hickey",
  "given_name": "Gerard Hickey",
  "preferred_username": "hickey",
  "nickname": "hickey",
  "groups": [
    "authentik Admins",
    "NextCloud Admins",
    "Grafana Admins",
    "Proxmox-Admins",
    "Authentik Admin Tools",
    "Authentik Backend Services"
  ]
}

The claims in the access token is as follows:

{
  "iss": "https://auth.wt0f.com/application/o/readeck/",
  "sub": "hickey",
  "aud": "H9uYxz2H6czUt08O0gZroxIAAUYj5hy0lgaM2IRg",
  "exp": 1775667590,
  "iat": 1775667290,
  "auth_time": 1775666408,
  "acr": "goauthentik.io/providers/oauth2/default",
  "amr": [
    "pwd"
  ],
  "sid": "d582cf9de4038d38e8dd095b1d892b83efa6fab7ced7b9e004f58b5d1ffbc6c3",
  "jti": "mGOpPVJBVBXyz5DTQvyEct54NOcHXX1OFyw398YR",
  "email": "hickey@kinetic-compute.com",
  "email_verified": false,
  "name": "Gerard Hickey",
  "given_name": "Gerard Hickey",
  "preferred_username": "hickey",
  "nickname": "hickey",
  "groups": [
    "authentik Admins",
    "NextCloud Admins",
    "Grafana Admins",
    "Proxmox-Admins",
    "Authentik Admin Tools",
    "Authentik Backend Services"
  ],
  "azp": "H9uYxz2H6czUt08O0gZroxIAAUYj5hy0lgaM2IRg",
  "uid": "bADM3vh0ws6dp2s5f8fb46fh8i2tawMGToExAL3T",
  "scope": "profile email openid"
}

As one can see, both of these tokens are very similar but they are representing different needs for the application. Both JWTs are signed by the private key of the authorization server and gets verified by retrieving the public key from the authorization server.

At this point the application can continue with the authenticated user as if the user had logged in with another method. At some point in the future the access token will expire and a new access token will need to be retrieved from the authorization server. This aspect I don't have as much visibility into yet. There are references to a refresh_token that is included in the response that provides the access and ID tokens, but I am not receiving this from my Authentik server. It could be that Authentik does not provide a refresh_token or it is a matter of the configuration I have in the Authentik for the application. I am not sure which. Once I have the user being created/loaded I will be able to experiment and learn what needs to be done to generate new access tokens.

]]>
hickey 122170536: https://codeberg.org/readeck/readeck/pulls/1182#issuecomment-13033491 Sun, 12 Apr 2026 17:56:56 +0200
ghost_of_cerberus commented on pull request readeck/readeck#1163 https://codeberg.org/readeck/readeck/pulls/1163#issuecomment-13023957 Extend username charset to allow '.' <p dir="auto">No worries, <a href="/olivier" class="mention" rel="nofollow">@olivier</a>. The intended solution appears to be much more robust. Looking forward to testing it out. :)</p> No worries, @olivier. The intended solution appears to be much more robust. Looking forward to testing it out. :)

]]>
ghost_of_cerberus 122093124: https://codeberg.org/readeck/readeck/pulls/1163#issuecomment-13023957 Sun, 12 Apr 2026 13:59:18 +0200
Minoru commented on issue readeck/browser-extension#127 https://codeberg.org/readeck/browser-extension/issues/127#issuecomment-13022079 Fails with "Could not establish connection. Receiving end does not exist" <p dir="auto">Thanks for the detailed instructions! Apparently 30 seconds come from Firefox:</p> Thanks for the detailed instructions! Apparently 30 seconds come from Firefox:

]]>
Minoru 122072316: https://codeberg.org/readeck/browser-extension/issues/127#issuecomment-13022079 Sun, 12 Apr 2026 12:32:52 +0200
mislav commented on issue readeck/browser-extension#127 https://codeberg.org/readeck/browser-extension/issues/127#issuecomment-12995484 Fails with "Could not establish connection. Receiving end does not exist" <p dir="auto"><a href="/Minoru" class="mention" rel="nofollow">@Minoru</a> I can not find any specific client-side timeout for the browser extension POSTing the page payload to the Readeck API:</p> <p dir="auto"></p><div class="file-preview-box"><div class="header"><div><a href="https://codeberg.org/readeck/browser-extension/src/commit/c762ba668e58c3e127b57ba7d34ca6fdb269edfc/src/lib/readeck-api.js#L197-L218" class="muted" rel="nofollow">src/lib/readeck-api.js</a></div><span class="text grey">Lines 197 to 218 in <a href="https://codeberg.org/readeck/browser-extension/src/commit/c762ba668e58c3e127b57ba7d34ca6fdb269edfc" class="text black" rel="nofollow">c762ba6</a></span></div><div class="ui table"><table class="file-preview"><tbody><tr><td class="lines-num"><span data-line-number="197"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="cm">/** </span></code></td></tr><tr><td class="lines-num"><span data-line-number="198"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="cm"> * savePage sends the page to Readeck. </span></code></td></tr><tr><td class="lines-num"><span data-line-number="199"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="cm"> * </span></code></td></tr><tr><td class="lines-num"><span data-line-number="200"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="cm"> * @async </span></code></td></tr><tr><td class="lines-num"><span data-line-number="201"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="cm"> * @param {import(&#34;../content-script/content-script&#34;).PageObj} page Page object </span></code></td></tr><tr><td class="lines-num"><span data-line-number="202"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="cm"> * @returns {Promise&lt;import(&#34;../background&#34;).ApiResult&gt;} A promise of the API call result </span></code></td></tr><tr><td class="lines-num"><span data-line-number="203"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="cm"> */</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="204"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="kr">export</span> <span class="kr">async</span> <span class="kd">function</span> <span class="nx">savePage</span><span class="p">(</span><span class="nx">page</span><span class="p">)</span> <span class="p">{</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="205"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="k">return</span> <span class="kr">await</span> <span class="nx">browser</span><span class="p">.</span><span class="nx">runtime</span><span class="p">.</span><span class="nx">sendMessage</span><span class="p">(</span><span class="p">{</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="206"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">type</span><span class="o">:</span> <span class="s2">&#34;save-page&#34;</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="207"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">serverURL</span><span class="o">:</span> <span class="nx">get</span><span class="p">(</span><span class="nx">serverURL</span><span class="p">)</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="208"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">path</span><span class="o">:</span> <span class="s2">&#34;api/bookmarks&#34;</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="209"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">params</span><span class="o">:</span> <span class="p">{</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="210"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">method</span><span class="o">:</span> <span class="s2">&#34;post&#34;</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="211"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">headers</span><span class="o">:</span> <span class="p">{</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="212"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">Accept</span><span class="o">:</span> <span class="s2">&#34;application/json&#34;</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="213"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">Authorization</span><span class="o">:</span> <span class="sb">`</span><span class="sb">Bearer </span><span class="si">${</span><span class="nx">get</span><span class="p">(</span><span class="nx">token</span><span class="p">)</span><span class="si">}</span><span class="sb">`</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="214"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="p">}</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="215"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="p">}</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="216"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="nx">page</span><span class="p">,</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="217"></span></td><td class="lines-code chroma"><code class="code-inner"> <span class="p">}</span><span class="p">)</span> </code></td></tr><tr><td class="lines-num"><span data-line-number="218"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="p">}</span> </code></td></tr></tbody></table></div></div><p dir="auto"></p> <p dir="auto"></p><div class="file-preview-box"><div class="header"><div><a href="https://codeberg.org/readeck/browser-extension/src/commit/c762ba668e58c3e127b57ba7d34ca6fdb269edfc/src/background.js#L32" class="muted" rel="nofollow">src/background.js</a></div><span class="text grey">Line 32 in <a href="https://codeberg.org/readeck/browser-extension/src/commit/c762ba668e58c3e127b57ba7d34ca6fdb269edfc" class="text black" rel="nofollow">c762ba6</a></span></div><div class="ui table"><table class="file-preview"><tbody><tr><td class="lines-num"><span data-line-number="32"></span></td><td class="lines-code chroma"><code class="code-inner"><span class="kr">async</span> <span class="kd">function</span> <span class="nx">readeckApiCall</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">params</span><span class="p">)</span> <span class="p">{</span> </code></td></tr></tbody></table></div></div><p dir="auto"></p> <p dir="auto">Could you inspect your browser extension to see if it prints anything useful to the JS console when this error happens?</p> <ol dir="auto"> <li>Open the Add-ons Manager by going to Tools → “Extensions and Themes”;</li> <li>Cog icon → “Debug add-ons”;</li> <li>“Inspect” the Readeck add-on;</li> <li>While keeping that devtools window open, submit a page to Readeck again;</li> <li>Check whether the JS console has something printed that might hint to the request being aborted client-side prior to nginx responding with HTTP 499.</li> </ol> @Minoru I can not find any specific client-side timeout for the browser extension POSTing the page payload to the Readeck API:

Lines 197 to 218 in c762ba6
/**
* savePage sends the page to Readeck.
*
* @async
* @param {import("../content-script/content-script").PageObj} page Page object
* @returns {Promise<import("../background").ApiResult>} A promise of the API call result
*/
export async function savePage(page) {
return await browser.runtime.sendMessage({
type: "save-page",
serverURL: get(serverURL),
path: "api/bookmarks",
params: {
method: "post",
headers: {
Accept: "application/json",
Authorization: `Bearer ${get(token)}`,
},
},
page,
})
}

async function readeckApiCall(url, params) {

Could you inspect your browser extension to see if it prints anything useful to the JS console when this error happens?

  1. Open the Add-ons Manager by going to Tools → “Extensions and Themes”;
  2. Cog icon → “Debug add-ons”;
  3. “Inspect” the Readeck add-on;
  4. While keeping that devtools window open, submit a page to Readeck again;
  5. Check whether the JS console has something printed that might hint to the request being aborted client-side prior to nginx responding with HTTP 499.
]]>
mislav 121790190: https://codeberg.org/readeck/browser-extension/issues/127#issuecomment-12995484 Sat, 11 Apr 2026 18:39:42 +0200
Minoru commented on issue readeck/browser-extension#127 https://codeberg.org/readeck/browser-extension/issues/127#issuecomment-12994692 Fails with "Could not establish connection. Receiving end does not exist" <p dir="auto">It didn&#39;t change a thing.</p> It didn't change a thing.

]]>
Minoru 121781118: https://codeberg.org/readeck/browser-extension/issues/127#issuecomment-12994692 Sat, 11 Apr 2026 18:12:50 +0200
mislav pushed to html-refresh-directive at readeck/readeck https://codeberg.org/readeck/readeck/commit/b167631d2ab897a0dc0b212aac78e8317b968e4d <a href="https://codeberg.org/readeck/readeck/commit/b167631d2ab897a0dc0b212aac78e8317b968e4d">b167631d2ab897a0dc0b212aac78e8317b968e4d</a> Simplify tinymeta b167631d2ab897a0dc0b212aac78e8317b968e4d Simplify tinymeta]]> mislav 121761048: https://codeberg.org/readeck/readeck/commit/b167631d2ab897a0dc0b212aac78e8317b968e4d Sat, 11 Apr 2026 17:33:23 +0200 mislav created pull request readeck/readeck#1185 https://codeberg.org/readeck/readeck/pulls/1185 1185#WIP: support HTML Refresh header# Summary

This extends Drop.Load() with support for HTML Refresh directive specified either via HTTP response header or via <meta> tag.

Fixes #1179

TODO:

  • Is Drop.Load() the correct place to implement this?
  • Should we set the HTTP Referer header when following this type of redirect? (The spec suggests we should.)
  • Set maximum redirect limit to prevent infinite redirect loops
  • Clean up the extension of the tinymeta package

Did you write it yourself?

I didn't use any AI tool to produce this contribution.

Did you add tests?

I added tests to my contribution

Did you run the tests?

The tests finished successfully

]]>
mislav 121723944: https://codeberg.org/readeck/readeck/pulls/1185 Sat, 11 Apr 2026 15:39:20 +0200
mislav pushed to html-refresh-directive at readeck/readeck https://codeberg.org/readeck/readeck/commit/0b66aae149e10e8ad88de73b96948421da20f044 <a href="https://codeberg.org/readeck/readeck/commit/0b66aae149e10e8ad88de73b96948421da20f044">0b66aae149e10e8ad88de73b96948421da20f044</a> WIP support HTML Refresh header 0b66aae149e10e8ad88de73b96948421da20f044 WIP support HTML Refresh header]]> mislav 121721916: https://codeberg.org/readeck/readeck/commit/0b66aae149e10e8ad88de73b96948421da20f044 Sat, 11 Apr 2026 15:33:40 +0200 mislav created branch html-refresh-directive in readeck/readeck https://codeberg.org/readeck/readeck/src/branch/html-refresh-directive mislav 121721886: https://codeberg.org/readeck/readeck/src/branch/html-refresh-directive Sat, 11 Apr 2026 15:33:40 +0200 fschoell commented on issue readeck/readeck-ios#15 https://codeberg.org/readeck/readeck-ios/issues/15#issuecomment-12987633 Long articles are 'choppy' <p dir="auto">ok yes beta works fine</p> ok yes beta works fine

]]>
fschoell 121695459: https://codeberg.org/readeck/readeck-ios/issues/15#issuecomment-12987633 Sat, 11 Apr 2026 14:07:24 +0200
Minoru opened issue readeck/browser-extension#127 https://codeberg.org/readeck/browser-extension/issues/127 127#Fails with "Could not establish connection. Receiving end does not exist"# I'm using Nginx as a reverse proxy for Readeck. Most pages are saved just fine, but occasionally I'll bump into one that fails like this:

Something went wrong :-( Could not establish connection. Receiving end does not exist

Nginx logs show code 499:

X.X.X.X - - [11/Apr/2026:10:32:19 +0000] "POST /api/bookmarks HTTP/2.0" 499 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0"

Readeck logs don't show anything for that request.

The page is https://blog.voron.me/r1bng_dxpedition?utm_source=teletype&utm_medium=feed_rss&utm_campaign=voronspb Previously it was failing to get saved because client_max_body_size in Nginx was set to 100M; I bumped that to 300M and now running into this error.

It might be some timeout. I didn't time it precisely, but it takes between 20 and 30 seconds between me clicking the "Save" button and this error appearing.

Extension version is 2.6.3, Firefox 140.9.1esr on Debian 13. As I said, I ran into this issue previously, including on my Android phone, so this isn't some new regression or anything like that.

]]>
Minoru 121672545: https://codeberg.org/readeck/browser-extension/issues/127 Sat, 11 Apr 2026 12:41:54 +0200
fabiante commented on issue readeck/readeck#1152 https://codeberg.org/readeck/readeck/issues/1152#issuecomment-12979854 Custom favicon <p dir="auto">I agree with you that even this seemingly small detail is already something that needs care long-term and will increase complexity. My initial response shows that pretty well.</p> I agree with you that even this seemingly small detail is already something that needs care long-term and will increase complexity. My initial response shows that pretty well.

]]>
fabiante 121639821: https://codeberg.org/readeck/readeck/issues/1152#issuecomment-12979854 Sat, 11 Apr 2026 10:20:10 +0200
fabiante commented on issue readeck/readeck#1152 https://codeberg.org/readeck/readeck/issues/1152#issuecomment-12979431 Custom favicon <p dir="auto">I would like to implement this. I have already changed the favicons locally, but that&#39;s just playing around.</p> I would like to implement this. I have already changed the favicons locally, but that's just playing around.

]]>
fabiante 121635009: https://codeberg.org/readeck/readeck/issues/1152#issuecomment-12979431 Sat, 11 Apr 2026 10:06:20 +0200
fabiante commented on issue readeck/readeck#399 https://codeberg.org/readeck/readeck/issues/399#issuecomment-12977631 Set link expiration time <p dir="auto">The <a href="https://readeck.org/en/docs/configuration#bookmarks-section" rel="nofollow">current configuration option (<code>public_share_ttl</code>)</a> allows to change the value of the shared link &#34;globally&#34;.</p> The current configuration option (public_share_ttl) allows to change the value of the shared link "globally".

]]>
fabiante 121620408: https://codeberg.org/readeck/readeck/issues/399#issuecomment-12977631 Sat, 11 Apr 2026 08:56:47 +0200
monki pushed to main at readeck/readeck-ios https://codeberg.org/readeck/readeck-ios/compare/c717af8f21f96267bc3b70eef07b2245a1cd1687...35cda891b4f033dad0c384e3a68d08e11ead04c8 <a href="https://codeberg.org/readeck/readeck-ios/commit/35cda891b4f033dad0c384e3a68d08e11ead04c8">35cda891b4f033dad0c384e3a68d08e11ead04c8</a> Merge pull request #42 from ilyas-hallak/bugfix/issue-27-settings-persistence <a href="https://codeberg.org/readeck/readeck-ios/commit/ef54a492b4218c072e3ca387acffd33c16513a47">ef54a492b4218c072e3ca387acffd33c16513a47</a> fix: adapt reader UI to color theme and add hide summary toggle <a href="https://codeberg.org/readeck/readeck-ios/commit/86c5ff87c662f4530210ca892ea1ba6e76eac66f">86c5ff87c662f4530210ca892ea1ba6e76eac66f</a> fix: move CSS help sheet to top-level to prevent dismissing parent sheet <a href="https://codeberg.org/readeck/readeck-ios/commit/00c0f2090db624fd573460508d168833ec47ed53">00c0f2090db624fd573460508d168833ec47ed53</a> fix: prevent settings from being reset on partial saves (#27) <a href="https://codeberg.org/readeck/readeck-ios/commit/b22cb935479ab1b5070d05051fc5b96ebf14cbbb">b22cb935479ab1b5070d05051fc5b96ebf14cbbb</a> Merge pull request #41 from ilyas-hallak/feat/issue-40-article-summary 35cda891b4f033dad0c384e3a68d08e11ead04c8 Merge pull request #42 from ilyas-hallak/bugfix/issue-27-settings-persistence ef54a492b4218c072e3ca387acffd33c16513a47 fix: adapt reader UI to color theme and add hide summary toggle 86c5ff87c662f4530210ca892ea1ba6e76eac66f fix: move CSS help sheet to top-level to prevent dismissing parent sheet 00c0f2090db624fd573460508d168833ec47ed53 fix: prevent settings from being reset on partial saves (#27) b22cb935479ab1b5070d05051fc5b96ebf14cbbb Merge pull request #41 from ilyas-hallak/feat/issue-40-article-summary]]> monki 121495281: https://codeberg.org/readeck/readeck-ios/compare/c717af8f21f96267bc3b70eef07b2245a1cd1687...35cda891b4f033dad0c384e3a68d08e11ead04c8 Fri, 10 Apr 2026 23:44:17 +0200 monki pushed to bugfix/issue-27-settings-persistence at readeck/readeck-ios https://codeberg.org/readeck/readeck-ios/commit/ef54a492b4218c072e3ca387acffd33c16513a47 <a href="https://codeberg.org/readeck/readeck-ios/commit/ef54a492b4218c072e3ca387acffd33c16513a47">ef54a492b4218c072e3ca387acffd33c16513a47</a> fix: adapt reader UI to color theme and add hide summary toggle ef54a492b4218c072e3ca387acffd33c16513a47 fix: adapt reader UI to color theme and add hide summary toggle]]> monki 121492992: https://codeberg.org/readeck/readeck-ios/commit/ef54a492b4218c072e3ca387acffd33c16513a47 Fri, 10 Apr 2026 23:35:45 +0200 monki pushed to bugfix/issue-27-settings-persistence at readeck/readeck-ios https://codeberg.org/readeck/readeck-ios/commit/86c5ff87c662f4530210ca892ea1ba6e76eac66f <a href="https://codeberg.org/readeck/readeck-ios/commit/86c5ff87c662f4530210ca892ea1ba6e76eac66f">86c5ff87c662f4530210ca892ea1ba6e76eac66f</a> fix: move CSS help sheet to top-level to prevent dismissing parent sheet 86c5ff87c662f4530210ca892ea1ba6e76eac66f fix: move CSS help sheet to top-level to prevent dismissing parent sheet]]> monki 121472889: https://codeberg.org/readeck/readeck-ios/commit/86c5ff87c662f4530210ca892ea1ba6e76eac66f Fri, 10 Apr 2026 23:05:53 +0200 monki pushed to bugfix/issue-27-settings-persistence at readeck/readeck-ios https://codeberg.org/readeck/readeck-ios/compare/a7950e6aaf81a94d77145e14470b4c9777da9f45...00c0f2090db624fd573460508d168833ec47ed53 <a href="https://codeberg.org/readeck/readeck-ios/commit/00c0f2090db624fd573460508d168833ec47ed53">00c0f2090db624fd573460508d168833ec47ed53</a> fix: prevent settings from being reset on partial saves (#27) <a href="https://codeberg.org/readeck/readeck-ios/commit/b22cb935479ab1b5070d05051fc5b96ebf14cbbb">b22cb935479ab1b5070d05051fc5b96ebf14cbbb</a> Merge pull request #41 from ilyas-hallak/feat/issue-40-article-summary <a href="https://codeberg.org/readeck/readeck-ios/commit/c42177c85dedc7932547a84ab4f4648899c1c6e4">c42177c85dedc7932547a84ab4f4648899c1c6e4</a> refactor: inject factory into ArticleSummaryViewModel with default .shared <a href="https://codeberg.org/readeck/readeck-ios/commit/92eea4d01309cc561ae095cc074cb8f259e7fc71">92eea4d01309cc561ae095cc074cb8f259e7fc71</a> refactor: extract SummarizationRepository and HTMLStringUtils from UseCase <a href="https://codeberg.org/readeck/readeck-ios/commit/3cc3adce0ce02d4d4130e74d2605839336e57fe5">3cc3adce0ce02d4d4130e74d2605839336e57fe5</a> fix: make summary card header reliably tappable for collapse/expand 00c0f2090db624fd573460508d168833ec47ed53 fix: prevent settings from being reset on partial saves (#27) b22cb935479ab1b5070d05051fc5b96ebf14cbbb Merge pull request #41 from ilyas-hallak/feat/issue-40-article-summary c42177c85dedc7932547a84ab4f4648899c1c6e4 refactor: inject factory into ArticleSummaryViewModel with default .shared 92eea4d01309cc561ae095cc074cb8f259e7fc71 refactor: extract SummarizationRepository and HTMLStringUtils from UseCase 3cc3adce0ce02d4d4130e74d2605839336e57fe5 fix: make summary card header reliably tappable for collapse/expand]]> monki 121470294: https://codeberg.org/readeck/readeck-ios/compare/a7950e6aaf81a94d77145e14470b4c9777da9f45...00c0f2090db624fd573460508d168833ec47ed53 Fri, 10 Apr 2026 22:56:44 +0200 monki created branch bugfix/issue-27-settings-persistence in readeck/readeck-ios https://codeberg.org/readeck/readeck-ios/src/branch/bugfix/issue-27-settings-persistence monki 121470282: https://codeberg.org/readeck/readeck-ios/src/branch/bugfix/issue-27-settings-persistence Fri, 10 Apr 2026 22:56:44 +0200 monki commented on issue readeck/readeck-ios#37 https://codeberg.org/readeck/readeck-ios/issues/37#issuecomment-12949995 Follow The Money articles content not visible when shared from Safari <p dir="auto">It&#39;s possible with Readeck 0.22, and I will implement this in the next few weeks in the app. It’s one of the most wished features. :)</p> It's possible with Readeck 0.22, and I will implement this in the next few weeks in the app. It’s one of the most wished features. :)

]]>
monki 121325271: https://codeberg.org/readeck/readeck-ios/issues/37#issuecomment-12949995 Fri, 10 Apr 2026 15:57:03 +0200
mislav commented on issue readeck/readeck#1181 https://codeberg.org/readeck/readeck/issues/1181#issuecomment-12949203 Browser Bookmarklet <p dir="auto">Hi, thanks for the detailed feature request. Agreed that Readeck could in theory make the bookmarklet experience better; for example, take a look at the thoughts I shared on the same topic on our community forum: <a href="https://community.readeck.org/d/65-bookmarklet/5" rel="nofollow">https://community.readeck.org/d/65-bookmarklet/5</a></p> <p dir="auto">However, since nearly every browser out there is able to install the Readeck browser extension, which offers a much better and complete experience of sending web pages to Readeck than a bookmarklet ever could, I&#39;m wondering whether there is even a use-case for a bookmarklet over the browser extension? What do you think?</p> Hi, thanks for the detailed feature request. Agreed that Readeck could in theory make the bookmarklet experience better; for example, take a look at the thoughts I shared on the same topic on our community forum: https://community.readeck.org/d/65-bookmarklet/5

However, since nearly every browser out there is able to install the Readeck browser extension, which offers a much better and complete experience of sending web pages to Readeck than a bookmarklet ever could, I'm wondering whether there is even a use-case for a bookmarklet over the browser extension? What do you think?

]]>
mislav 121313343: https://codeberg.org/readeck/readeck/issues/1181#issuecomment-12949203 Fri, 10 Apr 2026 15:29:24 +0200
mislav commented on issue readeck/browser-extension#122 https://codeberg.org/readeck/browser-extension/issues/122#issuecomment-12948795 Chrome sends AVIF images to Readeck <p dir="auto">Thanks; confirmed that the latest browser extension fixes the issue for me in Chrome!</p> Thanks; confirmed that the latest browser extension fixes the issue for me in Chrome!

]]>
mislav 121308696: https://codeberg.org/readeck/browser-extension/issues/122#issuecomment-12948795 Fri, 10 Apr 2026 15:14:47 +0200
monki commented on issue readeck/readeck-ios#37 https://codeberg.org/readeck/readeck-ios/issues/37#issuecomment-12938685 Follow The Money articles content not visible when shared from Safari <p dir="auto">Sounds good! :)</p> Sounds good! :)

]]>
monki 121177293: https://codeberg.org/readeck/readeck-ios/issues/37#issuecomment-12938685 Fri, 10 Apr 2026 08:13:32 +0200
mislav created pull request readeck/browser-extension#126 https://codeberg.org/readeck/browser-extension/pulls/126 126#Fix YouTube video title getting pre-populated when adding bookmark# YouTube seems to have removed <meta name> and <meta property> tags
(at least for me) pertaining to the video being watched, with the only
remaining metadata being stored in JSON-LD with the type "VideoObject". This
wasn't among any of the allow-listed "article" types, so it was completely
ignored.

This adds VideoObject to known article types so that the bookmark form might
make use of video metadata.

]]>
mislav 121097850: https://codeberg.org/readeck/browser-extension/pulls/126 Thu, 09 Apr 2026 23:55:03 +0200
mislav pushed to fix-youtube-titles at readeck/browser-extension https://codeberg.org/readeck/browser-extension/commit/c762ba668e58c3e127b57ba7d34ca6fdb269edfc <a href="https://codeberg.org/readeck/browser-extension/commit/c762ba668e58c3e127b57ba7d34ca6fdb269edfc">c762ba668e58c3e127b57ba7d34ca6fdb269edfc</a> Fix YouTube video title getting pre-populated when adding bookmark c762ba668e58c3e127b57ba7d34ca6fdb269edfc Fix YouTube video title getting pre-populated when adding bookmark]]> mislav 121097802: https://codeberg.org/readeck/browser-extension/commit/c762ba668e58c3e127b57ba7d34ca6fdb269edfc Thu, 09 Apr 2026 23:54:58 +0200 mislav created branch fix-youtube-titles in readeck/browser-extension https://codeberg.org/readeck/browser-extension/src/branch/fix-youtube-titles mislav 121097775: https://codeberg.org/readeck/browser-extension/src/branch/fix-youtube-titles Thu, 09 Apr 2026 23:54:57 +0200