Internet Identity Setup Locally

Hello everyone, just want to ask if there’s a latest video tutorial on how to properly setup the internet-identity?

I really don’t know how to integrate it with my existing project locally.

Not sure that’s the official way, @nmattia or @frederikrothenberger can probably simplies the commands but, I do it as following in my projects when I want to deploy II locally:

git clone https://github.com/dfinity/internet-identity
cd internet-identity/demos/using-dev-build
npm ci
dfx deploy --no-wallet --argument '(null)'
1 Like

Another option is adding following tag in your dfx.json. It will fetch for you the last wasm of II automatically.

"canisters": {
   ...
   "internet_identity": {
      "type": "custom",
      "candid": "internet_identity.did",
      "wasm": "internet_identity.wasm",
      "build": "bash -c 'test -f internet_identity.wasm || curl -sSL https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity_dev.wasm -o internet_identity.wasm; test -f internet_identity.did || curl -sSL https://raw.githubusercontent.com/dfinity/internet-identity/main/src/internet_identity/internet_identity.did -o internet_identity.did'",
      "remote": {
        "candid": "internet_identity.did",
        "id": {
          "ic": "rdmx6-jaaaa-aaaaa-aaadq-cai"
        }
      }
    }
3 Likes

Hi @peterparker my hero.

Thank you for your response, I really appreciate it.

I just want to ask something, I’m following this Motoko course from Angela Yu, my question is how to it integrate the Internet Identity to the existing project?

Should I clone the (GitHub - dfinity/internet-identity: Internet Identity, a blockchain authentication system for the Internet Computer) inside the project folder? or just adjacent to it? or I’m using it all wrong I believe.

From the two solution I shared above, the second one is the easiest. If you add the snippet I shared with you in your dfx.json then you have nothing particular to do. The code takes care of downloading and deploying II for you locally.

"canisters": {
   ...
   "internet_identity": {
      "type": "custom",
      "candid": "internet_identity.did",
      "wasm": "internet_identity.wasm",
      "build": "bash -c 'test -f internet_identity.wasm || curl -sSL https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity_dev.wasm -o internet_identity.wasm; test -f internet_identity.did || curl -sSL https://raw.githubusercontent.com/dfinity/internet-identity/main/src/internet_identity/internet_identity.did -o internet_identity.did'",
      "remote": {
        "candid": "internet_identity.did",
        "id": {
          "ic": "rdmx6-jaaaa-aaaaa-aaadq-cai"
        }
      }
    }

If you use the first method, with the clone, I personally clone it in an adjancent project and then forget about it. i.e. having the repo cloned locally does not really matter, what’s matter is having II deployed in your local simulated II.

Does it answer your question?

2 Likes

Yes it did work, thank you so much @peterparker.

I did marked your last comment as solution so it would help the other developers about this matter.

You just save me time and thank you so much again Spider Man.

2 Likes

Oh cool awesome, happy to hear it solved it. Thanks for the feedback.

1 Like

I tried adding this to dfx.json, but I’ve tried different configurations when calling it here and the best I’ve gotten is a link to the candid UI of Internet Idendity. This is when hardcoding what I get when deploying the internet_identity canister into index.js (haven’t gotten process.env.INTERNET_IDENTITY_CANISTER_ID to work):

await authClient.login({
    onSuccess: async () => {
      handleAuthenticated(authClient);
    },
    // identityProvider: `https://nfid.one/${AUTH_PATH}`,
    // identityProvider: `http://127.0.0.1:4943/?canisterId=rno2w-sqaaa-aaaaa-aaacq-cai`,
    // &id=rkp4c-7iaaa-aaaaa-aaaca-cai
    identityProvider:
        // process.env.DFX_NETWORK === "ic"
        //   ? "https://identity.ic0.app/#authorize"
        //   : `http://localhost:${process.env.REPLICA_PORT}?canisterId=${process.env.INTERNET_IDENTITY_CANISTER_ID}#authorize`,
        //   identityProvider:
          process.env.DFX_NETWORK === "ic"
            ? "https://identity.ic0.app/#authorize"
            : `http://127.0.0.1:4943/?canisterId=ryjl3-tyaaa-aaaaa-aaaba-cai&id=rrkah-fqaaa-aaaaa-aaaaq-cai#authorize`,
          
    windowOpenerFeatures: 
      `left=${window.screen.width / 2 - 525}, `+
      `top=${window.screen.height / 2 - 705},` +
      `toolbar=0,location=0,menubar=0,width=525,height=705`,
  });

What should I change for it to take me to the Internet Identity UI in development?

I saw the light!

Is there anything I can do so that this correct ID is produced via process.env.INTERNET_IDENTITY_CANISTER_ID instead?

See my previous answer in your previous thread Debugging this Internet Identity Authentication Repo - #13 by peterparker

I had these lines in webpack from debugging earlier:

    new webpack.EnvironmentPlugin({
      NODE_ENV: process.env.NODE_ENV ?? "development",
      DFX_NETWORK: process.env.DFX_NETWORK ?? "local",
      REPLICA_PORT,
      ...canisterEnvVariables,
    }),

But they don’t seem to populate process.env.INTERNET_IDENTITY_CANISTER_ID

const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

function initCanisterEnv() {
  let localCanisters, prodCanisters;
  try {
    localCanisters = require(path.resolve(
      ".dfx",
      "local",
      "canister_ids.json"
    ));
  } catch (error) {
    console.log("No local canister_ids.json found. Continuing production");
  }
  try {
    prodCanisters = require(path.resolve("canister_ids.json"));
  } catch (error) {
    console.log("No production canister_ids.json found. Continuing with local");
  }

  const network =
    process.env.DFX_NETWORK ||
    (process.env.NODE_ENV === "production" ? "ic" : "local");

  const canisterConfig = network === "local" ? localCanisters : prodCanisters;

  return Object.entries(canisterConfig).reduce((prev, current) => {
    const [canisterName, canisterDetails] = current;
    prev[canisterName.toUpperCase() + "_CANISTER_ID"] =
      canisterDetails[network];
    return prev;
  }, {});
}
const canisterEnvVariables = initCanisterEnv();

const isDevelopment = process.env.NODE_ENV !== "production";

const REPLICA_PORT = process.env.DFX_REPLICA_PORT ?? "4943";

const frontendDirectory = "backed_usd_frontend";

const frontend_entry = path.join("src", frontendDirectory, "src", "index.html");

module.exports = {
  target: "web",
  mode: isDevelopment ? "development" : "production",
  entry: {
    // The frontend.entrypoint points to the HTML file for this build, so we need
    // to replace the extension to `.js`.
    index: path.join(__dirname, frontend_entry).replace(/\.html$/, ".js"),
  },
  devtool: isDevelopment ? "source-map" : false,
  optimization: {
    minimize: !isDevelopment,
    minimizer: [new TerserPlugin()],
  },
  resolve: {
    extensions: [".js", ".ts", ".jsx", ".tsx"],
    fallback: {
      assert: require.resolve("assert/"),
      buffer: require.resolve("buffer/"),
      events: require.resolve("events/"),
      stream: require.resolve("stream-browserify/"),
      util: require.resolve("util/"),
    },
  },
  output: {
    filename: "index.js",
    path: path.join(__dirname, "dist", frontendDirectory),
  },

  // Depending in the language or framework you are using for
  // front-end development, add module loaders to the default
  // webpack configuration. For example, if you are using React
  // modules and CSS as described in the "Adding a stylesheet"
  // tutorial, uncomment the following lines:
  // module: {
  //  rules: [
  //    { test: /\.(ts|tsx|jsx)$/, loader: "ts-loader" },
  //    { test: /\.css$/, use: ['style-loader','css-loader'] }
  //  ]
  // },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, frontend_entry),
      cache: false,
    }),
    new webpack.EnvironmentPlugin({
      NODE_ENV: process.env.NODE_ENV ?? "development",
      DFX_NETWORK: process.env.DFX_NETWORK ?? "local",
      REPLICA_PORT,
      ...canisterEnvVariables,
    }),
    new webpack.ProvidePlugin({
      Buffer: [require.resolve("buffer/"), "Buffer"],
      process: require.resolve("process/browser"),
    }),
    new CopyPlugin({
      patterns: [
        {
          from: `src/${frontendDirectory}/src/.ic-assets.json*`,
          to: ".ic-assets.json5",
          noErrorOnMissing: true
        },
      ],
    }),
  ],
  // proxy /api to port 4943 during development.
  // if you edit dfx.json to define a project-specific local network, change the port to match.
  devServer: {
    proxy: {
      "/api": {
        target: `http://127.0.0.1:${REPLICA_PORT}`,
        changeOrigin: true,
        pathRewrite: {
          "^/api": "/api",
        },
      },
    },
    static: path.resolve(__dirname, "src", frontendDirectory, "assets"),
    hot: true,
    watchFiles: [path.resolve(__dirname, "src", frontendDirectory)],
    liveReload: true,
  },
};

