Blog: indieweb

Configuring Vouch Proxy with Indieauth

This post was written in en

Location: 38.581573, -121.494400

Table of Contents

Introduction

A few months ago, I wrote a blog post on Vouch Proxy using Google as an idP, or Identity provider. This time I will be writing on how to configure vouch proxy to use indieAuth as the idP.

This blog post will be very similar to the blog post mentioned above but we will focus on indieAuth.

Today, I'll demonstrate how to setup Vouch Proxy on an nginx web server. In this example I will be using IndieAuth as our provider using a very minimal configuration.

This tutorial assumes you have prior knowledge of using a linux server such as Debian. Message me at hello@lifeofpablo.com if you need some help. I'd be happy to do so!

Use Cases

I currently use it for: * Signing into my website * Using it for my guestbook * Sign into my RSS feeder. * Using same cookie on my website. Similar to single sign on.

What Vouch Proxy Does?

According to the Repository README.md, it states the following:

Vouch Proxy (VP) forces visitors to login and authenticate with an IdP (such as one of the services listed above) before allowing them access to a website.

Vouch Proxy protects websites

VP can also be used as a Single Sign On (SSO) solution to protect all web applications in the same domain.

Vouch Proxy is a Single Sign On solution

After a visitor logs in Vouch Proxy allows access to the protected websites for several hours. Every request is checked by VP to ensure that it is valid.

VP can send the visitor's email, name and other information which the IdP provides (including access tokens) to the web application as HTTP headers. VP can be used to replace application user management entirely. In our case, we are passing an HTTP header with your domain to sign into sites that support indieauth protocol.

An example of an HTTP header being passed is my domain, https://lifeofpablo.com.

Things you'll need/prepare:

  • A linux server with a public IP address with hosting and SSL
    • Debian will be used here but any of the common distros will work
    • Certbot is an easy solution to get SSL certifcate for https://
  • Go Language (to compile vouch-proxy)
  • Vouch Proxy
  • Make sure your website is setup for use with the Indieauth protocol.
  • Nginx Web Server
  • Digital Ocean has a good guide if you need to learn how to setup virtual blocks in nginx.

Download/Install Vouch Proxy from Github

Make sure to have Go Lang installed. Follow the instructions for your operating system. In my case I am using debian.

Download Vouch Proxy from it's Github repository.

$ git clone https://github.com/vouch/vouch-proxy.git
$ cd vouch-proxy
$ ./do.sh goget
$ ./do.sh build

Vouch Proxy Nginx Virtual Block

Let's go ahead and create a virtual block to proxy Vouch Proxy.

server {

        server_name vouch.domain.com; #decide what subdomain you will use.

       # Proxy to your Vouch instance
  location / {
    proxy_set_header  Host $http_host; #this variable will match your domain above
    proxy_set_header  X-Forwarded-Proto https;
    proxy_pass        http://127.0.0.1:9090;  #Default port is 9090 but you can change it if that port is already used. Remember this port for later.
  }
}

Let's go ahead and create a virtual block for a regular nginx website site or edit an existing virtual block. This is the website/service that you will protect with Vouch Proxy.

In this example I am using a php web app. If you a non php site site to work you can remove this location block and and edit it to your needs.

Vouch Proxy config with Indieauth.com as a service provider.

Modify your config.yml

This will get you going, I have added some of my personal settings such as public access. Public access allows people to access your "protected app" without needing to login until you need them to login. Here are some options in how you can allow people to use your app. It is important to align the config in the config.yml file. Even an extra space can cause Vouch Proxy to fail. More on that in the next section.

Options

  • You can allow public access to the site but only allow everyone the option to sign into the website with a basic PHP script or use the corresponding http_header to use the website/web app to authenticate .
    • Comment out or delete the line, "allowAllUsers: true" and include the line," publicAccess: true" .
  • You can allow public access to the site but only allow certain people, (or in this case, domains) actually sign into the website.
    • Comment out or delete the line, "allowAllUsers: true" and include the line," publicAccess: true" .
  • You can force everyone to sign in before seeing the website but still allow everyone to access the website.
    • Include the "allowAllUsers: true" and comment out or delete the line,," publicAccess: true" .
