Skip to content

Commit e3b8a0f

Browse files
committed
feat(internet-identity): update for @icp-sdk/auth v6 API
1 parent 603096d commit e3b8a0f

1 file changed

Lines changed: 23 additions & 27 deletions

File tree

skills/internet-identity/SKILL.md

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Internet Identity (II) is the Internet Computer's native authentication system.
1616

1717
## Prerequisites
1818

19-
- `@icp-sdk/auth` (>= 5.0.0), `@icp-sdk/core` (>= 5.0.0)
19+
- `@icp-sdk/auth` (>= 6.0.0), `@icp-sdk/core` (>= 5.0.0)
2020

2121
## Canister IDs
2222

@@ -31,11 +31,11 @@ Internet Identity (II) is the Internet Computer's native authentication system.
3131

3232
2. **Setting delegation expiry too long.** Maximum delegation expiry is 30 days (2_592_000_000_000_000 nanoseconds). Longer values are silently clamped, which causes confusing session behavior. Use 8 hours for normal apps, 30 days maximum for "remember me" flows.
3333

34-
3. **Not handling auth callbacks.** The `authClient.login()` call requires `onSuccess` and `onError` callbacks. Without them, login failures are silently swallowed.
34+
3. **Not awaiting `signIn()` or skipping the `try`/`catch`.** `authClient.signIn()` returns a promise that rejects when the user closes the popup or authentication fails. Without `await` and a `catch`, those failures are silently swallowed.
3535

3636
4. **Using `shouldFetchRootKey` or `fetchRootKey()` instead of the `ic_env` cookie.** The `ic_env` cookie (set by the asset canister or the Vite dev server) already contains the root key as `IC_ROOT_KEY`. Pass it via the `rootKey` option to `HttpAgent.create()` — this works in both local and production environments without environment branching. See the icp-cli skill's `references/binding-generation.md` for the pattern. Never call `fetchRootKey()` — it fetches the root key from the replica at runtime, which lets a man-in-the-middle substitute a fake key on mainnet.
3737

38-
5. **Getting `2vxsx-fae` as the principal after login.** That is the anonymous principal -- it means authentication silently failed. Common causes: wrong `identityProvider` URL, missing `onSuccess` callback, or not extracting the identity from `authClient.getIdentity()` after login.
38+
5. **Getting `2vxsx-fae` as the principal after login.** That is the anonymous principal -- it means authentication silently failed. Common causes: wrong `identityProvider` URL passed to the `AuthClient` constructor, an unhandled rejection from `signIn()`, or reading `getIdentity()` before `signIn()` resolved.
3939

4040
6. **Passing principal as string to backend.** The `AuthClient` gives you an `Identity` object. Backend canister methods receive the caller principal automatically via the IC protocol -- you do not pass it as a function argument. The caller principal is available on the backend via `shared(msg) { msg.caller }` in Motoko or `ic_cdk::api::msg_caller()` in Rust. For backend access control patterns, see the **canister-security** skill.
4141

@@ -71,9 +71,6 @@ import { AuthClient } from "@icp-sdk/auth/client";
7171
import { HttpAgent, Actor } from "@icp-sdk/core/agent";
7272
import { safeGetCanisterEnv } from "@icp-sdk/core/agent/canister-env";
7373
74-
// Module-scoped so login/logout/createAuthenticatedActor can access it.
75-
let authClient;
76-
7774
// Read the ic_env cookie (set by the asset canister or Vite dev server).
7875
// Contains the root key and canister IDs — works in both local and production.
7976
const canisterEnv = safeGetCanisterEnv();
@@ -91,24 +88,26 @@ function getIdentityProviderUrl() {
9188
return "https://id.ai";
9289
}
9390
94-
// Login
91+
// Construct once — identityProvider (and optionally derivationOrigin or
92+
// openIdProvider for one-click sign-in: 'google' | 'apple' | 'microsoft')
93+
// are configured at construction time, not per sign-in.
94+
const authClient = new AuthClient({
95+
identityProvider: getIdentityProviderUrl(),
96+
});
97+
98+
// Login: signIn() returns the new Identity directly and rejects if the user
99+
// closes the popup or authentication fails.
95100
async function login() {
96-
return new Promise((resolve, reject) => {
97-
authClient.login({
98-
identityProvider: getIdentityProviderUrl(),
101+
try {
102+
const identity = await authClient.signIn({
99103
maxTimeToLive: BigInt(8) * BigInt(3_600_000_000_000), // 8 hours in nanoseconds
100-
onSuccess: () => {
101-
const identity = authClient.getIdentity();
102-
const principal = identity.getPrincipal().toText();
103-
console.log("Logged in as:", principal);
104-
resolve(identity);
105-
},
106-
onError: (error) => {
107-
console.error("Login failed:", error);
108-
reject(error);
109-
},
110104
});
111-
});
105+
console.log("Logged in as:", identity.getPrincipal().toText());
106+
return identity;
107+
} catch (error) {
108+
console.error("Login failed:", error);
109+
throw error;
110+
}
112111
}
113112
114113
// Logout
@@ -132,12 +131,9 @@ async function createAuthenticatedActor(identity, canisterId, idlFactory) {
132131
// Initialization — wraps async setup in a function so this code works with
133132
// any bundler target (Vite defaults to es2020 which lacks top-level await).
134133
async function init() {
135-
authClient = await AuthClient.create();
136-
137-
// Check if already authenticated (on page load)
138-
const isAuthenticated = await authClient.isAuthenticated();
139-
if (isAuthenticated) {
140-
const identity = authClient.getIdentity();
134+
// isAuthenticated() is sync; getIdentity() is async.
135+
if (authClient.isAuthenticated()) {
136+
const identity = await authClient.getIdentity();
141137
const actor = await createAuthenticatedActor(identity, canisterId, idlFactory);
142138
// Use actor to call backend methods
143139
}

0 commit comments

Comments
 (0)