If you add a console.log(canisterEnvVariables); in this config, what’s the output?

A bit of a basic question but how do I run the webpack config file on its own after placing the console.log in the right place?

Not sure this is the right way:

/Users/black/.nvm/versions/node/v18.12.1/bin/node ./backed_usd/webpack.config.js
No local canister_ids.json found. Continuing production
No production canister_ids.json found. Continuing with local
Process exited with code 1
Uncaught TypeError TypeError: Cannot convert undefined or null to object
    at initCanisterEnv (undefined:30:17)
    at <anonymous> (undefined:37:30)
    at Module._compile (undefined:1159:14)
    at Module._extensions..js (undefined:1213:10)
    at Module.load (undefined:1037:32)
    at Module._load (undefined:878:12)
    at executeUserEntryPoint (undefined:81:12)
    at <anonymous> (undefined:23:47)

Got that running the file directly with Node.js

I do have a canister_ids.json though:

{
  "__Candid_UI": {
    "local": "ryjl3-tyaaa-aaaaa-aaaba-cai"
  },
  "backed_usd_backend": {
    "local": "r7inp-6aaaa-aaaaa-aaabq-cai"
  },
  "backed_usd_frontend": {
    "local": "rkp4c-7iaaa-aaaaa-aaaca-cai"
  },
  "internet_identity": {
    "local": "rrkah-fqaaa-aaaaa-aaaaq-cai"
  }
}

