-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom authentication using dfinity/agent #164
Comments
This is not yet supported. Providing interfaces for generic custom authentication is tracked in #156.
I'm not sure what's "fake." Protected features require authenticated users. These are saved within a system collection named
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.
If you are not using the built-in supported authentication (II and NFID), you have indeed have to pass the 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 :) |
typescript nags at me, but what if I set 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 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 I also don't know how things are encoded in cloudStorage...
It's because typescript accepts only internet identity or nfid (see here). That will be extended once we develop the feature #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!
The text was updated successfully, but these errors were encountered: