Checking if a user owns a domain
Tags: javascript, typescript, domains
Published: 2021-04-03 15:11:26

---
title: Checking if a user owns a domain
published: true
date: 2021-04-03 02:00:00 UTC
tags: javascript,typescript,domains
canonical_url: https://www.solarwinter.net/checking-if-a-user-owns-a-domain/
cover_image: https://www.solarwinter.net/content/images/2021/04/nslookup.png
---

The technique we’re using is the one used by Google, Microsoft and others to verify that you've got some authority over a domain. So while it's not foolproof, at least we're in good company!

The code in this article is TypeScript, but the same method would work in most languages.

## Overview

All of the verification methods I've seen rely on the user being able to modify the site in some way - which makes sense, since you're checking if they have control over the site they're trying to use.

Most of them seem to have settled on using some form of DNS entry - a special record which they can check actually exists.

## Quick DNS intro

This is very brief; for a (slightly) fuller introduction to the DNS, see [my other post](https://www.solarwinter.net/domains/).

The Domain Name System consists of records giving information to computers accessing the internet. There are quite a few different types of record. The most basic one is called an A record, A for address. It essentially says "this text - foobar.example.com - points to this IP address".

There are a number of reserved addresses which have particular meanings. One useful address is `127.0.0.1` - that always means "this computer". The symbolic name for it is `localhost`.

## The plan

We want to check the user can modify the DNS entries for that domain, but not with anything particularly disruptive or complicated - the more complicated we make it the more likely it is that user error will creep in.

The simplest way - generate a random subdomain and have them create an A record pointing to `127.0.0.1`.

## Generating an alias

There are many different ways to do this. I chose to use the Node [uuid](https://www.npmjs.com/package/uuid) module and take the first 8 characters. 8 was chosen because it was random enough for our purposes, and because it was the first 'lump' in the v4 UUID.

```
siteDetails["alias"] = uuid().substr(0, 8);

```

## Checking the alias

Using the Node [dns module](https://nodejs.org/api/dns.html) we can resolve the alias we created; we append `domain` after it, making `alias` a subdomain.

The plain `dns` methods are callback based; it also supplies a `dnsPromises` set of APIs which are Promise based. We’ll use [that resolve method](https://nodejs.org/api/dns.html#dns_dnspromises_resolve_hostname_rrtype)for convenience.

```
import dns from "dns";
const dnsPromises = dns.promises;

type Site = {
  alias: string; // Alias we'll be verifying
  domain: string; // Domain the user gave us
  verified: boolean; // Is it verified yet
}

async function verifySite(site: Site) {
  try {
    const res = await dnsPromises.resolve(site.alias + "." + site.domain);
    const valid = ((res.length == 1) && (res[0] == "127.0.0.1"));
    site.verified = valid;
  } catch (err) {
    console.error(`Error ${err} doing site ${site.id} verification`);
  }
}

```

We’re expecting result of the lookup to be a single entry, `127.0.0.1` - if it is then we called it verified. Lastly, we make sure the data reflects what we just found.

## Running checks in the background

We now have a function which we can use to verify domains. The last stage is to have it run periodically in the background, rather than on-demand.

The implementation I used is below. I haven’t included the utility functions (like `getAllSites`, but the code should still be understandable without those.

`startBackground` uses `DOMAIN_VERIFY_PERIOD_SECONDS` from the environment if it’s defined - if it isn’t it defaults to 300 seconds (5 minutes). It then uses `setInterval` to schedule `verifySites`. `setInterval` takes milliseconds as an argument, so we convert it first.

`verifySites` simply gets the current list of sites and runs `verifySite` on all of them.

Lastly, `stopBackground` will cancel the interval function if it’s been scheduled to run.

```
import { getAllSites } from "./queries";

let domainCheckId: NodeJS.Timeout | null = null;

export async function verifySites() {
  const sites: Site[] = await getAllSites();
  sites.forEach(site => verifySite(site));
}

export function startBackground(): void {
  const SECOND = 1000;
  const period: number = parseInt(process.env.DOMAIN_VERIFY_PERIOD_SECONDS || "300");
  console.log(`Starting domainCheck, period ${period} seconds`);

  domainCheckId = setInterval(verifySites, SECOND * period);
}

export function stopBackground(): void {
  if (domainCheckId) {
    clearInterval(domainCheckId);
    domainCheckId = null;
  }
}

```

And that’s it - those functions are enough to start verifying domains in the background. Let me know if you use it!