Differences between II and Plug Authentication

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.

1 Like