{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreige3gjalf35gbzlal73owx5xlcswlavelpb4v3kdsmyhumbculu5a",
    "commit": {
      "cid": "bafyreiaml7fr4demuao4k2rkmbnqrj43nafnfeieun7ah3fepbutn4umbm",
      "rev": "3mmaaymqzf32f"
    },
    "uri": "at://did:plc:dadhhalkfcq3gucaq25hjqon/app.bsky.feed.post/3mmaaymmhtk2b",
    "validationStatus": "valid"
  },
  "content": {
    "$type": "pub.leaflet.content",
    "pages": [
      {
        "$type": "pub.leaflet.pages.linearDocument",
        "blocks": [
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "It's been a while since my last update, or even any progress, on the distributed PDS. I started looking into it again last week though and have hit quite the show stopper... OAuth 🫠"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#link",
                      "uri": "https://atproto.com/specs/oauth#demonstrating-proof-of-possession-d-po-p"
                    }
                  ],
                  "index": {
                    "byteEnd": 165,
                    "byteStart": 161
                  }
                }
              ],
              "plaintext": "I'm not going to pretend like I fully understand the specs of how OAuth works, but I know enough I think. With OAuth, the client and server use something called DPoP. As part of this process, the server will generate and rotate very frequently a nonce, which it uses to verify client auth requests. "
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "Here's the problem. This is a very high level basic version of what happens; like I said I'm not going to pretend I know enough."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": " In the distributed PDS world, let's say we have 2 nodes and we are using our round robin load balancing."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "Client starts an OAuth session creation which hits node 1 and it has generated and stored a nonce for the DPoP part of the request/response with the client. The client then tries to make a request for something (like creating a new record) which requires auth, so it sends over the OAuth tokens etc, using DPoP. However this request hits node 2. Node 2 attempts to verify the auth requests and rejects it because it uses a totally different nonce than node 1."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "So yh, that's quite a problem. Easy solution? Well not easy, but I think it's the least problematic for now."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "The load balancer ensures that any OAuth requests are always tried on a set node first, labeled as the auth node. It should be the one that's more likely to be available. When I say OAuth requests, I mean the requests to start the OAuth flow. Then any request that requires auth to complete (creating a record etc), the node that receives the request (if it doesn't happen to be the auth node) can make a request to the auth node with the clients auth details, and ask the auth node to verify. If successful, the non auth node, can then carry on with the client request. If for any reason the auth node is down, well the user will perhaps need to re-authenticate and a new auth node is configured. "
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "Remember, this is all just a proof of concept. I'm not actually going to run this with my main account! So re-authenticating isn't really a problem. "
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "There's one more idea that I had, that actually ties into the whole distributed PDS idea that I had. Remember I said originally that I can see a world where my phone is also the host of my PDS, and my laptop can also be the host of my PDS. Oh and my Pi could be one too. Well let's say I'm on my phone, using a client which needs to authenticate. Wouldn't it make sense, that the client on my phone goes straight to the PDS on my phone to authenticate? Then when I'm on my laptop, it uses the PDS on my laptop. See where I'm going with this? "
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "My idea of a distributed PDS isn't to distribute it for shits and giggles (although it is a ton of fun doing this). It's to prove that there is a possibility that me as a user, can use multiple devices and connect to a variety of PDS which improve the experience. All the data is still stored somewhere (Turso as a SQLite db host in this experiment). So maybe the real solution to the OAuth problem, is to just make sure that the client uses a consistent PDS host 🤷‍♂️"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "Maybe I'll try both. I could try and be brave and run a PDS on my laptop. Then when I try to use my laptop to do atproto things, I ensure that my Caddy config redirects my laptop requests, back to my laptop. Then all other requests from other devices go to my Pi. "
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "plaintext": "All I did writing that out was nerd snipe myself into doing just that... Stay tuned!"
            }
          }
        ],
        "id": "019e41da-0bdf-733e-8b69-e8391d369f6d"
      }
    ]
  },
  "description": "",
  "path": "/3mmaayhddq22b",
  "publishedAt": "2026-05-19T20:43:48.336Z",
  "site": "at://did:plc:dadhhalkfcq3gucaq25hjqon/site.standard.publication/3lzrigh3cl22p",
  "tags": [
    "pds",
    "atproto"
  ],
  "title": "Journey to a distributed PDS: OAuth and deeper thoughts on why this experiment exists..."
}