# Vouch Proxy configuration
# bare minimum to get Vouch Proxy running with IndieAuth
# This setup current is running side by side with another vouch proxy instance

vouch:
  logLevel: debug
  listen: 0.0.0.0
  port: 9090
  allowAllUsers: true
  cookie:
    secure: false
    domain: lifeofpablo.com
  publicAccess: true
oauth:
  # IndieAuth
  # https://indielogin.com/api
  provider: indieauth
  client_id: https://lifeofpablo.com
  auth_url: https://indieauth.com/auth
  callback_url: https://auth.lifeofpablo.com/auth

Run/test your Vouch Proxy configuration.

Run the following command

nohup ./vouch-proxy -loglevel debug > vouch.log 2>&1 &

It should display a process ID (PID)



[1] 53310

Hit enter. If no error or exit code displays, Vouch proxy is running!

If there is an error, it will exit such as the example below.



[1]+  Exit 126                nohup ./vouch-proxy -loglevel debug > vouch.log 2>&1

If there is an error, make sure your there is not weird spacing or errors in the configuration. If you are sure that you have the information correct, use the examples provided by Vouch Proxy and copy and paste the example to get the formatting correct. Adjust the configuration as needed to match your needs.

Nginx Virtual block protected by Vouch Proxy

server {
        listen 80;
        listen [::]:80;
        root /root/to/web/directory;
        index index.php index.html;
        server_name secretapp.example.com;

location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    client_max_body_size 100m;

 location ~* \.php$ {
try_files $uri =404;
    fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;# Adjust to your setup
    include fastcgi.conf;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param   REMOTE_USER $auth_user;
    #fastcgi_param   HTTP_REMOTE_USER $auth_user;
     }

# Any request to this server will first be sent to this URL
auth_request /vouch-validate;


location = /vouch-validate {
  # This address is where Vouch will be listening on
  proxy_pass http://127.0.0.1:9090/validate;

  proxy_set_header Content-Length "";
  proxy_set_header Host $http_host;
  proxy_set_header Remote-User $auth_user;
  proxy_pass_request_body off; # no need to send the POST body
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;

  # these return values are passed to the @error401 call
  auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt;
  auth_request_set $auth_resp_err $upstream_http_x_vouch_err;
  auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount;
}


auth_request_set $auth_user $upstream_http_x_vouch_user;

location = /logout {
        return 302 https://vouch.domain.com/logout?url=$scheme://$http_host;
}

error_page 401 = @error401;

# If the user is not logged in, redirect them to Vouch's login URL
location @error401 {
  return 302 https://vouch.domain.com/login?url=https://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
}

}

Eventually you will need to secure your site with SSL/TLS that makes your site use https://. More than ever, your traffic should be secure with using it as 0auth as the method used to sign in to your protected website(s).

Do this after you have the server blocks working in the following section.

