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
- π Day One: Fresh React app + AIOHA integration!
- π§ Day Two: Routing drama & rebellious NavBar π€
- π οΈ Day Three: Fixed Layouts, Routing & AIOHA π₯
- π§ Day Four: useState, useEffect, and .env headaches π
- π§Ή Day Five: Path Aliases to clean up relative path spaghetti π
- π‘ Day Six: Create Context Provider & call API
- π Day Seven: Show a toast message
π Whatβs New in Day 8?
In this episode, I went full-on security ninja. π₯· Here's what I implemented:
- π Login API with
@aioha & distriator combo
- π¦ Storing user data securely in
localStorageusing 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
π 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
- I asked AI to help optimize this post to make it more readable and viewer-friendly.
- Here is the link where you can find both original content & improvements made by AI
- https://www.perplexity.ai/search/e4abc965-4e52-442b-b001-ab6942995dff
π My Contributions to β¦οΈ Hive Ecosystem
| Contribution | To | Hive | Ecosystem |
|---|---|---|---|
| Hive Witness Node | Hive API Node (in progress) | 3Speak Video Encoder Node Operator (highest number of nodes) | 3Speak Mobile App Developer |
| 3Speak Podcast App Developer | 3Speak Shorts App Developer | 3Speak Support & Maintenance Team | Distriator Developer |
| CheckinWithXYZ | Hive Inbox | HiFind | Hive Donate App |
| Contributed to HiveAuth Mobile App | Ecency β 3Speak Integration | Ecency β InLeo Integration | Ecency β Actifit Integration |
| Hive Stats App | Vote for Witness App | HiveFlutterKit | New 3Speak App |
π Support Back
β€οΈ Appreciate my work? Consider supporting @threespeak &
@sagarkothari88! β€οΈ
| Vote | For | Witness |
|---|---|---|
| sagarkothari88 | ||
| threespeak |
Leave Day 8 - Secure π Login with AIOHA & LocalStorage Magic π§ to:
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
- HiveReactKit Dev Update: Enhanced Nav, Media Playback & Governance Improvements
- HiveSuite Game Update: Spider Solitaire Added to the Games Collection
- HiveSuite Dev Update: Klondike Solitaire Joins the Games Collection.
- HiveSuite Dev Update: Faster Navigation, Expanded Profile Drawer & Bookmark Experience Improvement.
- HiveSuite Dev Update: Shareable Profile Tabs & Redesigned Profile Drawer Experience
- HiveSuite Dev Update: Smart Mentions, Internal Navigation & Seamless Inline Media Experience.
- HiveReactKit Dev Update: Inline Media Playback, Enhanced Embeds & Cleaner Post Experience.
- HiveReactKit Dev Update: Smart @Mentions, Composer Intelligence & Improved In-App Navigation
- HiveSuite Dev Update: Bookmarks, Backend Improvements & Development Workflow Enhancement
- HiveSuite Dev Update: Advanced Bookmark System & Video Progress Experience.