In webpack.config.js:

const canisterEnvVariables = initCanisterEnv();
// Here add:
console.log(canisterEnvVariables);

Then run

npm run start

That’s where it was but I got a different log running it that way:

Shrink WASM module size.
Generating type declarations for canister backed_usd_backend:
  src/declarations/backed_usd_backend/backed_usd_backend.did.d.ts
  src/declarations/backed_usd_backend/backed_usd_backend.did.js
  src/declarations/backed_usd_backend/backed_usd_backend.did

> backed_usd_frontend@0.1.0 start
> webpack serve --mode development --env development

No production canister_ids.json found. Continuing with local
canisterEnvVariables is:  {
  __CANDID_UI_CANISTER_ID: 'ryjl3-tyaaa-aaaaa-aaaba-cai',
  BACKED_USD_BACKEND_CANISTER_ID: 'r7inp-6aaaa-aaaaa-aaabq-cai',
  BACKED_USD_FRONTEND_CANISTER_ID: 'rkp4c-7iaaa-aaaaa-aaaca-cai',
  INTERNET_IDENTITY_CANISTER_ID: 'rrkah-fqaaa-aaaaa-aaaaq-cai'
}

It seems to see them.

So in your app you should be able to use process.env.INTERNET_IDENTITY_CANISTER_ID

If you now adds a console.log(process.env.INTERNET_IDENTITY_CANISTER_ID) in your frontend app JS code, do you gets it at runtime in your browser?

Now I do. Thank you.

Why did it suddenly appear?

It is that I always used dfx deploy and never npm run start?

What’s the difference between working on dfx deploy vs using npm run start?

In particular, I worry that the special command I need to use for it to work might not be triggered with npm run. It needs to be dfx deploy backed_usd_backend --argument '(variant { Regtest })'

and dfx start --enable-bitcoin --background --clean

(it’s reading correctly when using dfx deploy and port 4943 too now)

When developing locally, backends always run on your local replica (“simulated network”).

Your frontend is also deployed on this local env (dfx deploy backed_usd_frontend). However, it is known to not be convenient to develop the frontend that way, because it would mean that each time you made a change, you would have to run dfx deploy again. e.g. You can imagine the number of deploy just to implement CSS changes :wink:

That’s why to make it convenient, the webpack.config.js is set with a proxy so that when you run npm run start it queries the backend on the local replica.

Hope this explains it a bit. So you are all set, have fun.

1 Like

Thanks. I’m a bit nervous about those special commands but I’ll report back if anything broke.

Thanks again.

It’s a bit tricky at first but after a while it gets easier. We have all been there. Happy to hear it worked out!

1 Like