Sagar Kothari avatar

Day 8 - Secure πŸ” Login with AIOHA & LocalStorage Magic πŸ§™

sagarkothari88

Published: 03 Aug 2025 β€Ί Updated: 03 Aug 2025Day 8 - Secure πŸ” Login with AIOHA & LocalStorage Magic πŸ§™

Day 8 - Secure πŸ” Login with AIOHA & LocalStorage Magic πŸ§™

πŸ“£ Hello Hive Community Members!


Welcome back to my wild ReactJS learning ride 🎒 β€” and guess what? We’re already on Day 8! If you've missed previous episodes, don't worry. Grab some popcorn 🍿 and catch up below:


πŸ“– ReactJS Journey So Far


πŸš€ What’s New in Day 8?

In this episode, I went full-on security ninja. πŸ₯· Here's what I implemented:

  • πŸ” Login API with aioha@aioha & distriator combo
  • πŸ“¦ Storing user data securely in localStorage using AES encryption & base64 encoding
  • βœ… Upsert logic for managing multiple Hive logins

🧠 Data Modeling Like a Boss

πŸ“ Folder: src/types/LoginApiRequestResponse.tsx

export interface LoginRequestDTO {
  challenge: string;
  proof: string;
  pubkey: string;
  username: string;
}

export interface LoginSuccessResponseDTO {
  token: string;
  type: string;
}

export interface LocalStorageUserDTO {
  token: string;
  type: string;
  challenge: string;
  proof: string;
  pubkey: string;
  username: string;
}

export interface LoginErrorResponseDTO {
  error: string;
}

πŸ’Ύ Encrypting User Data in LocalStorage

localstorage image reference

πŸ“ File: src/utils/LocalStorageUtils.tsx
Let’s bring in the secret scrolls of utility magic! πŸ§™

πŸ” Base64 Helper Spells

function toBase64(str: string): string {
  return typeof window !== "undefined"
    ? window.btoa(unescape(encodeURIComponent(str)))
    : Buffer.from(str, "utf-8").toString("base64");
}

function fromBase64(b64: string): string {
  return typeof window !== "undefined"
    ? decodeURIComponent(escape(window.atob(b64)))
    : Buffer.from(b64, "base64").toString("utf-8");
}

πŸ“₯ Retrieve Users from LocalStorage (aka Decrypt Scroll)

export function getLoggedInUsers(): LocalStorageUserDTO[] {
  const apiKey = import.meta.env.VITE_LOCAL_KEY;
  const data = localStorage.getItem("logged-in-users") || "";
  const decrypteText = CryptoJS.AES.decrypt(data, apiKey).toString(
    CryptoJS.enc.Utf8
  );
  if (!data) return [];
  try {
    const jsonStr = fromBase64(decrypteText);
    return JSON.parse(jsonStr);
  } catch (e) {
    console.error("Failed to decode/parse localStorage ", e);
    return [];
  }
}

πŸ“ Steps:

  • Get πŸ” key from .env
  • Decrypt β†’ decode β†’ parse β†’ return!

πŸ“ Store/Update New Logged-In Users (Avengers-like registry 🦸)

export function setLoggedInUsers(users: LocalStorageUserDTO[]): void {
  try {
    const apiKey = import.meta.env.VITE_DEKEY;
    const jsonStr = JSON.stringify(users);
    const base64Str = toBase64(jsonStr);
    const encryptedText = CryptoJS.AES.encrypt(base64Str, apiKey).toString();
    localStorage.setItem("logged-in-users", encryptedText);
  } catch (e) {
    console.error("Failed to encode/set localStorage ", e);
  }
}

πŸ”„ Save/Update User Info (like a React-powered CRM 😎)

export function saveOrUpdateUser(newUser: LocalStorageUserDTO): void {
  const users = getLoggedInUsers();
  const idx = users.findIndex((user) => user.username === newUser.username);
  if (idx !== -1) {
    users[idx] = newUser;
  } else {
    users.push(newUser);
  }
  setLoggedInUsers(users);
}

πŸ™…β€β™‚οΈ No remove logic yet β€” coming with future logout feature. Stay tuned!


πŸ”Œ Calling the Login API – FTW!

πŸ“ File: src/api/LoginApi.tsx

Here’s how the server handshake looks:

export const loginApi = async (challenge, proof, pubkey, username): Promise<null | string> => {
  try {
    const rqst: LoginRequestDTO = { challenge, proof, pubkey, username };
    const response = await fetch("https://beta-api.distriator.com/login", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(rqst),
    });

    if (!response.ok) {
      const errorBody: LoginErrorResponseDTO = await response.json();
      console.error("Login failed:", errorBody);
      return `Error - ${errorBody.error}`;
    }

    const success: LoginSuccessResponseDTO = await response.json();
    const updatedUser: LocalStorageUserDTO = { ...rqst, token: success.token, type: success.type };
    saveOrUpdateUser(updatedUser);
    return null;

  } catch (error) {
    console.error("Network error:", error);
    return `Network error - ${error.message}`;
  }
};

πŸ”₯ Boom! Now you're securely logged in and your data is sealed like Wakanda tech! πŸ›‘οΈ


🀝 AIOHA + Distriator Login Combo πŸ’ͺ

πŸ“ File: src/components/HiveUserAvatarButton.tsx

We've glued it all together using @aioha/react-ui. 🧩

<AiohaModal
  displayed={modalDisplayed}
  loginOptions={{
    msg: proof,
    keyType: KeyTypes.Posting,
  }}
  onLogin={performLogin}
  onClose={setModalDisplayed}
/>

And here’s the magic performLogin function:

async function performLogin(result: LoginResult) {
  if (result.success) {
    const loginResult = await loginApi(result.result, proof, result.publicKey || "none", result.username);
    if (loginResult == null) {
      console.log("πŸŽ‰ Logged in successfully!");
    } else {
      console.error(`Login failed: ${loginResult}`);
    }
  } else {
    console.error(result.error || "Something went wrong");
  }
}

🎯 Wrapping Up

This was a deep dive into login flows, secure data handling & functional integration of blockchain login workflows! 🧩

That's it for now, folks! Thank you so much for reading my post. πŸ’™

More power to the Hive Blockchain 🐝
More power to all our community members πŸ™Œ
Until next time, Happy Coding! πŸ’»βœ¨


πŸ“ Final Note


πŸš€ My Contributions to ♦️ Hive Ecosystem

ContributionToHiveEcosystem
Hive Witness NodeHive API Node (in progress)3Speak Video Encoder Node Operator (highest number of nodes)3Speak Mobile App Developer
3Speak Podcast App Developer3Speak Shorts App Developer3Speak Support & Maintenance TeamDistriator Developer
CheckinWithXYZHive InboxHiFindHive Donate App
Contributed to HiveAuth Mobile AppEcency ↔ 3Speak IntegrationEcency ↔ InLeo IntegrationEcency ↔ Actifit Integration
Hive Stats AppVote for Witness AppHiveFlutterKitNew 3Speak App

πŸ™Œ Support Back

❀️ Appreciate my work? Consider supporting threespeak@threespeak & sagarkothari88@sagarkothari88! ❀️

VoteForWitness
sagarkothari88sagarkothari88@sagarkothari88
threespeakthreespeak@threespeak

Leave Day 8 - Secure πŸ” Login with AIOHA & LocalStorage Magic πŸ§™ to:

Written by

App Developer on Hive - Distriator, Check in With XYZ, 3Speak, HiveSuite.app.

Read more #hive posts


Best Posts From Sagar Kothari

We have not curated any of sagarkothari88's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From Sagar Kothari