Custom domains

How it works

The account you signed in with belongs to this site. The app on the next page is a Molnify app served from app.domains.molnify.se, and it opens with that same sign-in.

Open the app


Set it up for your domain

  1. Pick a subdomain

    Choose the address you want the app to have, for example quotes.yourcompany.com. It can be any subdomain of your website's domain that you are not already using, but not the domain itself (yourcompany.com).

  2. Add a CNAME record

    A CNAME record makes one name in DNS point to another. Log in where your domain's DNS is managed and add one for your subdomain, pointing at app.molnify.com. Your new address will show an error until we have added it on our side, which happens in the next step.

  3. Tell Molnify

    Custom domains are set up on request. Send an email to info@molnify.com with:

    • the subdomain you chose
    • the ID of the app, which is the last part of its address at app.molnify.com/app/
    • the address of your site's login page
    • the email address of the Molnify account of each person who will upload the app

    We add your subdomain on our side and reply with the name of your algorithm. That is the name your setup is registered under at Molnify, and it goes into the app in the next step.

  4. Add the login handoff

    In the app

    Set the metadata TokenAuthentication, then upload the app again.

    TokenAuthentication algorithm=YOUR_ALGORITHM;salt=YOUR_SALT;loginPage=https://www.yourcompany.com/login

    loginPage is where the app sends a visitor who is not signed in to it.

    The salt is a secret that you choose. Make it a long random string of letters and digits, and treat it like a password, because anyone who has it can sign in to your app as any of your users. The workbook contains it, so take the same care with the file.

    If the upload reports that TokenAuthentication is not allowed for your address, that address was not among the ones you sent us in step 3.

    Then set the app's users to *@yourcompany.com, in the way the app already manages its users. That lets in addresses that end in @yourcompany.com, which every visitor from your site will have.

    On your site

    When a signed-in visitor opens the app, your server builds a link like this one and sends the visitor to it:

    https://quotes.yourcompany.com/tokenauthentication/APP_ID?email=IDENTITY&token=TOKEN

    IDENTITY is the email address the app will have for the visitor, and it is what a user.email input receives. Take the visitor's own address, replace the @ with __at__ and add @yourcompany.com. Write all of it in lower case, so that anna@gmail.com becomes anna__at__gmail.com@yourcompany.com. URL-encode it when you put it in the link.

    TOKEN is what Molnify checks before it lets the visitor in. It is the SHA-256 hash, written as lower-case hexadecimal, of this text: secret-MINUTE-SALT-IDENTITY. The word "secret" is part of the text. MINUTE is the current time in seconds since 1970, rounded down to a whole minute, so 1791543450 becomes 1791543420. SALT is the salt from the app.

    Build the link on your server each time a visitor opens the app, because a link only works for a minute or two. Do not build it in the browser, since that would reveal the salt. Once a visitor is in, they stay signed in to the app for the rest of their browser session.

    When a link is refused, the visitor is sent to your login page and sees no error. If that happens, check these:

    • Your server's clock. Molnify accepts the minute the link was made in and the one before and after, by its own clock.
    • The salt. It has to be the same on your server and in the app.
    • The algorithm name in the app, which has to be spelt as we sent it.
    • The end of IDENTITY, which has to be @yourcompany.com in lower case.

    Sample, PHP

    function molnify_app_link(string $email, string $salt): string {
        $siteDomain = 'yourcompany.com';
        $appAddress = 'https://quotes.yourcompany.com/tokenauthentication/quote-builder';
        $identity = strtolower(str_replace('@', '__at__', $email) . '@' . $siteDomain);
        $minute = intdiv(time(), 60) * 60;
        $token = hash('sha256', "secret-$minute-$salt-$identity");
        return $appAddress . '?' . http_build_query(['email' => $identity, 'token' => $token]);
    }

    Sample, Node.js

    const crypto = require("node:crypto");
    
    function molnifyAppLink(email, salt) {
      const siteDomain = "yourcompany.com";
      const appAddress = "https://quotes.yourcompany.com/tokenauthentication/quote-builder";
      const identity = `${email.replaceAll("@", "__at__")}@${siteDomain}`.toLowerCase();
      const minute = Math.floor(Date.now() / 60000) * 60;
      const token = crypto.createHash("sha256").update(`secret-${minute}-${salt}-${identity}`).digest("hex");
      return `${appAddress}?${new URLSearchParams({email: identity, token})}`;
    }