Hi I’m developing a Dapp that utilizes both II authentication (using @dfinity/auth-client & @dfinity/agent), as well as Plug Authentication. I’ve been able to get authentication and canister calls to work using II. using Plug, I can also successfully authenticate, however, when I try to make a canister call, I get a failure with the error:
Error: Invalid certificate: Signature verification failed
An example of a motoko canister method that works with II, but not with Plug, looks like this:
public shared func release(user: Principal) : async Types.Released {
if (Principal.equal(user, anonymous)){return false;};
custodians := List.push(user, custodians);
released := true;
return released;
};
The Method I use to Create my Plug Auth looks like this:
export class IC_PlugAuth {
constructor(authButton, iface, whitelist, canisterId) {
this.is = 'INTERNET_COMPUTER_PLUG_AUTH';
this.AUTH_BUTTON = authButton;
this.CANISTER_WHITE_LIST = whitelist;
this.CANISTER_ID = canisterId;
this.INTERFACE = iface;
this.AGENT = undefined;
this.ACTOR = undefined;
this.PRINCIPAL = undefined;
}
async authenticate(){
if(this.CANISTER_WHITE_LIST.length == 0 || this.CANISTER_ID == undefined || this.INTERFACE == undefined)
return;
const whitelist = this.CANISTER_WHITE_LIST;
const onConnectionUpdate = this.onConnectionUpdate;
this.AUTH_BUTTON.box.userData.loggedIn = await window.ic?.plug?.requestConnect({
whitelist,
onConnectionUpdate,
});
this.PRINCIPAL = window.ic.plug.agent.principal;
}
async createActor(){
if (window.ic.plug?.agent) {
this.ACTOR = await window.ic.plug.createActor({
canisterId: this.CANISTER_ID,
interfaceFactory: this.INTERFACE,
});
};
return this.ACTOR
}
async logout(){
await window.ic.plug.disconnect();
}
async onConnectionUpdate(){
await this.createActor();
}
}
And make calls on the actor as follows:
this.released = await this.ACTOR.release(this.ACTIVE_AUTH.PRINCIPAL);
For comparison, my working II Auth object looks like this:
export class IC_IIAuth {
constructor(authButton, canisterId, AuthClient, HttpAgent, createActor, idProvider) {
this.is = 'INTERNET_COMPUTER_II_AUTH';
this.AUTH_BUTTON = authButton;
this.CANISTER_ID = canisterId;
this.AUTH_CLIENT = AuthClient;
this.HTTP_AGENT = HttpAgent;
this.CREATE_ACTOR = createActor;
this.ID_PROVIDER = idProvider;
this.CLIENT = undefined;
this.AGENT = undefined;
this.ACTOR = undefined;
this.PRINCIPAL = undefined;
}
async authenticate(){
try{
this.CLIENT = await this.AUTH_CLIENT.create();
}catch(err){
console.log(err);
}
try{
await new Promise((resolve) => {
this.CLIENT.login({
identityProvider: this.ID_PROVIDER,
onSuccess: resolve,
});
});
}catch(err){
console.log(err);
}
this.AUTH_BUTTON.box.userData.loggedIn = true;
const identity = this.CLIENT.getIdentity();
this.PRINCIPAL = identity.getPrincipal();
this.AGENT = new this.HTTP_AGENT({identity});
}
async createActor(){
const agent = this.AGENT;
this.ACTOR = this.CREATE_ACTOR(this.CANISTER_ID, {
agent,
});
return this.ACTOR
}
async logout(){
await this.CLIENT.logout();
}
}
I can’t track down what the difference is, anyone out there who has some ideas, I’d be appreciative.