Added Google LIT protocol web3 auth
This commit is contained in:
parent
2f40f3f5ac
commit
7803294d6f
@ -31,12 +31,20 @@
|
||||
"dependencies": {
|
||||
"@graphql-tools/graphql-file-loader": "^8.0.0",
|
||||
"@graphql-tools/load": "^8.0.0",
|
||||
"@iconify/svelte": "^3.1.4",
|
||||
"@lit-protocol/auth-helpers": "^2.2.50",
|
||||
"@lit-protocol/constants": "^2.2.50",
|
||||
"@lit-protocol/lit-auth-client": "^2.2.50",
|
||||
"@lit-protocol/lit-node-client": "^2.2.50",
|
||||
"@lit-protocol/pkp-client": "^2.2.50",
|
||||
"@lit-protocol/types": "^2.2.50",
|
||||
"@tanstack/svelte-query": "^4.29.1",
|
||||
"@wundergraph/sdk": "^0.174.5",
|
||||
"@wundergraph/svelte-query": "^0.3.10",
|
||||
"axios": "^1.4.0",
|
||||
"cookie": "^0.5.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"ethers": "^6.7.1",
|
||||
"graphql": "^16.8.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jsonwebtoken": "^9.0.1",
|
||||
|
3005
pnpm-lock.yaml
generated
3005
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,14 @@
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<script>
|
||||
global = window;
|
||||
window.process = {
|
||||
env: {
|
||||
NODE_ENV: 'development'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
|
203
src/lib/GoogleAuth.svelte
Normal file
203
src/lib/GoogleAuth.svelte
Normal file
@ -0,0 +1,203 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import {
|
||||
isSignInRedirect,
|
||||
getProviderFromUrl,
|
||||
} from "@lit-protocol/lit-auth-client";
|
||||
import type { IRelayPKP } from "@lit-protocol/types";
|
||||
import Icon from "@iconify/svelte";
|
||||
import { createLitSession } from "./createLitSession";
|
||||
import { connectProvider } from "./setupLit";
|
||||
import { ethers } from "ethers";
|
||||
|
||||
const redirectUri = "http://localhost:3000/";
|
||||
|
||||
let sessionSigs, error, currentPKP, authMethod, provider;
|
||||
let messageToSign = { user: "Sam", loggedIn: true, signature: "" };
|
||||
let status = "Initializing...";
|
||||
let jsonObjectToVerify = null;
|
||||
let pkps: IRelayPKP[] = [];
|
||||
let view = "SIGN_IN";
|
||||
|
||||
onMount(() => {
|
||||
initialize();
|
||||
});
|
||||
|
||||
async function initialize() {
|
||||
status = "Connecting to Google provider...";
|
||||
try {
|
||||
provider = await connectProvider();
|
||||
status = "Connected to Google provider.";
|
||||
if (isSignInRedirect(redirectUri)) {
|
||||
const providerName = getProviderFromUrl();
|
||||
if (providerName) {
|
||||
await handleRedirect(providerName);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function authWithGoogle() {
|
||||
try {
|
||||
if (!provider) {
|
||||
provider = await connectProvider();
|
||||
status = "Reconnected to Google provider.";
|
||||
}
|
||||
await provider.signIn();
|
||||
status = "Signed in with Google.";
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleRedirect(providerName: string) {
|
||||
try {
|
||||
if (!provider) throw new Error("Invalid provider.");
|
||||
authMethod = await provider.authenticate();
|
||||
status = "Authenticated successfully.";
|
||||
pkps = await provider.fetchPKPsThroughRelayer(authMethod);
|
||||
status = "Fetched PKPs.";
|
||||
if (pkps.length === 0) {
|
||||
status = "No PKPs found. Minting...";
|
||||
await mint();
|
||||
} else {
|
||||
// Update the view to 'PKP' to show the available PKPs
|
||||
view = "PKP";
|
||||
}
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function mint() {
|
||||
const newPKP: IRelayPKP = await mintPkp(provider, authMethod);
|
||||
pkps = [...pkps, newPKP];
|
||||
status = "New PKP minted.";
|
||||
await createSession(newPKP);
|
||||
}
|
||||
|
||||
async function createSession(pkp: IRelayPKP) {
|
||||
try {
|
||||
currentPKP = pkp; // Assign the selected PKP to currentPKP
|
||||
sessionSigs = await createLitSession(provider, pkp.publicKey, authMethod);
|
||||
status = "Session created successfully.";
|
||||
view = "READY";
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
}
|
||||
}
|
||||
|
||||
function setError(err) {
|
||||
error = err;
|
||||
view = "ERROR";
|
||||
status = `Error: ${err.message}`;
|
||||
}
|
||||
|
||||
async function signMessageWithPKP() {
|
||||
try {
|
||||
// Create a specific JSON object
|
||||
const jsonString = JSON.stringify(messageToSign);
|
||||
|
||||
// Convert the JSON string to an array of character codes
|
||||
const toSign = ethers.getBytes(ethers.hashMessage(jsonString));
|
||||
|
||||
const litActionCode = `
|
||||
const go = async () => {
|
||||
const sigShare = await LitActions.signEcdsa({ toSign, publicKey, sigName });
|
||||
};
|
||||
go();
|
||||
`;
|
||||
|
||||
// Sign message
|
||||
const results = await litNodeClient.executeJs({
|
||||
code: litActionCode,
|
||||
sessionSigs: sessionSigs,
|
||||
jsParams: {
|
||||
toSign: toSign,
|
||||
publicKey: currentPKP.publicKey,
|
||||
sigName: "sig1",
|
||||
},
|
||||
});
|
||||
|
||||
// Get signature
|
||||
const result = results.signatures["sig1"];
|
||||
const signature = ethers.Signature.from({
|
||||
r: "0x" + result.r,
|
||||
s: "0x" + result.s,
|
||||
v: result.recid,
|
||||
});
|
||||
|
||||
// Add the signature to the JSON object
|
||||
messageToSign.signature = signature;
|
||||
|
||||
jsonObjectToVerify = { ...messageToSign };
|
||||
|
||||
console.log(
|
||||
"JSON object to sign: " + JSON.stringify(jsonObjectToVerify, null, 2)
|
||||
);
|
||||
|
||||
// Display the signed JSON
|
||||
status = JSON.stringify(messageToSign, null, 2);
|
||||
|
||||
// Verify the signature
|
||||
const recoveredAddr = ethers.verifyMessage(jsonString, signature);
|
||||
|
||||
// Check if the address associated with the signature is the same as the current PKP
|
||||
const verified =
|
||||
currentPKP.ethAddress.toLowerCase() === recoveredAddr.toLowerCase();
|
||||
|
||||
if (verified) {
|
||||
status = "The signature is valid.";
|
||||
} else {
|
||||
status = "The signature is invalid.";
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
setError(err);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex items-center justify-center h-screen">
|
||||
<div>
|
||||
{#if error}
|
||||
<div class="mt-4 text-center">
|
||||
<h1>Error</h1>
|
||||
<p>{error.message}</p>
|
||||
</div>
|
||||
{:else if view === "SIGN_IN"}
|
||||
<button on:click={authWithGoogle} class="btn variant-filled">
|
||||
<span><Icon icon="flat-color-icons:google" /></span>
|
||||
<span>Sign in with Google</span>
|
||||
</button>
|
||||
{/if}
|
||||
{#if view === "PKP"}
|
||||
<div>
|
||||
<h1>Select a PKP</h1>
|
||||
<ul>
|
||||
{#each pkps as pkp (pkp.publicKey)}
|
||||
<li>
|
||||
<button on:click={() => createSession(pkp)}>Use this PKP</button>
|
||||
<pre>{JSON.stringify(pkp, null, 2)}</pre>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
{#if view === "READY"}
|
||||
<div>
|
||||
<h1>Ready to sign</h1>
|
||||
<button on:click={signMessageWithPKP}>Sign Message</button>
|
||||
{#if messageToSign}
|
||||
<pre>{JSON.stringify(messageToSign)}</pre>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<div class="mt-4 text-center">
|
||||
<h1>Status</h1>
|
||||
<p>{status}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
23
src/lib/createLitSession.ts
Normal file
23
src/lib/createLitSession.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { IProvider } from '$lib/services/provider/IProvider';
|
||||
import { LitAccessControlConditionResource, LitAbility } from '@lit-protocol/auth-helpers';
|
||||
|
||||
export async function createLitSession(
|
||||
provider: IProvider,
|
||||
pkpPublicKey: string,
|
||||
authMethod: any,
|
||||
): Promise<any> {
|
||||
const litResource = new LitAccessControlConditionResource('*');
|
||||
return await provider.getSessionSigs({
|
||||
pkpPublicKey,
|
||||
authMethod,
|
||||
sessionSigsParams: {
|
||||
chain: 'ethereum',
|
||||
resourceAbilityRequests: [
|
||||
{
|
||||
resource: litResource,
|
||||
ability: LitAbility.PKPSigning
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -3 30 30">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5229 6.47715 22 12 22C17.5229 22 22 17.5229 22 12C22 6.47715 17.5229 2 12 2ZM0 12C0 5.3726 5.3726 0 12 0C18.6274 0 24 5.3726 24 12C24 18.6274 18.6274 24 12 24C5.3726 24 0 18.6274 0 12Z"
|
||||
fill="rgba(0,0,0,0.7)"
|
||||
stroke="none"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M9.59162 22.7357C9.49492 22.6109 9.49492 21.4986 9.59162 19.399C8.55572 19.4347 7.90122 19.3628 7.62812 19.1833C7.21852 18.9139 6.80842 18.0833 6.44457 17.4979C6.08072 16.9125 5.27312 16.8199 4.94702 16.6891C4.62091 16.5582 4.53905 16.0247 5.84562 16.4282C7.15222 16.8316 7.21592 17.9303 7.62812 18.1872C8.04032 18.4441 9.02572 18.3317 9.47242 18.1259C9.91907 17.9201 9.88622 17.1538 9.96587 16.8503C10.0666 16.5669 9.71162 16.5041 9.70382 16.5018C9.26777 16.5018 6.97697 16.0036 6.34772 13.7852C5.71852 11.5669 6.52907 10.117 6.96147 9.49369C7.24972 9.07814 7.22422 8.19254 6.88497 6.83679C8.11677 6.67939 9.06732 7.06709 9.73672 7.99999C9.73737 8.00534 10.6143 7.47854 12.0001 7.47854C13.386 7.47854 13.8777 7.90764 14.2571 7.99999C14.6365 8.09234 14.94 6.36699 17.2834 6.83679C16.7942 7.79839 16.3844 8.99999 16.6972 9.49369C17.0099 9.98739 18.2372 11.5573 17.4833 13.7852C16.9807 15.2706 15.9927 16.1761 14.5192 16.5018C14.3502 16.5557 14.2658 16.6427 14.2658 16.7627C14.2658 16.9427 14.4942 16.9624 14.8233 17.8058C15.0426 18.368 15.0585 19.9739 14.8708 22.6234C14.3953 22.7445 14.0254 22.8257 13.7611 22.8673C13.2924 22.9409 12.7835 22.9822 12.2834 22.9982C11.7834 23.0141 11.6098 23.0123 10.9185 22.948C10.4577 22.9051 10.0154 22.8343 9.59162 22.7357Z"
|
||||
fill="rgba(0,0,0,0.7)"
|
||||
stroke="none"
|
||||
/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.7 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.1566,22.8189c-10.4-14.8851-30.94-19.2971-45.7914-9.8348L22.2825,29.6078A29.9234,29.9234,0,0,0,8.7639,49.6506a31.5136,31.5136,0,0,0,3.1076,20.2318A30.0061,30.0061,0,0,0,7.3953,81.0653a31.8886,31.8886,0,0,0,5.4473,24.1157c10.4022,14.8865,30.9423,19.2966,45.7914,9.8348L84.7167,98.3921A29.9177,29.9177,0,0,0,98.2353,78.3493,31.5263,31.5263,0,0,0,95.13,58.117a30,30,0,0,0,4.4743-11.1824,31.88,31.88,0,0,0-5.4473-24.1157" style="fill:#ff3e00"/><path d="M45.8171,106.5815A20.7182,20.7182,0,0,1,23.58,98.3389a19.1739,19.1739,0,0,1-3.2766-14.5025,18.1886,18.1886,0,0,1,.6233-2.4357l.4912-1.4978,1.3363.9815a33.6443,33.6443,0,0,0,10.203,5.0978l.9694.2941-.0893.9675a5.8474,5.8474,0,0,0,1.052,3.8781,6.2389,6.2389,0,0,0,6.6952,2.485,5.7449,5.7449,0,0,0,1.6021-.7041L69.27,76.281a5.4306,5.4306,0,0,0,2.4506-3.631,5.7948,5.7948,0,0,0-.9875-4.3712,6.2436,6.2436,0,0,0-6.6978-2.4864,5.7427,5.7427,0,0,0-1.6.7036l-9.9532,6.3449a19.0329,19.0329,0,0,1-5.2965,2.3259,20.7181,20.7181,0,0,1-22.2368-8.2427,19.1725,19.1725,0,0,1-3.2766-14.5024,17.9885,17.9885,0,0,1,8.13-12.0513L55.8833,23.7472a19.0038,19.0038,0,0,1,5.3-2.3287A20.7182,20.7182,0,0,1,83.42,29.6611a19.1739,19.1739,0,0,1,3.2766,14.5025,18.4,18.4,0,0,1-.6233,2.4357l-.4912,1.4978-1.3356-.98a33.6175,33.6175,0,0,0-10.2037-5.1l-.9694-.2942.0893-.9675a5.8588,5.8588,0,0,0-1.052-3.878,6.2389,6.2389,0,0,0-6.6952-2.485,5.7449,5.7449,0,0,0-1.6021.7041L37.73,51.719a5.4218,5.4218,0,0,0-2.4487,3.63,5.7862,5.7862,0,0,0,.9856,4.3717,6.2437,6.2437,0,0,0,6.6978,2.4864,5.7652,5.7652,0,0,0,1.602-.7041l9.9519-6.3425a18.978,18.978,0,0,1,5.2959-2.3278,20.7181,20.7181,0,0,1,22.2368,8.2427,19.1725,19.1725,0,0,1,3.2766,14.5024,17.9977,17.9977,0,0,1-8.13,12.0532L51.1167,104.2528a19.0038,19.0038,0,0,1-5.3,2.3287" style="fill:#fff"/></svg>
|
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 352 KiB |
Binary file not shown.
Before Width: | Height: | Size: 113 KiB |
30
src/lib/setupLit.ts
Normal file
30
src/lib/setupLit.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// litProviderSetup.ts
|
||||
|
||||
import {
|
||||
LitAuthClient,
|
||||
GoogleProvider,
|
||||
BaseProvider,
|
||||
} from '@lit-protocol/lit-auth-client';
|
||||
import { ProviderType } from '@lit-protocol/constants';
|
||||
import { LitNodeClient } from '@lit-protocol/lit-node-client';
|
||||
|
||||
let provider: BaseProvider | undefined;
|
||||
|
||||
export async function connectProvider() {
|
||||
const litNodeClient = new LitNodeClient({
|
||||
litNetwork: 'serrano',
|
||||
debug: false
|
||||
});
|
||||
await litNodeClient.connect();
|
||||
|
||||
const litAuthClient = new LitAuthClient({
|
||||
litRelayConfig: {
|
||||
relayApiKey: 'test-api-key'
|
||||
},
|
||||
litNodeClient
|
||||
});
|
||||
|
||||
provider = litAuthClient.initProvider<GoogleProvider>(ProviderType.Google);
|
||||
|
||||
return provider;
|
||||
}
|
@ -8,7 +8,6 @@
|
||||
|
||||
const token = Cookies.get("token");
|
||||
|
||||
// Set the Authorization header token
|
||||
if (token) {
|
||||
client.setAuthorizationToken(token);
|
||||
}
|
||||
|
@ -1,24 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { createQuery } from "../lib/wundergraph";
|
||||
import Login from "$lib/Login.svelte";
|
||||
import User from "$lib/User.svelte";
|
||||
|
||||
const projectsQuery = createQuery({
|
||||
operationName: "Projects",
|
||||
});
|
||||
<script>
|
||||
import GoogleAuth from "$lib/GoogleAuth.svelte";
|
||||
</script>
|
||||
|
||||
<Login />
|
||||
<User />
|
||||
|
||||
<br />
|
||||
Projects
|
||||
<div class="results">
|
||||
{#if $projectsQuery.isLoading}
|
||||
<p>Loading...</p>
|
||||
{:else if $projectsQuery.error}
|
||||
<pre>Error: {JSON.stringify($projectsQuery.error, null, 2)}</pre>
|
||||
{:else}
|
||||
<pre>{JSON.stringify($projectsQuery.data, null, 2)}</pre>
|
||||
{/if}
|
||||
</div>
|
||||
<GoogleAuth />
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { prefetchQuery } from '$lib/wundergraph';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { queryClient } = await parent();
|
||||
|
||||
await prefetchQuery(
|
||||
{
|
||||
operationName: 'Dragons',
|
||||
},
|
||||
queryClient
|
||||
);
|
||||
};
|
24
src/routes/me/+page.svelte
Normal file
24
src/routes/me/+page.svelte
Normal file
@ -0,0 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { createQuery } from "../../lib/wundergraph";
|
||||
import Login from "$lib/Login.svelte";
|
||||
import User from "$lib/User.svelte";
|
||||
|
||||
const projectsQuery = createQuery({
|
||||
operationName: "Projects",
|
||||
});
|
||||
</script>
|
||||
|
||||
<Login />
|
||||
<User />
|
||||
|
||||
<br />
|
||||
Projects
|
||||
<div class="results">
|
||||
{#if $projectsQuery.isLoading}
|
||||
<p>Loading...</p>
|
||||
{:else if $projectsQuery.error}
|
||||
<pre>Error: {JSON.stringify($projectsQuery.error, null, 2)}</pre>
|
||||
{:else}
|
||||
<pre>{JSON.stringify($projectsQuery.data, null, 2)}</pre>
|
||||
{/if}
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user