Skip to content

Commit 60ddb08

Browse files
authored
Add missing lib to try-ii (#3162)
add lib
1 parent fbd6952 commit 60ddb08

File tree

15 files changed

+619
-0
lines changed

15 files changed

+619
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dist-showcase/
1818
.env
1919
lib
2020
!src/frontend/src/lib
21+
!src/try-ii/src/try-ii-frontend/src/lib
2122
/.svelte-kit
2223

2324
# Cargo build output
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import type { SignIdentity, Signature } from "@dfinity/agent";
2+
import {
3+
Delegation,
4+
DelegationChain,
5+
DelegationIdentity,
6+
type SignedDelegation,
7+
} from "@dfinity/identity";
8+
import { Principal } from "@dfinity/principal";
9+
10+
// The type of response from II as per the spec
11+
interface AuthResponseSuccess {
12+
kind: "authorize-client-success";
13+
delegations: {
14+
delegation: {
15+
pubkey: Uint8Array;
16+
expiration: bigint;
17+
targets?: Principal[];
18+
};
19+
signature: Uint8Array;
20+
}[];
21+
userPublicKey: Uint8Array;
22+
authnMethod: "pin" | "passkey" | "recovery";
23+
}
24+
25+
// Perform a sign in to II using parameters set in this app
26+
export const authWithII = async ({
27+
url: url_,
28+
maxTimeToLive,
29+
allowPinAuthentication,
30+
derivationOrigin,
31+
sessionIdentity,
32+
autoSelectionPrincipal,
33+
}: {
34+
url: string;
35+
maxTimeToLive?: bigint;
36+
allowPinAuthentication?: boolean;
37+
derivationOrigin?: string;
38+
autoSelectionPrincipal?: string;
39+
sessionIdentity: SignIdentity;
40+
}): Promise<{ identity: DelegationIdentity; authnMethod: string }> => {
41+
// Figure out the II URL to use
42+
const iiUrl = new URL(url_);
43+
iiUrl.hash = "#authorize";
44+
45+
// Open an II window and kickstart the flow
46+
const win = window.open(iiUrl, "ii-window");
47+
if (win === null) {
48+
throw new Error(`Could not open window for '${iiUrl}'`);
49+
}
50+
51+
// Wait for II to say it's ready
52+
const evnt = await new Promise<MessageEvent>((resolve) => {
53+
const readyHandler = (e: MessageEvent) => {
54+
if (e.origin !== iiUrl.origin) {
55+
// Ignore messages from other origins (e.g. from a metamask extension)
56+
return;
57+
}
58+
window.removeEventListener("message", readyHandler);
59+
resolve(e);
60+
};
61+
window.addEventListener("message", readyHandler);
62+
});
63+
64+
if (evnt.data.kind !== "authorize-ready") {
65+
throw new Error("Bad message from II window: " + JSON.stringify(evnt));
66+
}
67+
68+
// Send the request to II
69+
const sessionPublicKey: Uint8Array = new Uint8Array(
70+
sessionIdentity.getPublicKey().toDer()
71+
);
72+
73+
const request = {
74+
kind: "authorize-client",
75+
sessionPublicKey,
76+
maxTimeToLive,
77+
derivationOrigin,
78+
allowPinAuthentication,
79+
autoSelectionPrincipal,
80+
};
81+
82+
win.postMessage(request, iiUrl.origin);
83+
84+
// Wait for the II response and update the local state
85+
const response = await new Promise<MessageEvent>((resolve) => {
86+
const responseHandler = (e: MessageEvent) => {
87+
if (e.origin !== iiUrl.origin) {
88+
// Ignore messages from other origins (e.g. from a metamask extension)
89+
return;
90+
}
91+
window.removeEventListener("message", responseHandler);
92+
win.close();
93+
resolve(e);
94+
};
95+
window.addEventListener("message", responseHandler);
96+
});
97+
98+
const message = response.data;
99+
if (message.kind !== "authorize-client-success") {
100+
throw new Error("Bad reply: " + JSON.stringify(message));
101+
}
102+
103+
const identity = identityFromResponse({
104+
response: message as AuthResponseSuccess,
105+
sessionIdentity,
106+
});
107+
108+
return { identity, authnMethod: message.authnMethod };
109+
};
110+
111+
// Read delegations the delegations from the response
112+
const identityFromResponse = ({
113+
sessionIdentity,
114+
response,
115+
}: {
116+
sessionIdentity: SignIdentity;
117+
response: AuthResponseSuccess;
118+
}): DelegationIdentity => {
119+
const delegations = response.delegations.map(extractDelegation);
120+
121+
const delegationChain = DelegationChain.fromDelegations(
122+
delegations,
123+
response.userPublicKey.buffer
124+
);
125+
126+
const identity = DelegationIdentity.fromDelegation(
127+
sessionIdentity,
128+
delegationChain
129+
);
130+
131+
return identity;
132+
};
133+
134+
// Infer the type of an array's elements
135+
type ElementOf<Arr> = Arr extends readonly (infer ElementOf)[]
136+
? ElementOf
137+
: "argument is not an array";
138+
139+
export const extractDelegation = (
140+
signedDelegation: ElementOf<AuthResponseSuccess["delegations"]>
141+
): SignedDelegation => ({
142+
delegation: new Delegation(
143+
signedDelegation.delegation.pubkey,
144+
signedDelegation.delegation.expiration,
145+
signedDelegation.delegation.targets
146+
),
147+
signature: signedDelegation.signature
148+
.buffer as Signature /* brand type for agent-js */,
149+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<script lang="ts">
2+
import type { HTMLAttributes } from "svelte/elements";
3+
4+
type Color = "surface";
5+
type Size = "sm" | "md" | "lg";
6+
7+
type Props = HTMLAttributes<HTMLDivElement> & {
8+
color?: Color;
9+
size?: Size;
10+
};
11+
12+
const {
13+
children,
14+
class: className,
15+
color = "surface",
16+
size = "md",
17+
...props
18+
}: Props = $props();
19+
</script>
20+
21+
<div
22+
{...props}
23+
class={[
24+
"rounded-full border font-medium",
25+
{
26+
surface: "border-border-tertiary text-text-secondary bg-bg-primary",
27+
}[color],
28+
{
29+
sm: "px-2 py-0.5 text-xs",
30+
md: "px-2 py-0.5 text-sm",
31+
lg: "px-2.5 py-1 text-sm",
32+
}[size],
33+
className,
34+
]}
35+
>
36+
{@render children?.()}
37+
</div>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<script lang="ts">
2+
import ButtonOrAnchor from "$lib/components/ButtonOrAnchor.svelte";
3+
import type {
4+
HTMLAnchorAttributes,
5+
HTMLButtonAttributes,
6+
} from "svelte/elements";
7+
8+
type Variant = "primary" | "secondary" | "tertiary";
9+
type Size = "sm" | "md" | "lg" | "xl";
10+
11+
type Props = HTMLButtonAttributes &
12+
HTMLAnchorAttributes & {
13+
element?: HTMLElement;
14+
variant?: Variant;
15+
size?: Size;
16+
iconOnly?: boolean;
17+
};
18+
19+
let {
20+
children,
21+
element = $bindable(),
22+
class: className,
23+
variant = "primary",
24+
size = "md",
25+
iconOnly,
26+
...props
27+
}: Props = $props();
28+
</script>
29+
30+
<ButtonOrAnchor
31+
bind:element
32+
{...props}
33+
class={[
34+
"box-border flex items-center justify-center justify-self-start rounded-md font-semibold whitespace-nowrap opacity-100",
35+
{
36+
primary: [
37+
"bg-bg-brand-solid text-text-primary-inversed",
38+
"not-disabled:hover:bg-bg-brand-solid_hover",
39+
"disabled:bg-bg-disabled disabled:text-fg-disabled",
40+
],
41+
secondary: [
42+
"bg-bg-primary border-border-secondary text-fg-primary border",
43+
"not-disabled:hover:bg-bg-primary_hover",
44+
"disabled:border-border-disabled disabled:text-fg-disabled",
45+
],
46+
tertiary: [
47+
"text-fg-primary",
48+
"not-disabled:hover:bg-bg-primary_hover",
49+
"disabled:text-fg-disabled",
50+
],
51+
}[variant],
52+
"focus-visible:ring-focus-ring focus-visible:ring-offset-bg-primary outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
53+
{
54+
sm: iconOnly ? "size-9" : "h-9 gap-1.5 px-3 text-sm",
55+
md: iconOnly ? "size-10" : "h-10 gap-1.5 px-3.5 text-sm",
56+
lg: iconOnly ? "size-11" : "text-md h-11 gap-2.5 px-4",
57+
xl: iconOnly ? "size-12" : "text-md h-12 gap-2.5 px-4.5",
58+
}[size],
59+
className,
60+
]}
61+
>
62+
{@render children?.()}
63+
</ButtonOrAnchor>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script lang="ts">
2+
import type {
3+
HTMLButtonAttributes,
4+
HTMLAnchorAttributes,
5+
} from "svelte/elements";
6+
import { nonNullish } from "@dfinity/utils";
7+
8+
type Props = HTMLButtonAttributes &
9+
HTMLAnchorAttributes & {
10+
element?: HTMLElement;
11+
};
12+
13+
let { element = $bindable(), ...props }: Props = $props();
14+
const buttonProps: HTMLButtonAttributes | undefined = !("href" in props)
15+
? props
16+
: undefined;
17+
const anchorProps: HTMLAnchorAttributes | undefined =
18+
"href" in props ? props : undefined;
19+
</script>
20+
21+
{#if nonNullish(buttonProps)}
22+
<button bind:this={element} {...buttonProps}>
23+
{@render buttonProps.children?.()}
24+
</button>
25+
{:else if nonNullish(anchorProps)}
26+
<a bind:this={element} {...anchorProps}>
27+
{@render anchorProps.children?.()}
28+
</a>
29+
{/if}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script lang="ts">
2+
import type { HTMLAttributes } from "svelte/elements";
3+
import { SUPPORT_URL } from "$lib/config";
4+
5+
type Props = HTMLAttributes<HTMLElement>;
6+
7+
const { children, class: className, ...props }: Props = $props();
8+
</script>
9+
10+
<footer
11+
{...props}
12+
class={[
13+
"flex h-14 items-center justify-between px-4 py-3 md:px-6 lg:px-8",
14+
className,
15+
]}
16+
>
17+
<div class="text-text-tertiary text-sm font-medium">© Internet Identity</div>
18+
<nav class="text-text-primary flex gap-4 text-sm font-semibold">
19+
<a href={SUPPORT_URL} target="_blank" rel="noopener">Support</a>
20+
</nav>
21+
</footer>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script lang="ts">
2+
import type { HTMLAttributes } from "svelte/elements";
3+
import Logo from "$lib/components/Logo.svelte";
4+
5+
type Props = HTMLAttributes<HTMLHeadElement>;
6+
7+
const { children, class: className, ...props }: Props = $props();
8+
</script>
9+
10+
<header
11+
{...props}
12+
class={["flex h-14 items-center px-4 py-3 md:px-6 lg:px-8", className]}
13+
>
14+
<!-- TODO: Revert to anchor tag when we create the landing page -->
15+
<div class="flex h-14 items-center gap-4">
16+
<Logo class="text-fg-primary h-5.5" />
17+
<h1 class="text-md text-text-primary font-semibold md:block">
18+
Internet Identity
19+
</h1>
20+
</div>
21+
</header>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
import type { SVGAttributes } from "svelte/elements";
3+
4+
type Props = SVGAttributes<SVGSVGElement>;
5+
6+
const props: Props = $props();
7+
</script>
8+
9+
<svg viewBox="0 0 46 22" {...props}>
10+
<path
11+
d="M45.9992 11C45.9992 4.93463 40.9792 0 34.8188 0C32.2505 0 29.4539 1.33375 26.4911 3.96324C25.0903 5.2064 23.8757 6.5361 22.9637 7.60537C19.7613 3.99235 15.4664 0 11.1804 0C5.99986 0 1.4822 3.63324 0.306661 8.44735C0.308259 8.44331 0.309856 8.43765 0.311453 8.43199C0.309856 8.43765 0.308259 8.4425 0.306661 8.44735C0.106213 9.2675 0 10.1224 0 11C0 17.0654 4.94012 22 11.1005 22C13.6688 22 16.5453 20.6663 19.5081 18.0368C20.9089 16.7936 22.1235 15.4639 23.0355 14.3946C26.2379 18.0076 30.5336 22 34.8196 22C40.0001 22 44.5178 18.3668 45.6933 13.5535C45.8938 12.7333 46 11.8784 46 11.0008L45.9992 11ZM23.823 7.59404C24.8699 6.39779 25.9081 5.34147 26.9127 4.45015C29.7557 1.92662 32.4159 0.647059 34.8188 0.647059C40.6318 0.647059 45.3603 5.29132 45.3603 11C45.3603 11.8007 45.2653 12.6007 45.0768 13.3788C45.0465 13.4685 44.6592 14.5426 43.5555 15.5868C42.122 16.9432 40.179 17.6315 37.78 17.6324C40.3603 16.4968 42.1651 13.9457 42.1651 11C42.1651 6.99551 38.8693 3.73838 34.8188 3.73838C33.24 3.73838 31.3074 4.74375 29.0721 6.72779C28.0667 7.62074 27.0485 8.67059 25.9736 9.92507L25.5519 10.4152L23.3917 8.07529L23.823 7.59485V7.59404ZM20.0017 11.1084C19.1488 12.134 17.9189 13.5316 16.5054 14.7861C13.8716 17.1244 12.1594 17.6146 11.1804 17.6146C7.48605 17.6146 4.47294 14.647 4.47294 11C4.47294 7.35301 7.48286 4.40809 11.1804 4.38544C11.3145 4.38544 11.4766 4.39919 11.6731 4.43478C13.5785 5.17485 15.2804 6.35574 16.3082 7.30853C17.1347 8.07529 18.6321 9.64441 20.0009 11.1076L20.0017 11.1084ZM22.1762 14.406C21.1285 15.6022 20.0911 16.6585 19.0865 17.5499C16.2834 20.0378 13.5218 21.3529 11.1005 21.3529C8.29343 21.3529 5.66126 20.2732 3.68712 18.3126C1.72098 16.3601 0.638878 13.7629 0.638878 11C0.638878 10.1993 0.73471 9.39853 0.92238 8.62125C0.954324 8.52824 1.34164 7.45574 2.44371 6.41316C3.87719 5.05677 5.82018 4.36846 8.21916 4.36765C5.6389 5.50324 3.83407 8.05427 3.83407 11C3.83407 15.0045 7.12988 18.2616 11.1804 18.2616C12.7592 18.2616 14.6918 17.2563 16.9271 15.2722C17.9325 14.3793 18.9507 13.3294 20.0256 12.0749L20.4465 11.584C20.4465 11.584 22.5747 13.8891 22.5979 13.915L22.1754 14.406H22.1762ZM25.9975 10.8916C26.8504 9.86603 28.0803 8.46838 29.4938 7.2139C32.1276 4.87559 33.8398 4.38544 34.8188 4.38544C38.5131 4.38544 41.5263 7.35301 41.5263 11C41.5263 14.647 38.5163 17.5919 34.8188 17.6146C34.6847 17.6146 34.5226 17.6008 34.3253 17.5652C34.3269 17.5652 34.3277 17.566 34.3293 17.5668C32.4222 16.8268 30.7188 15.6451 29.6902 14.6915C28.8637 13.9247 27.3663 12.3556 25.9967 10.8924L25.9975 10.8916ZM45.6885 13.5648C45.6901 13.5607 45.6909 13.5559 45.6925 13.5526C45.6917 13.5559 45.6901 13.5607 45.6885 13.5648Z"
12+
class="fill-current"
13+
/>
14+
</svg>

0 commit comments

Comments
 (0)