I have been developing locally using Internet Identity for authentication with no problems on a 2017 iMac with a YubiKey.
I just switched to a MacBook Pro with an M1 processor and set everything up the same, but when I try to login, before I even select the login method, I get the following errors in Chrome Dev Tools (I get a blank screen with Safari):
This happens with the webpack dev server and if I browse directly to the dapp canister: http://{dapp canister id}.localhost:8000.
If I select āThis deviceā and use my fingerprint scanner, it just stays on that screen until it errors with a timeout.
I had no problem compiling and deploying the Internet Identity project. Is there anything special I need to do for an M1 processor to get local authentication working?
Alternatively, is there any code in the Internet Identity project that could be changed to bypass actual authentication and just return a static identity for development purposes?
Thank you.
Detailed error messages:
PoW: 3189.276123046875 ms
index.js:1065 createChallenge(ProofOfWork { timestamp=1645256116345000000, nonce=1420616005839431 })
index.js:2 Uncaught (in promise) Error: Fail to verify certificate
at Dt (index.js:2:121013)
at async Yt.n (index.js:2:124987)
at async Function.createChallenge (index.js:1065:5993)
Are you able to login to Internet Identity for apps on mainnet? There were some reports of clock syncing issues on new Macs, a simple reboot might have resolved those though.
@Ori: I just re-deployed my code to mainnet and confirmed that Internet Identity login works as expected from my MacBook Pro (M1 processor).
So this issue is only happening locally with the M1 processor. There is no issue on my iMac (Intel processor). Both macs are running macOS Monterey 12.1.
Honestly, I just want a way to mock Internet Identity authentication so that local secure canister calls work exactly the same. If someone has already done this, and is kind enough to share the solution, it would be greatly appreciated!
I was able to solve this by copying this file directly into the dApp project, then modifying some functions to return an auto-generated Identity based on a local config setting (the idea came from this post).
When developing locally, login just works by using a generated Identity instead of connecting to an II provider.
When deploying to mainnet, login uses the actual mainnet II provider.
Uhg. Although this works in the front-end code, when calling a canister function, the caller is the anonymous user principal. . So it seems there are still some things to figure out.
I have been learning about the inner workings of authentication, and my current understanding is that we canāt bypass an II provider because when a user sends a message, itās signed with the private key of the userās Identity, then the message envelope includes the signature and the public key.
The IC has to validate the signature against the public key, but it also needs to validate that the principal in the message is the true owner of that public key. I believe that last part means that the IC calls the II provider/canister to match the principal with the public key.
If that is the case, then it seems that a simple mock setup of II authentication for local development would require a mock II canister as well, which just validates all messages/requests.
(You may ask, why not use the II project locally as is, which is my preference, but it does not seem to work on M1 Apple processors. If there is a straightforward solution for the core issue, I would like to use that instead.)
If anyone has read up to this point, thanks for bearing with me.
A couple of months ago when I first heard about this issue I googled a bit, and apparently thereās a native VM tool from Canonical that lets you run ubuntu under m1 apple silicon. You could give that a try.
Iāve also had a deep dive through the II authentication flow for porting the agent-js parts to rust with yew, and I believe the idea is that the agent maintains a local random key, but receives a delegation based on that public key, and the replicas just verify that the delegation chain is properly signed. I donāt think the replicas communicate with the II app.
@GLdev Thank you for the response and the tip about Cononical. Itās a good last resort.
I see that delegation is implemented in the II canister. I was just learning about how that works. I think you are correct because the diagrams I have seen show the browser connecting the the II canister, and to the backend canisters, but there does not appear to be communication from the backend canister to the II canister. (Not like OAuth flows.)
It would be very nice to figure out how to mock a delegate. I understand they come with expirations, so that would need to be handled as well.
Alrighty, I finally have a local Internet Identity canister working on my MacBook Pro with an M1 processor. The trick is to update the JavaScript in the @dfinity/agent library (@kpeacock) from the node_modules folder of your locally cloned Internet Identity project. (It seems that the library is not open-source yet, or I just donāt know how to find it.)
Search node_modules for āFail to verify certificateā.
checkState() {
// if (!this.verified) {
// throw new UnverifiedCertificateError();
// }
}
Delete the dist folder.
Ensure you have a local instance of the IC running:
dfx start --background
Redeploy the II canister:
dfx deploy --no-wallet --argument '(null)'
After that I was able to create a new local Internet Identity. To reiterate from earlier, none of this was necessary on my 2017 iMac with an Intel processor. I donāt know how the processor is related to certificate verification, I just followed the errors and removed the code that threw them.
With this change, the message caller in public canister functions is the identity that was autogenerated in the UI code.
So now there are two working options: 1. Fake the Identity or 2. Use the local II provider (with the small hack mentioned in my last post for M1/M2 processors).
The code can be greatly improved, but at least this proof-of-concept is working now.
Unfortunately, Iām a little too late to save you the effort, but we recently started providing dev builds of II for local development. This build has the following properties:
Red banner, indicating that it is a dev build
Proof of work disabled for faster browser interaction
Captcha hardcoded to the character āaā so that tests can be automated
WebAuthen replaced by an interaction-less fake implementation
Internet Identity no longer assumes a fixed canister id.
This should allow you to integrate your canister with II the exact same way as it would on mainnet.
Could you quickly check that this works as intended on your M1 mac?
@frederikrothenberger Can you confirm that this is the correct process for testing the dev build? I am not seeing a red banner and I still get the same certificate error as before. Thanks.
git clone https://github.com/dfinity/internet-identity.git
cd internet-identity
npm ci
dfx start --background
# open new terminal window
dfx deploy --argument '(null)'
# manually copy downloaded dev build of internet_identity.wasm
# into ./.dfx/local/canisters/internet_identity folder.
dfx canister install internet_identity --argument '(null)' --mode reinstall
No, if you do not get a red banner, then dfx canister install did rebuild the II canister.
To run it from the II repository, do the following:
git clone https://github.com/dfinity/internet-identity.git
cd internet-identity
dfx start --background
# open new terminal window
export II_FETCH_ROOT_KEY=1
export II_DUMMY_CAPTCHA=1
export II_DUMMY_AUTH=1
export II_DUMMY_POW=1
npm ci
dfx deploy --argument '(null)'
Also, if you want to run II in your own project (without bothering with the II repo) you can just reference the prebuilt dev internet_identity.wasm in your dfx.json like so:
{
"canisters": {
"your_canister": {
...
},
"internet_identity": {
"candid": "internet_identity.did", // relative path to II did file. You can grab that from here: https://github.com/dfinity/internet-identity/blob/main/src/internet_identity/internet_identity.did
"type": "custom",
"wasm": "internet_identity.wasm" // relative path to dev build wasm
}
},
"networks": {
"local": {
"bind": "0.0.0.0:8000",
"type": "ephemeral"
}
},
"version": 1
}
Thereās also going to be a new "remote" config coming to dfx.json in the next version. Together with the development build, we should be able to simplify the developer experience for identity in the near future