Full-Stack Development
Auth Integration
Implement login, signup, protected routes, and token refresh in your frontend app.
How Auth Works
RaisFast uses JWT with short-lived access tokens + long-lived refresh tokens:
- User logs in with email/password → receives
access_token(15 min) +refresh_token(7 days) - Frontend stores tokens and sends
access_tokenin theAuthorizationheader - When
access_tokenexpires, userefresh_tokento get a new pair - Refresh tokens are stored in the database — you can revoke them
Login Flow
import { client } from "@/lib/client";
import { useState } from "react";
function LoginPage({ onLogin }) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
async function handleSubmit(e) {
e.preventDefault();
const result = await client.auth.login({ email, password });
localStorage.setItem("access_token", result.access_token);
localStorage.setItem("refresh_token", result.refresh_token);
client.setToken(result.access_token);
onLogin(result.user);
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit">Login</button>
</form>
);
}<script setup>
import { ref } from "vue";
import { client } from "@/lib/client";
const emit = defineEmits(["login"]);
const email = ref("");
const password = ref("");
async function handleLogin() {
const result = await client.auth.login({
email: email.value,
password: password.value,
});
localStorage.setItem("access_token", result.access_token);
localStorage.setItem("refresh_token", result.refresh_token);
client.setToken(result.access_token);
emit("login", result.user);
}
</script>
<template>
<form @submit.prevent="handleLogin">
<input v-model="email" type="email" placeholder="Email" />
<input v-model="password" type="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
</template>import { RaisFast } from "@raisfast/sdk";
const client = new RaisFast({ baseUrl: "/api" });
async function login(email, password) {
const result = await client.auth.login({ email, password });
localStorage.setItem("access_token", result.access_token);
localStorage.setItem("refresh_token", result.refresh_token);
client.setToken(result.access_token);
return result.user;
}
// Usage
document.getElementById("loginForm").addEventListener("submit", async (e) => {
e.preventDefault();
const user = await login(
document.getElementById("email").value,
document.getElementById("password").value
);
console.log("Logged in as", user.username);
});Token Refresh
Access tokens expire in 15 minutes. Handle refresh automatically:
import { client } from "./client";
let refreshPromise: Promise<void> | null = null;
export async function getValidToken(): Promise<string> {
const token = localStorage.getItem("access_token");
if (token) {
const payload = JSON.parse(atob(token.split(".")[1]));
if (payload.exp * 1000 > Date.now()) {
return token;
}
}
if (!refreshPromise) {
refreshPromise = (async () => {
const refreshToken = localStorage.getItem("refresh_token");
const result = await client.auth.refresh(refreshToken!);
localStorage.setItem("access_token", result.access_token);
localStorage.setItem("refresh_token", result.refresh_token);
client.setToken(result.access_token);
refreshPromise = null;
})();
}
await refreshPromise;
return localStorage.getItem("access_token")!;
}Protected Routes (React Example)
import { useState, useEffect } from "react";
import { client } from "@/lib/client";
import { getValidToken } from "@/lib/auth";
function ProtectedRoute({ children }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem("access_token");
if (!token) {
setLoading(false);
return;
}
client.setToken(token);
client.auth.me().then(setUser).catch(() => {
localStorage.removeItem("access_token");
}).finally(() => setLoading(false));
}, []);
if (loading) return <div>Loading...</div>;
if (!user) return <Navigate to="/login" />;
return children;
}Logout
async function logout() {
const refreshToken = localStorage.getItem("refresh_token");
if (refreshToken) {
await client.auth.logout(refreshToken);
}
localStorage.removeItem("access_token");
localStorage.removeItem("refresh_token");
client.setToken("");
}Registration
const user = await client.auth.register({
username: "newuser",
email: "user@example.com",
password: "MyStr0ngP@ss",
});Next Step
With auth in place, let's connect data and CRUD operations.
