Skip to main content

Alternative frontend origins

Intermediate
Authentication

If your application has reached the stage where you want to change domain names, and you have been authenticating with Internet Identity (II), you will want to make sure that your users can seamlessly keep the same principals they have already been using. To support this functionality, you can configure your application for alternative frontend origins using this guide.

You may need this guide if you are doing any of the following:

  • Moving from <canister-id>.icp0.io to a custom domain.
  • Asking users to log in at /login instead of /.
  • Supporting users using raw.icp0.io.
  • Configuring multiple apps in your organization to use the same principals.

Constraints

Currently, a maximum of 10 alternative origins can be listed.

Internet Identity will only follow this specification when the origin configuring these alternatives is hosted on a canister using certified assets.

For more information, see the Internet Identity specification.

Configuring alternative origins

For this example, you will have two domains, A and B. A will be the derivation origin, and B will be the alternative domain. To help illustrate this model, consider this website, which is hosted both at https://xxxxx.icp0.io and https://www.yourcustomdomain.com.

In this example, A would be https://xxxxx.icp0.io.

B would be the alternative origin, or https://www.yourcustomdomain.com.

Setting the derivation origin

If you are using Internet Identity, you are probably using AuthClient. Therefore, on the code for the B origin, you need to set the derivationOrigin to the AuthClient to A.

const authClient = await AuthClient.login({
//...
derivationOrigin: "https://xxxxx.icp0.io",
});

Note that for the AuthClient on A the field derivationOrigin can be omitted.

For more details about the login options in the AuthClient, see its documentation.

Listing alternative origins

On origin A, you need to provide an endpoint .well-known/ii-alternative-origins that tells Internet Identity that B is a valid alternative origin.

The response of this endpoint must be a valid JSON object with an alternativeOrigins key, containing an array of strings:

{
"alternativeOrigins": ["https://www.yourcustomdomain.com"]
}

Requirements:

  • Maximum of 10 alternative origins can be listed.
  • No trailing slash or paths should appear in the URL.
  • Order doesn't matter.

Note that there is no need to have .well-known/ii-alternative-origins on origin B.

Asset canister

Most developers implement their frontend applications using the Asset Canister. Therefore, we provide a tutorial on how to set up the alternative origins endpoint with it.

Adding the ii-alternative-origins config file

If your frontend canister is currently configured to deploy assets from a dist folder, make sure to update the sources for your canister to include both:

dfx.json
"source": [
    "dist",
    "src/assets"
]

Inside of src/assets, create a .well-known folder, and add a file named ii-alternative-origins.

The file needs to be exactly named ii-alternative-origins, with no file extension. The content inside will be formatted as JSON, but the file should not end with .json.

Inside of the file, list your alternative origins for A, which is B in our example. It will look something like this:

src/assets/.well-known/ii-alternative-origins
{
"alternativeOrigins": ["https://www.yourcustomdomain.com"]
}

Now, your project should look something like this:

├── dfx.json
├── src
│   ├── assets
│   │   ├── .well-known
│   │   │   └── ii-alternative-origins

Configuring your frontend canister

Because the dot syntax in .well-known ordinarily will be treated as "hidden" by the file system, the frontend canister will need to be configured to upload your document. To configure the frontend canister, create a new file, .ic-assets.json. .ic-assets.json needs to be placed inside a directory listed in sources for your canister, so you can use src/assets again. Your new list of files should look like this:

├── dfx.json
├── package.json
├── src
│   ├── project_frontend
│   │   ├── src
│   │   │   ├── .ic-assets.json
│   │   │   ├── .well-known
│   │   │   │   └── ii-alternative-origins

Then, configure the .well-known directory to be included with:

src/project_frontend/src/.ic-assets.json
[
  {
    "match": ".well-known",
    "ignore": false
  },
  {
    "match": ".well-known/ii-alternative-origins",
    "headers": {
      "Access-Control-Allow-Origin": "*",
      "Content-Type": "application/json"
    },
    "ignore": false
  }
]

This includes a general rule to not ignore the .well-known directory and rules to deliver the ii-alternative-origins with access control and content-type headers.

Now, all you need to do is deploy your canisters (both A and B).

From now on, when you attempt to authenticate from origin B, you will get back the same principal you get while using A.

For more information, see the Internet Identity specification for Alternative Origins.