Here is the link for Certbot for Debian. I have tested this on Debian 10 & 11. [https://certbot.eff.org/instructions?ws=nginx&os=debianbuster](Link for Certbot)

Certbot can do this for you as long as you have the subdomain in your DNS pointing to your machine and have cert bot installed. It'll add these blocks in your server blocks automatically.

It'll look similar to this . Certbot will rearrange and add a few things.

server { 

   server_name vouch.example.com  # or the domain of protected site will be in place of *vouch.example.com* by certbot

                                .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 

    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/vouch.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/vouch.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


}
server {
    if ($host = vouch.domain.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80;
        listen [::]:80;

        server_name secretapp.example.com;
    return 404; # managed by Certbot


}

Repeat for every server block you'd like protect.

Let's check for errors in nginx. Type the following command.

sudo nginx -t

You should see something similar to this:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Then restart nginx to push changes.

sudo systemctl restart nginx

Let's open a browser tab or window!

Note: I'm using Firefox. (Preference). Any modern browser should work.

Depending on your setup, you'll see a login screen or a website without login in

Type in the protected app' URL in the address bar

Image without description Sign in with your domain (indieauth).

Image without description

Trigger a login later, if needed. Image without description

OR

Type in the protected app' URL in the address bar

2 - Trigger Login Later

Image without description Trigger vouch proxy (indieauth).

Image without description

Image without description

Voila, the protected page.

Here is the home page of a Bludit CMS on subdomain acting as "secretapp.example.com"

I will write a blog post on using it on my website and my RSS feeder. I will also go in deeper about the cookie as well.

That's it! You have setup indieauth to protect (or not your pages

Want to see who's logged in?

Whether you just want to see the user authenticated via the http_header or use http_header to help you authenticate into the website we can use a simple php script. We added already the other parts but here's an overview.

In your main server block, just below the line auth_request /vouch-validate; which enables the auth_request module, we added the following:

auth_request_set $auth_user $upstream_http_x_vouch_user;

This will take the HTTP header that Vouch sets, X-Vouch-User, and assign it to the nginx variable $auth_user. Then, depending on whether you use fastcgi or proxy_pass, include one of the two lines below in your server block:

fastcgi_param REMOTE_USER $auth_user;
proxy_set_header Remote-User $auth_user;

These will set an HTTP header with the value of $auth_user that your backend server can read in order to know who logged in. For example, in PHP you can access this data using:

<?php
echo 'Hello, ' . $_SERVER['REMOTE_USER'] . '!';
?>

Content available in other languages

This post was written in en

Image without description

Read Blog Post en français.

Once a moon, I'll write in French, During our last Indieweb Meeting, we discussed, "Multilngual Brainstorming" related to h-entry tags.

Let's talk about this briefly!

If we must bring up the subject, content localization goes hand in hand.

The main question is, "How do I present content in different languages on my website"

It is important to use , href to select the ISO two-letter abbreviation of the intended language to be used. For this example below, we would use Spanish. The ISO code would be ES. The link must point to the version of the content in the intended language .

For Example:


<a rel="alternate" href=""  hreflang="[language abbreviation]">[link content]</a>


Example using`rel="alternate" ' with Spanish as the selected language option.

<html lang="en">

<article class="h-entry">
  <h1 class="p-name"> <a href="/in-english" class="u-url">Article in English</a> </h1>
  Read <a rel="alternate" href="/en-espanol" hreflang="es">Article en Espanol</a>
</article>
gRegor Morrill

Thank you for getting me up to speed with this topic and for providing me some sweet examples. It will make life easier. ! c

Some links :


Le contenu disponible dans d'autre langues

This post was written in fr

Image without description Read Blog Post in English

Normalement, j'écris en anglais. Pendant la dernière réunion d'IndieWeb, on a discuté le "multilingual-brainstorming" avec les balises ou catégorisation (tags en anglais) "h-entry."

C'est parti !

C'est important pour la localization .

La question présentais, "Comment presenter le contenu des blog posts en langues different ?"

Il faut utiliser la balise, href pour la selection de la langue en format ISO - Code des langues. Par exemple, l'espagnol sera le code, ES. Il est important d'avoir un lien où le contenu est disponible dans la langue prévue.

Par Example:


<a rel="alternate" href=""  hreflang="[abréviation du langue]">[contenu du lien]</a>


Example avec rel="alternate" qu’utilise l'espagnol.

<html lang="en">

<article class="h-entry">
  <h1 class="p-name"> <a href="/in-english" class="u-url">Article in English</a> </h1>
  Read <a rel="alternate" href="/en-espanol" hreflang="es">Article en Espanol</a>
</article>
gRegor Morrill

Merci 1000 fois pour t'assistance. Je suis mis à jour!

Some Links :


Implementing Indielogin to my site and microsub compatible.

This post was written in en

Image without description

Intro

I've been on this SSO/oauth rabbit hole these last few weeks. I have implemented vouch-proxy (blog post coming soon, I promise. pls don't hate me! ) I happened to stumble upon indieauth which leadme to indielogin, and so forth continuing my rabbit hole. I heard about it this many years ago but it placed on my, "I know I should look into this soon" filing cabinet. Queue the Spongebob scene.

Indie Web states the following:

The IndieWeb effort is different from previous efforts/communities:

  • Principles over project-centrism. Others assume a monoculture of one project for all. We are developing a plurality of projects. The IndieWeb community has a code-of-conduct.
  • Publish on your site instead of emailing a list. Show before tell. Prioritize by making what you need, creating, iterating on your own site.
  • Design first, protocols & formats second. Focus on good UX & using your own prototype features to create minimum necessary formats & protocols.

I would like to give a shoutout to the IndieWeb Community and Aaron Parecki all that they do. You guys provide so much information. It wouldn't have been possible for this.

Disclamer: By no means is my setup even close to being perfect. I'm still a new to this.

The premise here is that you use your domain. Mine for example:

https://lifeofpablo.com

IndieAuth

IndieAuth is a federated login protocol for Web sign-in, enabling users to use their own domain to sign in to other sites and services. IndieAuth can be used to implement OAuth2 login AKA OAuth-based login.

Here are a few examples of sites that use indieauth:

image-4.png screenshot-2023-03-18-at-21-22-25-webmention.io.png screenshot-2023-03-18-at-21-34-44-indielogin.com.png

Selfauth

On my site I implemented, selfauth. Selfauth is a single user authorization endpoint written as single-file PHP without a database. For common indielogin/indieauth, it usually requires putting a <link..... rel="me> in my header pointing to Twitter or Github to help identify me and use as a method of authenticating my domain. I instead used selfauth and used a to a directory on my server to use as an authorization_endpoint as shown below.

<link rel="authorization_endpoint" href="https://lifeofpablo.com/auth/" />

So now I can login to any website that authenticates users using indielogin/indieauth

Adding h-entry microformats2

h-entry is the microformats2 vocabulary for marking up blog posts on web sites. It can also be used to mark-up any other episodic or time series based content.

Today, I added h-entry tags to my homepage and to my blog. H-entry tags are simply html classes added to a specific locations on a page. I am using Datenstrom Yellow. I used their API and the blog layouts (blog-start.html & blog.html )

Your h-entries should have, at minimum, the following properties:

e-content

  • the main content of the post

p-name

  • if your post is an article with a name, use this classname.

dt-published

  • the datetime the post was published at, in ISO8601 format, with a timezone
  • Datenstrom Yellow does this already in this format

u-url

  • the canonical URL of the post, especially important on pages listing multiple posts

Here is a full list of h-entry tags

Use this site to help you validate and make sure the information is pulling correctly. Adjust your code accordingly.

Here is my code reflecting h-entry tags as classes on Datenstrom, (the flat-file cms this site is running on).

I recommend using <span></span> where you need to place two or h-entry tags on the same line. It will help prevent unnecessary line breaks. Datenstrom, for example puts the date and author in the same line. (Look at example below and then look what I do in my code)

2023-03-19 by Pablo Morales

Webmention.io Webmention.io

Webmention is an open web standard (W3C Recommendation) for conversations and interactions across the web, a powerful building block used for a growing distributed network of peer-to-peer comments, likes, reposts, and other responses across the web.

This is the part where I start losing it a bit. Webmention.io is pretty straight forward. I have started experimenting with cross-site conversations. Luckly Webmentions.io helps me with this.

Basically, you sign up using your domain and configure your website with the appropriate steps to webmentions.io to start allowing you to do cross-site interactions.

The steps are

  • Sign up using your domain
  • Setup
  • Get your mention feeds
  • Get your API key.

Joining the community and attending events

There seems to be a big community! I am for sure commited! I will continue to share and contribute to this community. I am always looking to find new people to share things I enjoy.

I am really excited to join my first event virtually. I am going to join the "Homebrew Website Club" this week and meet some cool people! Want to join ? Here is the link.

Here's the link to the entire calendar. Upcoming Events

Conclusion

  • That's it! We covered:
  • Indieauth
  • Selfauth
  • h-entry tags & code examples
  • Webmention.io
  • Joining the community

I didn't go too much in detail but it's a start. I am happy to continue experimenting with this protocal and implementation for an open-web. Rabbit holes like this are fun and push my limits! There are so many options on how you can implement indieauth and how you can process your data. It's easier for anyone who is using a popular platform such as Wordpress. Why not try the non-easy route? It's fun!

Happy authenticating!

  • Pablo