Over the past couple of days I've noticed a problem when posting a comment on the blog.
The comment is submitted but you are not directed back to the post. No follow-up actions occur either such as sending a webmention where appropriate or mailing me to advise that a comment has been submitted.
After checking, I saw the site is generating a 405 error in wp-comments-post.php which checks that the request method is POST
and fails if the method doesn't match.
I'm not sure when it started but I think it might have coincided with the update to WordPress 4.9.7.
I tried disabling a number of plugins and custom functions to no avail. Searches revealed that this is a relatively common issue with some saying it relates to a problem sending emails from WordPress. I turned off the email notification options in Discussion Settings and comments started working.
Email is definitely the issue. I've tried a couple of SMTP plugins instead of relying on defaults but get the same error so I don't know what's actually causing it.
I've left the email notifications off for now so that things work until I can find the cause. There may, consequently, be a delay in me responding or reacting to comments.
{
"type": "entry",
"author": {
"name": "Colin Walker",
"url": "https://colinwalker.blog/",
"photo": null
},
"url": "https://colinwalker.blog/09-07-2018-1239/",
"published": "2018-07-09T11:39:24+00:00",
"content": {
"html": "<p>Over the past couple of days I've noticed a problem when posting a comment on the blog.</p>\n<p>The comment is submitted but you are not directed back to the post. No follow-up actions occur either such as sending a webmention where appropriate or mailing me to advise that a comment has been submitted.</p>\n<p>After checking, I saw the site is generating a 405 error in wp-comments-post.php which checks that the request method is <code>POST</code> and fails if the method doesn't match.</p>\n<p>I'm not sure when it started but I think it might have coincided with the update to WordPress 4.9.7.</p>\n<p>I tried disabling a number of plugins and custom functions to no avail. Searches revealed that this is a relatively common issue with some saying it relates to a problem sending emails from WordPress. I turned off the email notification options in Discussion Settings and comments started working.</p>\n<p>Email is definitely the issue. I've tried a couple of SMTP plugins instead of relying on defaults but get the same error so I don't know what's actually causing it.</p>\n<p>I've left the email notifications off for now so that things work until I can find the cause. There may, consequently, be a delay in me responding or reacting to comments.</p>",
"text": "Over the past couple of days I've noticed a problem when posting a comment on the blog.\nThe comment is submitted but you are not directed back to the post. No follow-up actions occur either such as sending a webmention where appropriate or mailing me to advise that a comment has been submitted.\nAfter checking, I saw the site is generating a 405 error in wp-comments-post.php which checks that the request method is POST and fails if the method doesn't match.\nI'm not sure when it started but I think it might have coincided with the update to WordPress 4.9.7.\nI tried disabling a number of plugins and custom functions to no avail. Searches revealed that this is a relatively common issue with some saying it relates to a problem sending emails from WordPress. I turned off the email notification options in Discussion Settings and comments started working.\nEmail is definitely the issue. I've tried a couple of SMTP plugins instead of relying on defaults but get the same error so I don't know what's actually causing it.\nI've left the email notifications off for now so that things work until I can find the cause. There may, consequently, be a delay in me responding or reacting to comments."
},
"_id": "574140",
"_source": "237",
"_is_read": true
}
{
"type": "entry",
"author": {
"name": "Colin Walker",
"url": "https://colinwalker.blog/",
"photo": null
},
"url": "https://colinwalker.blog/vouch/",
"published": "2018-07-03T12:03:25+00:00",
"content": {
"html": "<p><a href=\"https://david.shanske.com/2018/07/01/brainstorming-on-implementing-vouch-following-and-blogrolls/\">David Shanske</a> wrote about a <a href=\"https://indieweb.org/2018/vouch\">brainstorming session</a> held at Indieweb Summit 2018 about implementing \"<a href=\"https://indieweb.org/Vouch\">Vouch</a>\" - a trust/anti-spam extension for webmention.</p>\n<p>The idea of Vouch is that people create a list of webmention senders they trust and make this available to others. If a domain is in a published trusted list then it has been \"vouched for\" meaning it's safe to accept and approve webmentions from that domain.</p>\n<p>As David says <em>\"This should block automated spam and aid in moderation.\"</em></p>\n<p>But, problem is, <em>\"(w)here do you find people who have been approved by people you have approved of?\"</em> How do we build lists and share them? Can a blogroll be such a list?</p>\n<p>Various ideas were proposed including using a <code>rel</code> value such as follower, following or contact, or maybe using microformats markup to declare <code>u-follow-of</code> entries in a h-feed.</p>\n<p>Now, the issue with a blogroll is that, unless it's explicitly curated, its member sites may well not be configured to send webmentions and it might be a bit of a waste.</p>\n<p>As such, I thought my <a href=\"https://colinwalker.blog/directory/\">/Directory</a> could be an ideal place to hold such a list. It is automated, only includes sites that have sent webmentions and only shows those that I approve - I've not had webmention spam but any would be removed from comments and not appear in the directory.</p>\n<p>I've laid the groundwork by adding a h-feed and <code>u-follow-of</code> markup to the Directory plugin (subject to tweaking but it's a start) so we now need the missing link of telling other sites where your list is.</p>",
"text": "David Shanske wrote about a brainstorming session held at Indieweb Summit 2018 about implementing \"Vouch\" - a trust/anti-spam extension for webmention.\nThe idea of Vouch is that people create a list of webmention senders they trust and make this available to others. If a domain is in a published trusted list then it has been \"vouched for\" meaning it's safe to accept and approve webmentions from that domain.\nAs David says \"This should block automated spam and aid in moderation.\"\nBut, problem is, \"(w)here do you find people who have been approved by people you have approved of?\" How do we build lists and share them? Can a blogroll be such a list?\nVarious ideas were proposed including using a rel value such as follower, following or contact, or maybe using microformats markup to declare u-follow-of entries in a h-feed.\nNow, the issue with a blogroll is that, unless it's explicitly curated, its member sites may well not be configured to send webmentions and it might be a bit of a waste.\nAs such, I thought my /Directory could be an ideal place to hold such a list. It is automated, only includes sites that have sent webmentions and only shows those that I approve - I've not had webmention spam but any would be removed from comments and not appear in the directory.\nI've laid the groundwork by adding a h-feed and u-follow-of markup to the Directory plugin (subject to tweaking but it's a start) so we now need the missing link of telling other sites where your list is."
},
"name": "Vouch",
"_id": "574144",
"_source": "237",
"_is_read": true
}
Liked: Scripting News: What became of the blogosphere?...
"I doubt if the blogosphere of 2018 is smaller in absolute terms than the blogosphere of the early 2000s. In fact I'm pretty sure it's orders of magnitude larger...
What changed is we lost the center."
The emergence of social networks as a driving force on the internet gave people quicker, easier ways to make a point, connect and have conversations. Blogs still existed but became isolated, the strands that wove them together as more of a community unraveled.
Things have been getting better:
- a backlash in some quarters
- the indieweb movement seeking to facilitate cross-talk using technologies like webmentions
- micro.blog aiming to get people focused on blogging again
But it is still too easy to jump on your social platform of choice rather than have discussions via blogs.
{
"type": "entry",
"author": {
"name": "Colin Walker",
"url": "https://colinwalker.blog/",
"photo": null
},
"url": "https://colinwalker.blog/26-06-2018-1500/",
"published": "2018-06-26T14:02:09+00:00",
"content": {
"html": "<p><em>Liked: <a href=\"http://scripting.com/2018/06/26/114410.html\">Scripting News: What became of the blogosphere?</a>...</em></p>\n<blockquote><p>\n <em>\"I doubt if the blogosphere of 2018 is smaller in absolute terms than the blogosphere of the early 2000s. In fact I'm pretty sure it's orders of magnitude larger...</em></p>\n<p> <em>What changed is we lost the center.\"</em>\n</p></blockquote>\n<p>The emergence of social networks as a driving force on the internet gave people quicker, easier ways to make a point, connect and have conversations. Blogs still existed but became isolated, the strands that wove them together as more of a community unraveled.</p>\n<p>Things have been getting better:</p>\n<ul><li>a backlash in some quarters</li>\n<li>the indieweb movement seeking to facilitate cross-talk using technologies like webmentions</li>\n<li>micro.blog aiming to get people focused on blogging again</li>\n</ul><p>But it is still too easy to jump on your social platform of choice rather than have discussions via blogs.</p>",
"text": "Liked: Scripting News: What became of the blogosphere?...\n\n \"I doubt if the blogosphere of 2018 is smaller in absolute terms than the blogosphere of the early 2000s. In fact I'm pretty sure it's orders of magnitude larger...\n What changed is we lost the center.\"\n\nThe emergence of social networks as a driving force on the internet gave people quicker, easier ways to make a point, connect and have conversations. Blogs still existed but became isolated, the strands that wove them together as more of a community unraveled.\nThings have been getting better:\na backlash in some quarters\nthe indieweb movement seeking to facilitate cross-talk using technologies like webmentions\nmicro.blog aiming to get people focused on blogging again\nBut it is still too easy to jump on your social platform of choice rather than have discussions via blogs."
},
"_id": "574152",
"_source": "237",
"_is_read": true
}
If you’re familiar with OAuth, this introduction to IndieAuth walks through the process of how auth for the open web works. Really happy that Micro.blog supports this now.
{
"type": "entry",
"author": {
"name": null,
"url": "https://www.manton.org/",
"photo": null
},
"url": "https://www.manton.org/2018/07/07/if-youre-familiar.html",
"content": {
"html": "<p>If you\u2019re familiar with OAuth, <a href=\"https://aaronparecki.com/2018/07/07/7/oauth-for-the-open-web\">this introduction to IndieAuth</a> walks through the process of how auth for the open web works. Really happy that Micro.blog supports this now.</p>",
"text": "If you\u2019re familiar with OAuth, this introduction to IndieAuth walks through the process of how auth for the open web works. Really happy that Micro.blog supports this now."
},
"published": "2018-07-07T15:41:12-05:00",
"_id": "570871",
"_source": "12",
"_is_read": true
}
We posted a new episode of Core Intuition this week with a summary of my time at IndieWeb Summit and more.
{
"type": "entry",
"author": {
"name": null,
"url": "https://www.manton.org/",
"photo": null
},
"url": "https://www.manton.org/2018/07/06/212232.html",
"content": {
"html": "<p>We posted <a href=\"https://coreint.org/2018/07/episode-335-kind-of-a-challenge-for-newcomers/\">a new episode of Core Intuition</a> this week with a summary of my time at IndieWeb Summit and more.</p>",
"text": "We posted a new episode of Core Intuition this week with a summary of my time at IndieWeb Summit and more."
},
"published": "2018-07-06T16:22:32-05:00",
"_id": "570873",
"_source": "12",
"_is_read": true
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://www.manton.org/",
"photo": null
},
"url": "https://www.manton.org/2018/07/04/indieauth-for-external.html",
"name": "IndieAuth for external blogs",
"content": {
"html": "<p>Earlier this week I wrote about <a href=\"http://www.manton.org/2018/07/indieauth-for-micro-blog.html\">making Micro.blog an IndieAuth provider</a>. This allows anyone with a Micro.blog-hosted blog to sign in to IndieWeb-compatible apps. For example, using <a href=\"http://ownyourgram.com/\">OwnYourGram</a> to automatically copy Instagram photos to your own blog on Micro.blog.</p>\n\n<p>I\u2019ve now expanded this support to let anyone use Micro.blog to authorize an app even if your blog is hosted outside of Micro.blog. If you host somewhere else, you\u2019ll still be responsible for setting up posting, but having basic IndieAuth support can be useful if you want to connect your blog to tools that don\u2019t need to post, like <a href=\"https://xn--sr8hvo.ws/\">IndieWeb Ring</a> or the <a href=\"https://indieweb.org/\">IndieWeb.org</a> wiki.</p>\n\n<p>There are instructions <a href=\"http://help.micro.blog/2017/web-site-verification/\">on this Micro.blog help page</a> for adding the appropriate HTML tags to your site.</p>",
"text": "Earlier this week I wrote about making Micro.blog an IndieAuth provider. This allows anyone with a Micro.blog-hosted blog to sign in to IndieWeb-compatible apps. For example, using OwnYourGram to automatically copy Instagram photos to your own blog on Micro.blog.\n\nI\u2019ve now expanded this support to let anyone use Micro.blog to authorize an app even if your blog is hosted outside of Micro.blog. If you host somewhere else, you\u2019ll still be responsible for setting up posting, but having basic IndieAuth support can be useful if you want to connect your blog to tools that don\u2019t need to post, like IndieWeb Ring or the IndieWeb.org wiki.\n\nThere are instructions on this Micro.blog help page for adding the appropriate HTML tags to your site."
},
"published": "2018-07-04T08:21:54-05:00",
"_id": "570880",
"_source": "12",
"_is_read": true
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://www.manton.org/",
"photo": null
},
"url": "https://www.manton.org/2018/07/02/193738.html",
"name": "The web is the social network",
"content": {
"html": "<p>In my talk at Peers Conference earlier this year I closed with this quote from Brent Simmons:</p>\n\n<blockquote>\n Micro.blog is not an alternative silo: instead, it\u2019s what you build when you believe that <em>the web itself</em> is the great social network.\n</blockquote>\n\n<p>I\u2019ve been thinking more about Brent\u2019s post since then, and so for the keynote that Jean and I gave at <a href=\"http://www.manton.org/2018/06/indieweb-summit-2018-wrap-up.html\">IndieWeb Summit last week</a> I wanted to start with that quote. Many people have written nice testimonials about Micro.blog, but this one really seems to capture the goal.</p>\n\n<p>It should come as no surprise that I liked <a href=\"http://inessential.com/2018/02/01/why_micro_blog_is_not_another_app_net\">Brent\u2019s full post from February about why Micro.blog isn\u2019t like App.net</a>. He made the case even better than I usually do, about how the web is more important than any one platform:</p>\n\n<blockquote>\n But if you think of the years 1995-2005, you remember when the web was our social network: blogs, comments on blogs, feed readers, and services such as Flickr, Technorati, and BlogBridge to glue things together. Those were great years \u2014 but then a few tragedies happened: Google Reader came out, and then, almost <em>worse</em>, it went away. Worse still was the rise of Twitter and Facebook, when we decided it would be okay to give up ownership and let just a couple companies own our communication.\n</blockquote>\n\n<p>Micro.blog is one of the first platforms to focus on domain names that decouple the timeline from post storage. Anyone can post a Micro.blog-hosted site at their own domain name today and move it all somewhere else tomorrow. It\u2019s a simple, IndieWeb-friendly architecture that we think is essential to the next phase of the web.</p>",
"text": "In my talk at Peers Conference earlier this year I closed with this quote from Brent Simmons:\n\n\n Micro.blog is not an alternative silo: instead, it\u2019s what you build when you believe that the web itself is the great social network.\n\n\nI\u2019ve been thinking more about Brent\u2019s post since then, and so for the keynote that Jean and I gave at IndieWeb Summit last week I wanted to start with that quote. Many people have written nice testimonials about Micro.blog, but this one really seems to capture the goal.\n\nIt should come as no surprise that I liked Brent\u2019s full post from February about why Micro.blog isn\u2019t like App.net. He made the case even better than I usually do, about how the web is more important than any one platform:\n\n\n But if you think of the years 1995-2005, you remember when the web was our social network: blogs, comments on blogs, feed readers, and services such as Flickr, Technorati, and BlogBridge to glue things together. Those were great years \u2014 but then a few tragedies happened: Google Reader came out, and then, almost worse, it went away. Worse still was the rise of Twitter and Facebook, when we decided it would be okay to give up ownership and let just a couple companies own our communication.\n\n\nMicro.blog is one of the first platforms to focus on domain names that decouple the timeline from post storage. Anyone can post a Micro.blog-hosted site at their own domain name today and move it all somewhere else tomorrow. It\u2019s a simple, IndieWeb-friendly architecture that we think is essential to the next phase of the web."
},
"published": "2018-07-02T14:37:38-05:00",
"_id": "570883",
"_source": "12",
"_is_read": true
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://www.manton.org/",
"photo": null
},
"url": "https://www.manton.org/2018/07/02/indieauth-for-microblog.html",
"name": "IndieAuth for Micro.blog",
"content": {
"html": "<p>After posting about <a href=\"http://www.manton.org/2018/06/indieweb-summit-2018-wrap-up.html\">my time at IndieWeb Summit</a> and <a href=\"http://www.manton.org/2018/06/indiebookclub.html\">the new IndieBookClub support</a>, let me give some more details on what IndieAuth means for Micro.blog. I spent the second day of IndieWeb Summit working on this, and it has now been rolled out to all Micro.blog users. (If you haven\u2019t posted in the last few days, after your next post your microblog will be updated with the new authorization endpoints.)</p>\n\n<p>IndieAuth lets you sign in to other apps using your own domain name. If Micro.blog is hosting a blog for you, you can use that custom domain or your subdomain like yourname.micro.blog to sign in.</p>\n\n<p>While this was possible before with extra configuration to delegate auth to another service, Micro.blog can now be an IndieAuth provider on its own. It\u2019s much easier for IndieWeb apps to work with Micro.blog.</p>\n\n<p>Here are some apps that work great with Micro.blog:</p>\n\n<ul><li><a href=\"https://quill.p3k.io/\">Quill</a>: web-based interface for posting to your microblog.</li>\n<li><a href=\"https://ownyourgram.com/\">OwnYourGram</a>: automatically post your Instagram photos to your microblog.</li>\n<li><a href=\"https://ownyourswarm.p3k.io/\">OwnYourSwarm</a>: automatically post your Swarm check-ins to your microblog.</li>\n<li><a href=\"https://indiebookclub.biz/\">IndieBookClub</a>: post what books you're reading or want to read.</li>\n<li><a href=\"https://omnibear.com/\">Omnibear</a>: Chrome or Firefox extension for quick posting.</li>\n<li><a>IndieWeb Ring</a>: wait\u2026 <a href=\"http://help.micro.blog/2018/web-rings/\">what?</a></li>\n</ul><p>I\u2019m really happy with the progress over the last week because it makes Micro.blog-hosted sites more useful. As I mentioned in my IndieWeb Summit keynote, the business model for Micro.blog is aligned with what users need. If you pay for Micro.blog hosting, we\u2019ll keep making it better without worrying about ads or other user-hostile distractions.</p>",
"text": "After posting about my time at IndieWeb Summit and the new IndieBookClub support, let me give some more details on what IndieAuth means for Micro.blog. I spent the second day of IndieWeb Summit working on this, and it has now been rolled out to all Micro.blog users. (If you haven\u2019t posted in the last few days, after your next post your microblog will be updated with the new authorization endpoints.)\n\nIndieAuth lets you sign in to other apps using your own domain name. If Micro.blog is hosting a blog for you, you can use that custom domain or your subdomain like yourname.micro.blog to sign in.\n\nWhile this was possible before with extra configuration to delegate auth to another service, Micro.blog can now be an IndieAuth provider on its own. It\u2019s much easier for IndieWeb apps to work with Micro.blog.\n\nHere are some apps that work great with Micro.blog:\n\nQuill: web-based interface for posting to your microblog.\nOwnYourGram: automatically post your Instagram photos to your microblog.\nOwnYourSwarm: automatically post your Swarm check-ins to your microblog.\nIndieBookClub: post what books you're reading or want to read.\nOmnibear: Chrome or Firefox extension for quick posting.\nIndieWeb Ring: wait\u2026 what?\nI\u2019m really happy with the progress over the last week because it makes Micro.blog-hosted sites more useful. As I mentioned in my IndieWeb Summit keynote, the business model for Micro.blog is aligned with what users need. If you pay for Micro.blog hosting, we\u2019ll keep making it better without worrying about ads or other user-hostile distractions."
},
"published": "2018-07-02T08:24:37-05:00",
"_id": "570886",
"_source": "12",
"_is_read": true
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://www.manton.org/",
"photo": null
},
"url": "https://www.manton.org/2018/06/30/indiebookclub.html",
"name": "IndieBookClub",
"content": {
"html": "<p>As I mentioned in <a href=\"http://www.manton.org/2018/06/indieweb-summit-2018-wrap-up.html\">my IndieWeb Summit wrap-up</a>, I added support for <a href=\"https://indiebookclub.biz/\">IndieBookClub</a> while in Portland. IndieBookClub is a little like Goodreads, but built on standards like Microformats and Micropub so that you can post what you\u2019re reading to your own blog.</p>\n\n<p>Now that I\u2019m back in Austin, I\u2019ve tweaked the behavior to be smarter about recognizing the ISBN that IndieBookClub sends to Micro.blog. Posts from IndieBookClub also get the \ud83d\udcda emoji added automatically so that they show up in the <a href=\"https://micro.blog/discover/books\">books Discover section</a> on Micro.blog. Here\u2019s a screenshot of what posts look like on your Micro.blog-hosted site:</p>\n\n<p><img src=\"http://manton.micro.blog/uploads/2018/b6a848e9c9.jpg\" width=\"593\" height=\"321\" alt=\"Screenshot of IndieBookClub post\" /></p>\n\n<p>If the ISBN is specified, Micro.blog will redirect the link to Amazon, although we may change that in the future. And it\u2019s just a regular blog post, so you can always edit it using Markdown in Micro.blog.</p>",
"text": "As I mentioned in my IndieWeb Summit wrap-up, I added support for IndieBookClub while in Portland. IndieBookClub is a little like Goodreads, but built on standards like Microformats and Micropub so that you can post what you\u2019re reading to your own blog.\n\nNow that I\u2019m back in Austin, I\u2019ve tweaked the behavior to be smarter about recognizing the ISBN that IndieBookClub sends to Micro.blog. Posts from IndieBookClub also get the \ud83d\udcda emoji added automatically so that they show up in the books Discover section on Micro.blog. Here\u2019s a screenshot of what posts look like on your Micro.blog-hosted site:\n\n\n\nIf the ISBN is specified, Micro.blog will redirect the link to Amazon, although we may change that in the future. And it\u2019s just a regular blog post, so you can always edit it using Markdown in Micro.blog."
},
"published": "2018-06-30T14:06:44-05:00",
"_id": "570889",
"_source": "12",
"_is_read": true
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://www.manton.org/",
"photo": null
},
"url": "https://www.manton.org/2018/06/30/indieweb-summit-wrapup.html",
"name": "IndieWeb Summit 2018 wrap-up",
"content": {
"html": "<p>Last week I was in Portland for <a href=\"https://2018.indieweb.org/\">IndieWeb Summit</a>. This was only my second IndieWeb conference (the first was IndieWebCamp in Austin). I had a great time in Portland and got even more than I expected out of IndieWeb Summit.</p>\n\n<p>The first day was short keynotes and sessions led by attendees on a range of topics. Jean and I talked about our experience and goals with Micro.blog in reaching even more mainstream users. I went to sessions on Microformats, timeline algorithms, code libraries for common IndieWeb building blocks, and Microsub. Some of this carried over to the beginning of the next day, including Aaron Parecki leading a discussion about IndieAuth.</p>\n\n<p>We held <a href=\"http://macgenie.micro.blog/2018/06/26/micro-meetup-a.html\">a Micro.blog meetup at Von Ebert Brewing</a> after the first day wrapped up. Thanks everyone for joining us!</p>\n\n<p>Most of the second day was a hack day to work on our own projects, and at the end of the day everyone could present what they had worked on. I was so impressed with what people had come up with, whether that was improvements to their own site or prototypes for new tools.</p>\n\n<p>It turned out that having this dedicated time was exactly what I needed to turn Micro.blog into an IndieAuth provider. This means that Micro.blog no longer needs to delegate to Twitter or GitHub for authorization when someone is using an IndieWeb posting tool like OwnYourGram or Quill. Users can instead authorize directly with their Micro.blog account. I also added support for the <code>summary</code> fallback parameter in Micropub, which makes Micro.blog compatible with <a href=\"https://indiebookclub.biz/\">IndieBookClub</a>.</p>\n\n<p>In the morning before I left Portland, I interviewed Tantek and Aaron for my upcoming book Indie Microblogging. We had a great conversation on the founding of IndieWebCamp, the accomplishments and changes in the community, and where everything is going from here.</p>\n\n<p><img src=\"http://manton.micro.blog/uploads/2018/6f65264901.jpg\" width=\"300\" height=\"300\" alt=\"Coava Coffee\" /><img src=\"http://manton.micro.blog/uploads/2018/03bc2cf6d4.jpg\" width=\"300\" height=\"300\" alt=\"Portland bridge\" /></p>\n\n<p>Portland was great. For this trip I opted for an Airbnb close to the IndieWeb Summit venue. It was also just a block from <a href=\"https://www.coavacoffee.com/\">Coava Coffee</a>, where I spent a couple mornings catching up on work. I hope to be back in Portland for IndieWeb Summit next year.</p>",
"text": "Last week I was in Portland for IndieWeb Summit. This was only my second IndieWeb conference (the first was IndieWebCamp in Austin). I had a great time in Portland and got even more than I expected out of IndieWeb Summit.\n\nThe first day was short keynotes and sessions led by attendees on a range of topics. Jean and I talked about our experience and goals with Micro.blog in reaching even more mainstream users. I went to sessions on Microformats, timeline algorithms, code libraries for common IndieWeb building blocks, and Microsub. Some of this carried over to the beginning of the next day, including Aaron Parecki leading a discussion about IndieAuth.\n\nWe held a Micro.blog meetup at Von Ebert Brewing after the first day wrapped up. Thanks everyone for joining us!\n\nMost of the second day was a hack day to work on our own projects, and at the end of the day everyone could present what they had worked on. I was so impressed with what people had come up with, whether that was improvements to their own site or prototypes for new tools.\n\nIt turned out that having this dedicated time was exactly what I needed to turn Micro.blog into an IndieAuth provider. This means that Micro.blog no longer needs to delegate to Twitter or GitHub for authorization when someone is using an IndieWeb posting tool like OwnYourGram or Quill. Users can instead authorize directly with their Micro.blog account. I also added support for the summary fallback parameter in Micropub, which makes Micro.blog compatible with IndieBookClub.\n\nIn the morning before I left Portland, I interviewed Tantek and Aaron for my upcoming book Indie Microblogging. We had a great conversation on the founding of IndieWebCamp, the accomplishments and changes in the community, and where everything is going from here.\n\n\n\nPortland was great. For this trip I opted for an Airbnb close to the IndieWeb Summit venue. It was also just a block from Coava Coffee, where I spent a couple mornings catching up on work. I hope to be back in Portland for IndieWeb Summit next year."
},
"published": "2018-06-30T13:34:01-05:00",
"_id": "570890",
"_source": "12",
"_is_read": true
}
Slow start for me this morning. Luckily my Airbnb left a Stumptown cold brew coffee in the fridge. Catching up on support email before heading over to IndieWeb Summit day 2.
{
"type": "entry",
"author": {
"name": null,
"url": "https://www.manton.org/",
"photo": null
},
"url": "https://www.manton.org/2018/06/27/slow-start-for.html",
"content": {
"html": "<p>Slow start for me this morning. Luckily my Airbnb left a Stumptown cold brew coffee in the fridge. Catching up on support email before heading over to <a href=\"https://2018.indieweb.org/\">IndieWeb Summit</a> day 2.</p>",
"text": "Slow start for me this morning. Luckily my Airbnb left a Stumptown cold brew coffee in the fridge. Catching up on support email before heading over to IndieWeb Summit day 2."
},
"published": "2018-06-27T10:29:23-05:00",
"_id": "570892",
"_source": "12",
"_is_read": true
}
IndieAuth, the extension to OAuth 2.0, was developed by Aaron Parecki and implemented by multiple people in the IndieWeb community, including myself.
The problem has been that people conflated it with the service Aaron created as a reference implementation, which implemented IndieAuth for people who didn’t have it by using the OAuth services of sites like Twitter and Github to bootstrap the service.
Aaron succeeds here in finally conveying a point it took me a long time to understand, and partially only by reading and implementing one of these.
Was pleased to see the founder of Home Assistant, a product I use, tweeting that he would adopt this in that product. Looking forward to seeing what people come up with.
{
"type": "entry",
"published": "2018-07-08T23:12:52-04:00",
"url": "https://david.shanske.com/2018/07/08/2007/",
"in-reply-to": [
"https://aaronparecki.com/2018/07/07/7/oauth-for-the-open-web"
],
"content": {
"text": "IndieAuth, the extension to OAuth 2.0, was developed by Aaron Parecki and implemented by multiple people\u00a0 in the IndieWeb community, including myself.\nThe problem has been that people conflated it with the service Aaron created as a reference implementation, which implemented IndieAuth for people who didn\u2019t have it by using the OAuth services of sites like Twitter and Github to bootstrap the service.\nAaron succeeds here in finally conveying a point it took me a long time to understand, and partially only by reading and implementing one of these.\nWas pleased to see the founder of Home Assistant, a product I use, tweeting that he would adopt this in that product. Looking forward to seeing what people come up with.",
"html": "IndieAuth, the extension to OAuth 2.0, was developed by Aaron Parecki and implemented by multiple people\u00a0 in the IndieWeb community, including myself.\n<p>The problem has been that people conflated it with the service Aaron created as a reference implementation, which implemented IndieAuth for people who didn\u2019t have it by using the OAuth services of sites like Twitter and Github to bootstrap the service.</p>\n<p>Aaron succeeds here in finally conveying a point it took me a long time to understand, and partially only by reading and implementing one of these.</p>\n<p>Was pleased to see the founder of Home Assistant, a product I use, <a href=\"https://twitter.com/balloob/status/1015740688695250946\">tweeting</a> that he would adopt this in that product. Looking forward to seeing what people come up with.</p>"
},
"author": {
"type": "card",
"name": "David Shanske",
"url": "https://david.shanske.com/",
"photo": "https://aperture-proxy.p3k.io/6f1f841c095626a5e52a3b86849e757329773a28/68747470733a2f2f64617669642e7368616e736b652e636f6d2f77702d636f6e74656e742f75706c6f6164732f6176617461722d707269766163792f63616368652f67726176617461722f322f632f326362316638616664396338643362363436623430373163356564383837633937306438316436323565656564383765343437373036393430653263343033642d3132352e706e67"
},
"refs": {
"https://aaronparecki.com/2018/07/07/7/oauth-for-the-open-web": {
"type": "entry",
"url": "https://aaronparecki.com/2018/07/07/7/oauth-for-the-open-web",
"name": "OAuth for the Open Web",
"author": {
"type": "card",
"name": "Aaron Parecki",
"url": "https://aaronparecki.com/",
"photo": "https://aaronparecki.com/images/profile.jpg"
}
}
},
"_id": "570713",
"_source": "5",
"_is_read": true
}
I think that's all the brain power I've got for today. Feels good to have another IndieAuth server implementation in the wild now tho!
{
"type": "entry",
"published": "2018-07-08T18:10:04-07:00",
"url": "https://aaronparecki.com/2018/07/08/17/",
"content": {
"text": "I think that's all the brain power I've got for today. Feels good to have another IndieAuth server implementation in the wild now tho!"
},
"author": {
"type": "card",
"name": "Aaron Parecki",
"url": "https://aaronparecki.com/",
"photo": "https://aperture-media.p3k.io/aaronparecki.com/2b8e1668dcd9cfa6a170b3724df740695f73a15c2a825962fd0a0967ec11ecdc.jpg"
},
"_id": "569992",
"_source": "16",
"_is_read": true
}
I just implemented an IndieAuth server for Aperture, which sounds crazy but it's actually pretty cool. Now you can log in to apps like https://indiepaper.io and they can post content directly into a private channel!
If you have an Aperture account, try logging in to Quill using https://aperture.p3k.io as your URL. Here's a little demo of it in action!
{
"type": "entry",
"published": "2018-07-08T16:29:06-07:00",
"url": "https://aaronparecki.com/2018/07/08/15/aperture-indieauth",
"category": [
"p3k",
"indieauth"
],
"photo": [
"https://aperture-media.p3k.io/aaronparecki.com/11a0975c0afde82ff1fdbb303efe1e6b2b464096e8d9d297d33656b8c4d5b37b.png"
],
"video": [
"https://aperture-media.p3k.io/aaronparecki.com/24eadfbe365c654a9b9ff565b7284b0b2e01713ac22130a814e041c9daa72696.mp4"
],
"content": {
"text": "I just implemented an IndieAuth server for Aperture, which sounds crazy but it's actually pretty cool. Now you can log in to apps like https://indiepaper.io and they can post content directly into a private channel! \n\nIf you have an Aperture account, try logging in to Quill using https://aperture.p3k.io as your URL. Here's a little demo of it in action!",
"html": "I just implemented an IndieAuth server for Aperture, which sounds crazy but it's actually pretty cool. Now you can log in to apps like <a href=\"https://indiepaper.io\">https://indiepaper.io</a> and they can post content directly into a private channel! <br /><br />If you have an Aperture account, try logging in to Quill using <a href=\"https://aperture.p3k.io\">https://aperture.p3k.io</a> as your URL. Here's a little demo of it in action!"
},
"author": {
"type": "card",
"name": "Aaron Parecki",
"url": "https://aaronparecki.com/",
"photo": "https://aperture-media.p3k.io/aaronparecki.com/2b8e1668dcd9cfa6a170b3724df740695f73a15c2a825962fd0a0967ec11ecdc.jpg"
},
"_id": "569737",
"_source": "16",
"_is_read": true
}
Yeah, I think it’s an incredibly useful feature. I think @manton likes the name Favorite, but I do feel like your option #2, renaming it is the best option. I think renaming it to Bookmark explains more of the purpose, is clearer that it doesn’t send information to others, and it already plays nice with the bookmark-of micropub vocabulary, so if there was gonna be a change I think that’s the best one 🙂
{
"type": "entry",
"published": "2018-07-07T23:20:51-04:00",
"summary": "Yeah, I think it\u2019s an incredibly useful feature. I think @manton likes the name Favorite, but I do feel like your option #2, renaming it is the best option. I think renaming it to Bookmark explains more of the purpose, is clearer that it doesn\u2019t send information to others, and it already plays nice with the bookmark-of micropub vocabulary, so if there was gonna be a change I think that\u2019s the best one \ud83d\ude42",
"url": "https://eddiehinkle.com/2018/07/07/28/reply/",
"category": [
"2"
],
"in-reply-to": [
"https://www.burk.io/2018/07/07/202918.html"
],
"content": {
"text": "Yeah, I think it\u2019s an incredibly useful feature. I think @manton likes the name Favorite, but I do feel like your option #2, renaming it is the best option. I think renaming it to Bookmark explains more of the purpose, is clearer that it doesn\u2019t send information to others, and it already plays nice with the bookmark-of micropub vocabulary, so if there was gonna be a change I think that\u2019s the best one \ud83d\ude42",
"html": "<p>Yeah, I think it\u2019s an incredibly useful feature. I think <a href=\"https://eddiehinkle.com/timeline/undefined\">@manton</a> likes the name Favorite, but I do feel like your option <a href=\"https://eddiehinkle.com/tag/2/\">#2</a>, renaming it is the best option. I think renaming it to Bookmark explains more of the purpose, is clearer that it doesn\u2019t send information to others, and it already plays nice with the bookmark-of micropub vocabulary, so if there was gonna be a change I think that\u2019s the best one \ud83d\ude42</p>"
},
"author": {
"type": "card",
"name": "Eddie Hinkle",
"url": "https://eddiehinkle.com/",
"photo": "https://aperture-proxy.p3k.io/cc9591b69c2c835fa2c6e23745b224db4b4b431f/68747470733a2f2f656464696568696e6b6c652e636f6d2f696d616765732f70726f66696c652e6a7067"
},
"refs": {
"https://www.burk.io/2018/07/07/202918.html": {
"type": "entry",
"url": "https://www.burk.io/2018/07/07/202918.html",
"name": "https://www.burk.io/2018/07/07/202918.html"
}
},
"_id": "564491",
"_source": "226",
"_is_read": true
}
Great suggestion. I am debating either including mf2py as a dependency, or just using https://python.microformats.io as a web service like I do with Mercury, so I don't have to worry about keeping it up to date.
I will likely want to take the output from mf2py and strip out everything but the basics. Any directional feedback is, of course, welcome!
{
"type": "entry",
"published": "2018-07-07T20:58:07+00:00",
"url": "https://cleverdevil.io/2018/great-suggestion-i-am-debating-either-including-mf2py-as-a",
"in-reply-to": [
"https://github.com/cleverdevil/indiepaper/issues/2"
],
"content": {
"text": "Great suggestion. I am debating either including mf2py as a dependency, or just using\u00a0https://python.microformats.io as a web service like I do with Mercury, so I don't have to worry about keeping it up to date.I will likely want to take the output from mf2py and strip out everything but the basics. Any directional feedback is, of course, welcome!",
"html": "<p>Great suggestion. I am debating either including mf2py as a dependency, or just using\u00a0<a href=\"https://python.microformats.io\">https://python.microformats.io</a> as a web service like I do with Mercury, so I don't have to worry about keeping it up to date.</p><p>I will likely want to take the output from mf2py and strip out everything but the basics. Any directional feedback is, of course, welcome!</p>\n<p><a href=\"https://brid.gy/publish/github\"></a></p>"
},
"author": {
"type": "card",
"name": "Jonathan LaCour",
"url": "https://cleverdevil.io/profile/cleverdevil",
"photo": "https://aperture-proxy.p3k.io/77e5d6e5871324c43aebf2e3e7a5553e14578f66/68747470733a2f2f636c65766572646576696c2e696f2f66696c652f66646263373639366135663733383634656131316138323863383631653133382f7468756d622e6a7067"
},
"_id": "562165",
"_source": "71",
"_is_read": true
}
If you’re familiar with OAuth, this introduction to IndieAuth walks through the process of how auth for the open web works. Really happy that Micro.blog supports this now.
{
"type": "entry",
"author": {
"name": "manton",
"url": "http://www.manton.org",
"photo": null
},
"url": "http://www.manton.org/2018/07/7056.html",
"content": {
"html": "<p>If you\u2019re familiar with OAuth, <a href=\"https://aaronparecki.com/2018/07/07/7/oauth-for-the-open-web\">this introduction to IndieAuth</a> walks through the process of how auth for the open web works. Really happy that Micro.blog supports this now.</p>",
"text": "If you\u2019re familiar with OAuth, this introduction to IndieAuth walks through the process of how auth for the open web works. Really happy that Micro.blog supports this now."
},
"published": "2018-07-07T20:41:12+00:00",
"updated": "2018-07-07T20:41:12+00:00",
"_id": "560818",
"_source": "12",
"_is_read": true
}
I added experimental support for IndieAuth in Indiepaper today. Test it out here – https://www.indiepaper.io/indieauth.html. Once authenticated, you get an automatically generated bookmarklet and a button to click for automatically configuring Indiepaper for macOS.
{
"type": "entry",
"published": "2018-07-07T20:11:16+00:00",
"url": "https://cleverdevil.io/2018/i-added-experimental-support-for-indieauth-in",
"syndication": [
"https://twitter.com/cleverdevil/status/1015689745228279811"
],
"content": {
"text": "I added experimental support for IndieAuth in Indiepaper today. Test it out here \u2013 https://www.indiepaper.io/indieauth.html. Once authenticated, you get an automatically generated bookmarklet and a button to click for automatically configuring Indiepaper for macOS.",
"html": "I added experimental support for IndieAuth in Indiepaper today. Test it out here \u2013 <a href=\"https://www.indiepaper.io/indieauth.html\">https://www.indiepaper.io/indieauth.html</a>. Once authenticated, you get an automatically generated bookmarklet and a button to click for automatically configuring Indiepaper for macOS."
},
"author": {
"type": "card",
"name": "Jonathan LaCour",
"url": "https://cleverdevil.io/profile/cleverdevil",
"photo": "https://aperture-proxy.p3k.io/77e5d6e5871324c43aebf2e3e7a5553e14578f66/68747470733a2f2f636c65766572646576696c2e696f2f66696c652f66646263373639366135663733383634656131316138323863383631653133382f7468756d622e6a7067"
},
"_id": "560797",
"_source": "71",
"_is_read": true
}
If I sent a reply into micro.blog via webmention. If I make a typo and send a second webmention, rather than using the permalink of the webmention to de-duplicate the post and just update the existing post, it creates a brand new second post with the new post content creating duplicate posts.
{
"type": "entry",
"published": "2018-07-07T14:11:11-04:00",
"summary": "If I sent a reply into micro.blog via webmention. If I make a typo and send a second webmention, rather than using the permalink of the webmention to de-duplicate the post and just update the existing post, it creates a brand new second post with the new post content creating duplicate posts.",
"url": "https://eddiehinkle.com/2018/07/07/13/reply/",
"in-reply-to": [
"https://github.com/microdotblog/issues"
],
"name": "Du-dupe replies received via webmention",
"author": {
"type": "card",
"name": "Eddie Hinkle",
"url": "https://eddiehinkle.com/",
"photo": "https://aperture-proxy.p3k.io/cc9591b69c2c835fa2c6e23745b224db4b4b431f/68747470733a2f2f656464696568696e6b6c652e636f6d2f696d616765732f70726f66696c652e6a7067"
},
"refs": {
"https://github.com/microdotblog/issues": {
"type": "entry",
"url": "https://github.com/microdotblog/issues",
"name": "https://github.com/microdotblog/issues"
}
},
"_id": "559884",
"_source": "226",
"_is_read": true
}
{
"type": "entry",
"published": "2018-07-07T09:30:27-07:00",
"url": "https://aaronparecki.com/2018/07/07/7/oauth-for-the-open-web",
"featured": "https://aaronparecki.com/2018/07/07/7/image-1.jpg",
"category": [
"indieauth",
"oauth",
"oauth2",
"indieweb"
],
"name": "OAuth for the Open Web",
"content": {
"text": "OAuth has become the de facto standard for authorization and authentication on the web. Nearly every company with an API used by third party developers has implemented OAuth to enable people to build apps on top of it.\nWhile OAuth is a great framework for this, the way it has ended up being used is much more centralized and closed than prior efforts like OpenID 1. Every service that spins up an OAuth-enabled API ends up being its own isolated system. For example, if I want to build an app that can read someone's step count from FitBit, I have to first go register as a developer on FitBit's website in order to get API keys to use with their OAuth API.\u00a0\nThis works okay for major services like Google, Twitter, Facebook, and even FitBit, but breaks down when you start to consider use cases like having someone's personal WordPress blog be its own OAuth server. If I want to build an app that lets you upload photos to your WordPress site, I'm obviously not going to be able to register for API keys on everyone's own WordPress installations. Enabling third party clients to be built against systems like WordPress or Mastodon opens up a huge possibility for some really interesting things. The trick is always how do these apps authenticate the user or obtain a token they can use to access those APIs.\nThis post details a few specific challenges with OAuth preventing it from being used by independent websites, as well as the solutions to each.\n\nClient Registration\nThe first major hurdle to overcome is the need for the developer to register to get API keys for the service. In a world where everyone's own website is its own OAuth server, it's obviously not practical to have an app developer register API keys at each.\nIn OAuth, client registration gives us a few specific things:\n\n Provides a unique ID that is used to identify the app throughout the OAuth process, called the client ID\n \n\n Provides a place to enter the name and icon for the app which is displayed during login\n Registers one or more redirect URLs for security\n For \"confidential clients\" (web server apps), registration also provides the client with a client secret\nNote that in traditional OAuth, client secrets are not used by mobile apps or JavaScript apps, and OAuth servers will often not even issue secrets to those types of apps. Since we're trying to avoid registration entirely, we can also just avoid using client secrets at all, and leverage the same protections OAuth already has in place for clients that can't use a secret.\nIn order to avoid registration, we need a solution for the first three bullet points above.\nClient ID: Every application needs a unique identifier. If we're talking about turning every website into an OAuth provider, we need a way to have globally unique identifiers for every OAuth app. It turns out we already have a mechanism for this: URLs! In this Open Web version of OAuth, client IDs can be the application's URL. For web-based apps, this is straightforward, as it's simply the website the app is running on. For native apps, this can be the application's \"about\" page.\nApplication name and icon: Since the application's client ID is a URL, we can assume every application has a web page that talks about it, and treat that web page as the place the client defines its own metadata like name and icon. A simple way to accomplish this is with Microformats, so that the application's web page just needs to add a couple classes around the name and icon of the app. This is currently documented and implemented as the h-app microformat.\nRedirect URL registration: This one is a bit more subtle. The purpose of redirect URL registration is to prevent an attacker from tricking an authorization server into sending authorization codes to the attacker. This becomes especially important when we aren't using client secrets. The trick is that since client IDs are already URLs, we can shortcut the normal registration process by declaring a rule that redirect URLs have to be on the same domain as the client ID. This way, we can avoid a situation where an application claiming to be good.example.com sets a redirect URL to attacker.example.org and steals the authorization code. The only way to get the authorization code to attacker.example.org would be to set the client ID to that domain as well, which a user would hopefully notice.\n\nUser Accounts\nThere are two different situations to consider with regards to user accounts: authentication and authorization. Authentication is the process of proving the identity of the person signing in. Authorization is how an application obtains permission to do something to someone's account.\nWhen we talk about authentication, we are talking about wanting to allow an unknown user to identify themselves to the site they're logging in to. Common examples of this are using your email address as your identity to sign in to a website. You bring an existing identity (your email address) and then authenticate (usually by clicking a link that was sent to your email). The original version of OpenID was created to solve this problem on the web. People identified themselves with a URL, which they were able to prove they controlled using OpenID. This allows a new user to log in to a site without needing a prior relationship with the site.\nWhen we talk about authorization, the situation is subtly different. In this case, we're talking about a user of a website wanting to give permission to a third-party app to access some part of their account. We're very used to this pattern now, which is the typical OAuth use case of granting an application the ability to access your Google Calendar, or logging in to a third party Twitter app.\nAuthorization: There isn't really a challenge unique OAuth on the Open Web with regards to authorization. Once the client registration problem is solved, everything else falls into place nicely. It is assumed that users are authorizing an application to access an account they already have, so the application will just end up with an access token that works with their existing account.\nAuthentication: Where we need to define some new behavior is talking about authentication. In this case, we want users to be able to bring an existing identity and use it to log in to other places. This means we need a way to uniquely identify users across the entire web. We can again use URLs as the solution! Every user is identified by a URL. This can be a short URL like someone's domain name, e.g. https://aaronparecki.com/, or for a site with multiple users, can be a URL that contains a path specifying a particular user on the site, e.g. https://github.com/aaronpk.\u00a0\n\nDiscovery\nWith traditional OAuth services, discovery is not needed since the application author knows which OAuth server they're talking to before they start building the app. There is typically a \"Sign in with ____\" button in the application that begins the authorization process. In the case of using OAuth for authentication, the common pattern is to include buttons for several common \"social login\" providers such as Facebook, Google, Twitter and LinkedIn. Before the \"social login\" space essentially consolidated to these four, there were sometimes a dozen of these buttons on an application's login page, which eventually became known as the \"NASCAR problem\".\nIn a world where every WordPress or Gitlab site is its own OAuth provider, there obviously can't be a button for each on a login screen. Instead, we need to find out from the user which server to use to authenticate them.\u00a0\nSince we previously stated that every user identifier is a URL, we can ask the user to enter their URL in the sign-in screen, and then fetch that URL and discover their authorization server from there.\nOnce we've found the user's authorization endpoint, we can start a normal OAuth request and send them to their server to authenticate. When the server redirects back to the application, it will go and verify the authorization code with their authorization endpoint just like normally happens with OAuth.\n\nKnowing Who Logged In\nWhile knowing any user identity information is technically not part of OAuth, we do need the server to return a user identifier when using OAuth for authentication. In practice, most applications also want at least a unique user identifier in the authorization case as well.\nWe've previously said that user identifiers are URLs, which solves the global user identity problem, and gives us a mechanism to discover the user's OAuth server. So all we need is a way to return this information to the application after the user has authenticated.\u00a0\nOAuth gives us an easy opportunity to return this to the application: in the access token response when the application sends the authorization code to obtain an access token. The server can at that point return the full user identifier of the user that logged in. As long as the domain name matches the domain that the user entered at the start, the application can consider it successful. This also gives the authorization server the opportunity to canonicalize the user identifier, correcting \"http\" to \"https\", or adding a path component to the user's profile URL.\n\nLet's do this!\nBy now, hopefully you're thinking \"this sounds great, Aaron, someone should write this up as a OAuth extension!\" I'm glad you asked!\nThe IndieAuth spec, an OAuth 2.0 extensionEarlier this year, I wrote this all up as an extension to OAuth 2.0, called IndieAuth. IndieAuth encapsulates these small additions needed for OAuth 2.0 to work in the Open Web.\nDespite this spec being published in January, it has actually been implemented for several years before that. There are many implementations of this extension on the server side, everything from standalone authorization server projects, to a WordPress\u00a0plugin, and it's even implemented by a commercial service, Micro.blog. As far as consuming apps, nearly every Micropub app has implemented this for logging users in.\nFor further details on implementing this extension, there are several guides available depending on whether you're writing a client, a server, or just part of a server.\nAuthenticating users with IndieAuth\n Obtaining an access token with IndieAuth\n Creating an Authorization Endpoint\n Creating a Token Endpoint\nThere are a few existing open source projects you can use to get started if you don't want to write your own!\n\nselfauth - a standalone authorization server using a simple password login\n \nIndieAuth for WordPress - a plugin that turns your WordPress install into an OAuth 2.0 server\n \nAcquiescence - an authorization endpoint written in Ruby that authenticates users via GitHub\nFor further reading, check out the IndieAuth spec.\u00a0Feel free to drop in to the IndieWeb chat if you'd like to talk about this, or you can reach me on Twitter\u00a0or from my website.",
"html": "<img src=\"https://aperture-media.p3k.io/aaronparecki.com/063490713e5cecd672d9688e83f4edb016e4ef7e0d1b6cd1fa3efd1149d27047.jpg\" alt=\"\" class=\"u-featured\" /><p>OAuth has become the de facto standard for authorization and authentication on the web. Nearly every company with an API used by third party developers has implemented OAuth to enable people to build apps on top of it.</p>\n<p>While OAuth is a great framework for this, the way it has ended up being used is much more centralized and closed than prior efforts like OpenID 1. Every service that spins up an OAuth-enabled API ends up being its own isolated system. For example, if I want to build an app that can read someone's step count from FitBit, I have to first go register as a developer on FitBit's website in order to get API keys to use with their OAuth API.\u00a0</p>\n<p>This works okay for major services like Google, Twitter, Facebook, and even FitBit, but breaks down when you start to consider use cases like having someone's personal WordPress blog be its own OAuth server. If I want to build an app that lets you upload photos to your WordPress site, I'm obviously not going to be able to register for API keys on everyone's own WordPress installations. Enabling third party clients to be built against systems like WordPress or Mastodon opens up a huge possibility for some really interesting things. The trick is always how do these apps authenticate the user or obtain a token they can use to access those APIs.</p>\n<p>This post details a few specific challenges with OAuth preventing it from being used by independent websites, as well as the solutions to each.</p>\n\n<h2>Client Registration</h2>\n<p>The first major hurdle to overcome is the need for the developer to register to get API keys for the service. In a world where everyone's own website is its own OAuth server, it's obviously not practical to have an app developer register API keys at each.</p>\n<p>In OAuth, client registration gives us a few specific things:</p>\n<ul><li>\n Provides a unique ID that is used to identify the app throughout the OAuth process, called the client ID\n <br /></li>\n <li>Provides a place to enter the name and icon for the app which is displayed during login</li>\n <li>Registers one or more redirect URLs for security</li>\n <li>For \"confidential clients\" (web server apps), registration also provides the client with a client secret</li>\n</ul><p>Note that in traditional OAuth, client secrets are not used by mobile apps or JavaScript apps, and OAuth servers will often not even issue secrets to those types of apps. Since we're trying to avoid registration entirely, we can also just avoid using client secrets at all, and leverage the same protections OAuth already has in place for clients that can't use a secret.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/b31e8bcf790aa2b853eee68cf80e8b0e61994aaf09c727a83c55466089a1b217.png\" alt=\"\" /><p>In order to avoid registration, we need a solution for the first three bullet points above.</p>\n<p><b>Client ID</b>: Every application needs a unique identifier. If we're talking about turning every website into an OAuth provider, we need a way to have globally unique identifiers for every OAuth app. It turns out we already have a mechanism for this: URLs! In this Open Web version of OAuth, client IDs can be the application's URL. For web-based apps, this is straightforward, as it's simply the website the app is running on. For native apps, this can be the application's \"about\" page.</p>\n<p><b>Application name and icon</b>: Since the application's client ID is a URL, we can assume every application has a web page that talks about it, and treat that web page as the place the client defines its own metadata like name and icon. A simple way to accomplish this is with Microformats, so that the application's web page just needs to add a couple classes around the name and icon of the app. This is currently documented and implemented as the <a href=\"https://indieweb.org/h-app\">h-app</a> microformat.</p>\n<p><b>Redirect URL registration</b>: This one is a bit more subtle. The purpose of redirect URL registration is to prevent an attacker from tricking an authorization server into sending authorization codes to the attacker. This becomes especially important when we aren't using client secrets. The trick is that since client IDs are already URLs, we can shortcut the normal registration process by declaring a rule that redirect URLs have to be on the same domain as the client ID. This way, we can avoid a situation where an application claiming to be good.example.com sets a redirect URL to attacker.example.org and steals the authorization code. The only way to get the authorization code to attacker.example.org would be to set the client ID to that domain as well, which a user would hopefully notice.</p>\n\n<h2>User Accounts</h2>\n<p>There are two different situations to consider with regards to user accounts: <i>authentication</i> and <i>authorization</i>. Authentication is the process of proving the identity of the person signing in. Authorization is how an application obtains permission to do something to someone's account.</p>\n<p>When we talk about <i>authentication</i>, we are talking about wanting to allow an unknown user to identify themselves to the site they're logging in to. Common examples of this are using your email address as your identity to sign in to a website. You bring an existing identity (your email address) and then authenticate (usually by clicking a link that was sent to your email). The original version of OpenID was created to solve this problem on the web. People identified themselves with a URL, which they were able to prove they controlled using OpenID. This allows a new user to log in to a site without needing a prior relationship with the site.</p>\n<p>When we talk about <i>authorization</i>, the situation is subtly different. In this case, we're talking about a user of a website wanting to give permission to a third-party app to access some part of their account. We're very used to this pattern now, which is the typical OAuth use case of granting an application the ability to access your Google Calendar, or logging in to a third party Twitter app.</p>\n<p><b>Authorization</b>: There isn't really a challenge unique OAuth on the Open Web with regards to authorization. Once the client registration problem is solved, everything else falls into place nicely. It is assumed that users are authorizing an application to access an account they already have, so the application will just end up with an access token that works with their existing account.</p>\n<p><b>Authentication</b>: Where we need to define some new behavior is talking about authentication. In this case, we want users to be able to bring an existing identity and use it to log in to other places. This means we need a way to uniquely identify users across the entire web. We can again use URLs as the solution! Every user is identified by a URL. This can be a short URL like someone's domain name, e.g. <b>https://aaronparecki.com/</b>, or for a site with multiple users, can be a URL that contains a path specifying a particular user on the site, e.g. <b>https://github.com/aaronpk</b>.\u00a0</p>\n\n<h2>Discovery</h2>\n<p>With traditional OAuth services, discovery is not needed since the application author knows which OAuth server they're talking to before they start building the app. There is typically a \"Sign in with ____\" button in the application that begins the authorization process. In the case of using OAuth for authentication, the common pattern is to include buttons for several common \"social login\" providers such as Facebook, Google, Twitter and LinkedIn. Before the \"social login\" space essentially consolidated to these four, there were sometimes a dozen of these buttons on an application's login page, which eventually became known as the \"NASCAR problem\".</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/53b04744ebfaec38d6b6b4b65fb19b217a91f712d489f19ec85be8e2f2e201c5.png\" alt=\"\" /><p>In a world where every WordPress or Gitlab site is its own OAuth provider, there obviously can't be a button for each on a login screen. Instead, we need to find out from the user which server to use to authenticate them.\u00a0</p>\n<p>Since we previously stated that every user identifier is a URL, we can ask the user to enter their URL in the sign-in screen, and then fetch that URL and discover their authorization server from there.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/61b1c30b21fa6ac074564d906b4d490faf5523af6aa6a70d19076093e19c2c13.png\" alt=\"\" /><p>Once we've found the user's authorization endpoint, we can start a normal OAuth request and send them to their server to authenticate. When the server redirects back to the application, it will go and verify the authorization code with their authorization endpoint just like normally happens with OAuth.</p>\n\n<h2>Knowing Who Logged In</h2>\n<p>While knowing any user identity information is technically not part of OAuth, we do need the server to return a user identifier when using OAuth for authentication. In practice, most applications also want at least a unique user identifier in the authorization case as well.</p>\n<p>We've previously said that user identifiers are URLs, which solves the global user identity problem, and gives us a mechanism to discover the user's OAuth server. So all we need is a way to return this information to the application after the user has authenticated.\u00a0</p>\n<p>OAuth gives us an easy opportunity to return this to the application: in the access token response when the application sends the authorization code to obtain an access token. The server can at that point return the full user identifier of the user that logged in. As long as the domain name matches the domain that the user entered at the start, the application can consider it successful. This also gives the authorization server the opportunity to canonicalize the user identifier, correcting \"http\" to \"https\", or adding a path component to the user's profile URL.</p>\n\n<h2>Let's do this!</h2>\n<p>By now, hopefully you're thinking \"this sounds great, Aaron, someone should write this up as a OAuth extension!\" I'm glad you asked!</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/861471899aba530cbd64a1330d163ca9e77d28c92b8bf86bc238a6c07dcc3c01.png\" alt=\"\" />The <a href=\"https://indieauth.spec.indieweb.org/\">IndieAuth</a> spec, an OAuth 2.0 extension<p>Earlier this year, I wrote this all up as an extension to OAuth 2.0, called IndieAuth. IndieAuth encapsulates these small additions needed for OAuth 2.0 to work in the Open Web.</p>\n<p>Despite this spec being published in January, it has actually been implemented for several years before that. There are <a href=\"https://indieweb.org/IndieAuth#Implementations\">many implementations</a> of this extension on the server side, everything from standalone authorization server projects, to a <a href=\"https://indieweb.org/Wordpress_IndieAuth_Plugin\">WordPress</a>\u00a0plugin, and it's even implemented by a commercial service, <a href=\"http://www.manton.org/2018/07/indieauth-for-micro-blog.html\">Micro.blog</a>. As far as consuming apps, nearly every <a href=\"https://indieweb.org/Micropub/Clients\">Micropub app</a> has implemented this for logging users in.</p>\n<p>For further details on implementing this extension, there are several guides available depending on whether you're writing a client, a server, or just part of a server.</p>\n<ul><li><a href=\"https://indieweb.org/indieauth-for-login\">Authenticating users with IndieAuth</a></li>\n <li><a href=\"https://indieweb.org/obtaining-an-access-token\">Obtaining an access token with IndieAuth</a></li>\n <li><a href=\"https://indieweb.org/authorization-endpoint\">Creating an Authorization Endpoint</a></li>\n <li><a href=\"https://indieweb.org/token-endpoint\">Creating a Token Endpoint</a></li>\n</ul><p>There are a few existing open source projects you can use to get started if you don't want to write your own!</p>\n<ul><li>\n<a href=\"https://github.com/inklings-io/selfauth\">selfauth</a> - a standalone authorization server using a simple password login</li>\n <li>\n<a href=\"https://wordpress.org/plugins/indieauth/\">IndieAuth for WordPress</a> - a plugin that turns your WordPress install into an OAuth 2.0 server</li>\n <li>\n<a href=\"https://github.com/barryf/acquiescence\">Acquiescence</a> - an authorization endpoint written in Ruby that authenticates users via GitHub</li>\n</ul><p>For further reading, check out the <a href=\"https://indieauth.spec.indieweb.org/\">IndieAuth spec</a>.\u00a0Feel free to drop in to the <a href=\"https://indieweb.org/discuss\">IndieWeb chat</a> if you'd like to talk about this, or you can reach me on <a href=\"https://twitter.com/aaronpk\">Twitter</a>\u00a0or from <a href=\"https://aaronparecki.com/\">my website</a>.</p>"
},
"author": {
"type": "card",
"name": "Aaron Parecki",
"url": "https://aaronparecki.com/",
"photo": "https://aperture-media.p3k.io/aaronparecki.com/2b8e1668dcd9cfa6a170b3724df740695f73a15c2a825962fd0a0967ec11ecdc.jpg"
},
"_id": "558768",
"_source": "16",
"_is_read": true
}