Understanding Auth Providers
An auth provider is an object containing methods that handle authentication operations. Refine consumes these methods through authentication hooks throughout your application.Quick Setup
import { AuthProvider } from "@refinedev/core";
const authProvider: AuthProvider = {
login: async ({ email, password }) => {
// Make API call to authenticate
const response = await fetch("https://api.example.com/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
if (response.ok) {
const { token, user } = await response.json();
localStorage.setItem("token", token);
localStorage.setItem("user", JSON.stringify(user));
return {
success: true,
redirectTo: "/",
};
}
return {
success: false,
error: {
name: "LoginError",
message: "Invalid email or password",
},
};
},
check: async () => {
const token = localStorage.getItem("token");
if (token) {
return {
authenticated: true,
};
}
return {
authenticated: false,
redirectTo: "/login",
error: {
name: "AuthError",
message: "Not authenticated",
},
};
},
logout: async () => {
localStorage.removeItem("token");
localStorage.removeItem("user");
return {
success: true,
redirectTo: "/login",
};
},
onError: async (error) => {
if (error.status === 401 || error.status === 403) {
return {
logout: true,
redirectTo: "/login",
error,
};
}
return {};
},
getIdentity: async () => {
const user = localStorage.getItem("user");
if (user) {
return JSON.parse(user);
}
return null;
},
getPermissions: async () => {
const user = localStorage.getItem("user");
if (user) {
const { roles } = JSON.parse(user);
return roles;
}
return null;
},
};
export default authProvider;
import { Refine, Authenticated } from "@refinedev/core";
import { BrowserRouter, Routes, Route, Outlet } from "react-router";
import routerProvider from "@refinedev/react-router";
import authProvider from "./authProvider";
import { LoginPage } from "./pages/login";
import { Dashboard } from "./pages/dashboard";
const App = () => (
<BrowserRouter>
<Refine
authProvider={authProvider}
routerProvider={routerProvider}
resources={[
{ name: "posts", list: "/posts" },
]}
>
<Routes>
<Route
element={
<Authenticated
key="authenticated-routes"
fallback={<Navigate to="/login" />}
>
<Outlet />
</Authenticated>
}
>
<Route index element={<Dashboard />} />
<Route path="/posts" element={<PostList />} />
</Route>
<Route
element={
<Authenticated key="auth-pages" fallback={<Outlet />}>
<Navigate to="/" />
</Authenticated>
}
>
<Route path="/login" element={<LoginPage />} />
</Route>
</Routes>
</Refine>
</BrowserRouter>
);
import { useLogin } from "@refinedev/core";
import { useState } from "react";
export const LoginPage = () => {
const { mutate: login, isLoading } = useLogin();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
login({ email, password });
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
required
/>
<button type="submit" disabled={isLoading}>
{isLoading ? "Loading..." : "Login"}
</button>
</form>
);
};
Authentication Methods
Login
Thelogin method is called when users attempt to authenticate:
useLogin hook in your components:
Check Authentication
Thecheck method verifies if a user is authenticated:
Logout
Error Handling
TheonError method handles authentication errors from API calls:
Authentication Patterns
JWT Authentication
OAuth / Social Login
Role-Based Access Control
Advanced Features
Custom Registration
Password Reset
Get User Identity
Integration Examples
Auth0
Supabase
Best Practices
- Never store sensitive data in localStorage: Use httpOnly cookies for tokens when possible
- Implement token refresh: Prevent users from being logged out unexpectedly
- Handle errors gracefully: Provide clear error messages to users
- Use HTTPS: Always use secure connections in production
- Implement rate limiting: Protect against brute force attacks
- Validate on both client and server: Never trust client-side validation alone
Next Steps
- Learn about Router Integration
- Explore Access Control
- Set up Form Handling