Exploring IndieAuth (But I Started With Micropub)

I’ve spent some time over the past week working on a proof-of-concept integration of Micropub into Django. I don’t have anything functional to show for it, but I have a much better understanding of IndieAuth, Micropub, and writing decoupled Django apps.

I’ve spent some time over the past week working on a proof-of-concept (POC) integration of micropub into Django.

Micropub is a protocol for managing content on a website. Implementing it on my website could allow me to post from clients outside of my website that support the protocol, including making iOS shortcuts to, for example, upload an photo from the share sheet. I think this could help reduce the friction it takes to get content from where I am to my site.

An implementation validator exists at micropub.rocks, so I figured I’d start there and implement features as needed. The first thing it wants is to authorize view IndieAuth or a manually-input access token for the micropub endpoint. That sent me down the path of trying to implement IndieAuth in the POC also.

IndieAuth is an authorization spec built on top of OAuth2 to allow a website owner to authorize services with their website. Micropub and IndieAuth seem pretty closely tied. The Micropub spec says “Authorization SHOULD be handled via the OAuth 2.0 [RFC6749] protocol. Applications MAY use the [IndieAuth] extension which supports endpoint discovery from a URL“ (Micropub § 5.2) and The IndieAuth spec says “IndieAuth is an identity layer on top of OAuth 2.0 [RFC6749], primarily used to obtain an OAuth 2.0 Bearer Token [RFC6750] for use by [Micropub] clients.” (IndieAuth abstract).

IndieAuth

A key point with IndieAuth is that the client_id in the flow now has meaning. It is now a URL where the client should publish a Client ID Metadata Document in JSON which should contain the client_id, an optional client_name, the client_uri, an optional logo_uri, and optional redirect_uris.

I used the oauthlib python package to help me along in implementing the IndieAuth server piece, and it mostly did well. It requires an implementation of a RequestValidator class to manage the data storage requirements in the flow, and I was able to use method overrides there to enforce the bulk of the IndieAuth requirements.

I went as far as I could testing the server with Postman, but in the end also implemented a client. oauthlib was less helpful here, or perhaps I was losing steam.

Micropub

When I finally felt like I had this piece at least functional I went back to micropub.rocks. I immediately ran into a roadblock: micropub.rocks does not implement a client metadata in JSON. It seems to implement an older version of the spec which called for client metadata being embedded in microformats in an HTML document. The last change to the micropub.rocks source was 4 years ago, and the change in the spec to the JSON metadata document happened six months ago, so that makes sense.

I did not have the energy to implement older versions of the IndieAuth spec. I figured that I’ll just generate non-expiring access tokens from Django to use in micropub clients and skip the IndieAuth flow. And then I thought for the time being I’ll work on implementing micropub without authorization.

The spec is good, but the IndieWeb “Handling a micropub request” is great.

I didn’t make it far before getting the itch to implement some changes on my actual website instead of in the POC. Instead of feeling the need to cover all cases in the POC, I could implement gradually in my website.

In addition to learning a lot more about these specs, I tried implementing them in Django in a decoupled manner, in a way that I could include a "micropub" package or an "indieauth" package in my website. I think the biggest thing from that is seeing that it probably can’t be a install package and be done, but rather the packages provide some classes that I can inherit in my site to get the bulk of the work done, but allow me to integrate as needed. Micropub, for example, needs to be able to save a new post request. That’s outside of Micropub’s scope. But I could inherit a Micropub view that does the work of parsing the request and write the specific-to-my-site pieces myself.

Even with nothing real to show, I learned a ton working through the IndieAuth spec, the related OAuth specs, and the bit of Micropub work. I feel I have a better handle on these, and a better handle on writing Django code.