Open CodingFu opened 1 week ago
How can I add user with custom provider there?
This is not yet supported. Providing interfaces for generic custom authentication is tracked in #156.
Is there any way i can "fake" authentication in juno?
I'm not sure what's "fake." Protected features require authenticated users. These are saved within a system collection named #user
. If you are looking to hack around, one thing you could try is handling the reading and setting of such entities yourself. You can replicate the getDoc
and setDoc
methods from https://github.com/junobuild/juno-js/blob/51ecef384e001eab3d9c4aa254eb6df0b1a3a9f8/packages/core/src/services/user.services.ts#L16
This requires being able to obtain or derive an identity on your own—i.e., an identity is a must. It is worth noting that this can also potentially become insecure quickly; therefore, precautions are advised.
I know that i can make my customIdentity ...
If you are not using the built-in supported authentication (II and NFID), you have indeed have to pass the satellite
parameters with your identity for each call.
Let me know if you have any other questions.
This was very very helpful! I managed to implement authentication! Thank you very much.
Cool! Is your solution open source? Would you ming sharing it?
let customIdentity: Identity | null = null;
export function setAPICustomIdentity(identity: Identity) {
customIdentity = identity;
}
export function getSatteliteOptions(): SatelliteOptions {
let options: SatelliteOptions = {};
if (customIdentity) {
options = {
identity: customIdentity,
satelliteId: import.meta.env.VITE_JUNO_ID as string,
};
}
return options;
}
import React, { useEffect } from "react";
import { initCloudStorage } from "@tma.js/sdk"
import Loading from "../LoadingSplashScreen";
import { Ed25519KeyIdentity, ECDSAKeyIdentity } from "@dfinity/identity"
import { useRecoilState } from "recoil";
import { authState, customIdentity as customIdentityAtom } from "@/atoms/auth";
import { getSatteliteOptions, setAPICustomIdentity } from "@/api";
import { fetchProfile, profileState } from "@/atoms/profile";
import { User, UserData, getDoc, setDoc } from "@junobuild/core";
import { Profile } from "@/types/entities";
import { useLocation, useNavigate } from "react-router-dom";
import { postEvent } from '@tma.js/sdk';
export default function TelegramAuthProvider({
children,
}: {
children: React.ReactNode;
}) {
const IDENITITY_KEY = "telegram_internet_identity";
const [isInitialized, setIsInitialized] = React.useState(false);
const [, setUser] = useRecoilState<User | null>(authState);
const [, setProfile] = useRecoilState<Profile | null>(profileState);
const location = useLocation();
const navigate = useNavigate();
useEffect(() => {
async function authorize() {
const cloudStorage = initCloudStorage();
console.log("authorizing")
let restoredIdentity = await cloudStorage.get(IDENITITY_KEY);
let identity : Ed25519KeyIdentity;
if (!restoredIdentity) {
console.log("generating identity")
identity = await Ed25519KeyIdentity.generate();
await cloudStorage.set(IDENITITY_KEY, JSON.stringify(identity.toJSON()));
console.log("idenitity saved", identity.toJSON())
console.log("principal:", identity.getPrincipal().toString())
} else {
identity = Ed25519KeyIdentity.fromJSON(restoredIdentity);
console.log("restored identity", identity)
console.log("principal:", identity.getPrincipal().toString())
}
setAPICustomIdentity(identity);
const user = await getDoc<UserData>({
collection: `#user`,
key: identity.getPrincipal().toText(),
satellite: getSatteliteOptions()
});
if (!user) {
const result = await setDoc<UserData>({
collection: `#user`,
doc: {
key: identity.getPrincipal().toText(),
data: {
provider: "internet_identity",
},
},
satellite: getSatteliteOptions()
});
setUser(result);
} else {
setUser(user);
}
setIsInitialized(true);
}
authorize();
}, []);
if (!isInitialized) {
return <Loading />;
}
return <>{children}</>;
}
Then whenever I do getDoc or setDoc I do it like that:
await setDoc({
collection: 'profiles',
doc: {
key: '123',
data: { username: 'CodingFu' }
},
satellite: getSatteliteOptions()
})
Baically i generate an identity and store it in telegram cloudStorage
it's like localStorage but it's synced between telegram clients on laptops, iphones, etc.
I'm still not 100% sure on security, but it does the trick.
I plan to move it out to auth canister and will make auth canister give me delegated identity, but while we are in prototyping phase, this approach works for me :)
@peterpeterparker
typescript nags at me, but what if I set provider
to telegram
in
const result = await setDoc<UserData>({
collection: `#user`,
doc: {
key: identity.getPrincipal().toText(),
data: {
// @ts-ignore
provider: "telegram",
},
},
satellite: getSatteliteOptions()
});
will it break the system? will satellite allow this?
Thanks a lot for the share, insteresting approach.
I'm still not 100% sure on security, but it does the trick.
I don't know how cloudStorage works but, indeed that does not feel super secure. Is the access to cloudStorage securised or anyone that basically knows telegram_internet_identity
can retrieve the identity you stored? If the latest, it would be quite a loop hole.
I also don't know how things are encoded in cloudStorage...
typescript nags at me, but what if I set provider to telegram in
It's because typescript accepts only internet identity or nfid (see here). That will be extended once we develop the feature https://github.com/junobuild/juno-js/issues/156.
I am trying to implement third-party authentication mechanism on front-end. I'm trying to log in telegram web app into juno (because both nfid and internet identity work poorly in this environment)
Setup:
I have profiles table in juno (read: Public, write: Managed)
And i construct my identity in the following way:
I understand for the fact that user does not exist on authentication tab.
How can I add user with custom provider there? Is there any way i can "fake" authentication in juno? I know that i can make my
customIdentity
a controller for the satellite, but I can't do it for all the users. Plus I want to maintain "owner" field.Please help!