Below is my code where I am authentication the session key at the time of login.
I am able to authenticate it. But, when I call the backend canister whoami(), it throws error
Error fetching principal ID: Error: bad secret key size
at webpack_modules…/node_modules/tweetnacl/nacl-fast.js.nacl.sign (nacl-fast.js:2271:1)
at webpack_modules…/node_modules/tweetnacl/nacl-fast.js.nacl.sign.detached (nacl-fast.js:2290:1)
at SessionIdentity.sign (ed25519.js:103:41)
at SessionIdentity.sign (auth.js:32:1)
at DelegationIdentity.sign (delegation.js:206:1)
at DelegationIdentity.transformRequest (delegation.js:213:1)
at async HttpAgent.query (index.js:251:1)
at async caller (actor.js:155:1)
at async callWhoami (auth.js:127:1)
at async webpack_modules…/src/frontend/src/auth.js.document.getElementById.onclick (auth.js:139:1)
callWhoami @ auth.js:131
await in callWhoami
webpack_modules…/src/frontend/src/auth.js.document.getElementById.onclick @ auth.js:139Understand this errorAI
Below is my code
import { createActor, backend } from ‘…/…/declarations/backend’;
import { AuthClient } from ‘@dfinity/auth-client’;
import { HttpAgent, DerEncodedPublicKey } from ‘@dfinity/agent’;
import { fromHexString } from ‘@dfinity/candid’;
import { Ed25519KeyIdentity, Ed25519PublicKey } from ‘@dfinity/identity’;
import { IdbStorage } from ‘@dfinity/auth-client/lib/cjs/storage’;
// Initialize the actor with the backend
let actor = backend;
let authClient; // Declare authClient globally
let result;
// Helper function to convert ArrayBuffer to hex string
const bytesToHex = (buffer) => {
return Array.from(new Uint8Array(buffer), (byte) =>
byte.toString(16).padStart(2, ‘0’)
).join(‘’);
};
// SessionIdentity class definition
class SessionIdentity extends Ed25519KeyIdentity {
constructor(publicKey) {
super(publicKey); // Call the constructor of Ed25519KeyIdentity
this.publicKey = publicKey;
}
getPublicKey() {
return this.publicKey;
}
async sign(blob) {
const signature = await super.sign(blob); // Use the sign method from Ed25519KeyIdentity
return signature;
}
}
// Function to handle login and setup authentication
const setupAuth = async () => {
const url = new URL(window.location.href);
const sessionKey = url.searchParams.get(‘sessionkey’) ?? ‘’; // Extract session key from the URL
let options = { storage: new IdbStorage() };
if (sessionKey) {
const derPublicKey = fromHexString(sessionKey)
const publicKey = Ed25519PublicKey.fromDer(derPublicKey);
options.identity = new SessionIdentity(publicKey);
// Create the Auth instance with options
authClient = await AuthClient.create(options); // Initialize authClient here
console.log('auth: ', authClient);
// Start the login process and wait for it to finish
await new Promise((resolve) => {
authClient.login({
identityProvider: process.env.II_URL,
onSuccess: resolve,
});
});
// Check if authenticated using the auth instance
if (await authClient.isAuthenticated()) {
console.log('Successfully authenticated');
const identity = authClient.getIdentity();
const agent = new HttpAgent({ identity: identity });
// Create an actor to interact with the backend
actor = createActor(process.env.BACKEND_CANISTER_ID, {
agent,
});
console.log('actor: ', actor);
console.log('identity: ', identity);
const delegations = identity._delegation.delegations.map(
(delegation) => ({
delegation: {
expiration: delegation.delegation.expiration.toString(),
pubkey: bytesToHex(delegation.delegation.pubkey),
},
signature: bytesToHex(delegation.signature),
principalID: identity.getPrincipal().toString()
})
);
const publicKey = bytesToHex(identity._inner.getPublicKey().toDer());
// Create the final structure
result = {
delegations,
publicKey,
};
console.log(JSON.stringify(result, null, 2));
} else {
console.error('Authentication failed');
}
} else {
console.log(‘Session key is not present’);
}
};
// Function to handle logout
const handleLogout = async () => {
if (!authClient) {
console.error(‘Auth client is not initialized’);
return; // Exit if authClient is not initialized
}
try {
await authClient.logout(); // Call the logout method
console.log(“Successfully logged out”);
// Update the UI after logout
document.getElementById("getData").innerText = ""; // Clear data message
document.getElementById("login").style.display = "block"; // Show login button
document.getElementById("logout").style.display = "none"; // Hide logout button
} catch (error) {
console.error(‘Error during logout:’, error);
}
};
const callWhoami = async () => {
try {
const principalID = await actor.whoami(); // Call the whoami() method on the actor
console.log(“Principal ID:”, principalID);
document.getElementById(“logging”).innerText = principalID.toString(); // Display principal ID in the UI
} catch (error) {
console.error(“Error fetching principal ID:”, error);
}
};
// Example event listener for a button to call whoami
document.getElementById(“getData”).onclick = async (e) => {
e.preventDefault();
await callWhoami(); // Then call whoami
};
document.getElementById(“login”).onclick = async (e) => {
e.preventDefault();
await setupAuth(); // Ensure authentication is set up first
};
const logoutButton = document.getElementById(“logout”);
logoutButton.onclick = async (e) => {
e.preventDefault();
await handleLogout(); // Call the handleLogout function to log out
return false;
};
My usecase is, firsy I want to authenticate using session key with inter identitty and then call backend canister funcs.
Please help here.