bkend-auth
Installation
SKILL.md
bkend.ai Authentication
Implement user authentication with bkend.ai BaaS.
Actions
| Action | Description | Example |
|---|---|---|
setup |
Set up auth | $bkend-auth setup |
flow |
Auth flow diagram | $bkend-auth flow |
rbac |
Role-based access | $bkend-auth rbac |
Authentication Flow
1. User submits email + password
2. POST /auth/email/signup (new user) or /auth/email/signin (existing)
3. Server returns { user, access_token, refresh_token }
4. Store access_token in memory/localStorage
5. Store refresh_token in httpOnly cookie (secure)
6. Include access_token in Authorization header for API calls
7. When access_token expires -> use refresh_token to get new one
8. On logout -> invalidate tokens
Signup
async function handleSignup(email: string, password: string, name: string) {
const { user, access_token, refresh_token } = await bkend.auth.signup({
email, password, name,
});
localStorage.setItem('bkend_access_token', access_token);
return user;
}
Login
async function handleLogin(email: string, password: string) {
const { user, access_token, refresh_token } = await bkend.auth.signin({
email, password,
});
localStorage.setItem('bkend_access_token', access_token);
return user;
}
Get Current User
async function getCurrentUser() {
return bkend.auth.me(); // Uses token from localStorage
}
Logout
function handleLogout() {
bkend.auth.signout().catch(() => {});
localStorage.removeItem('bkend_access_token');
localStorage.removeItem('bkend_refresh_token');
window.location.href = '/login';
}
Token Refresh
async function refreshToken() {
const refreshToken = localStorage.getItem('bkend_refresh_token');
if (!refreshToken) throw new Error('No refresh token');
const { access_token } = await bkend.auth.refresh(refreshToken);
localStorage.setItem('bkend_access_token', access_token);
return access_token;
}
Protected Route Component
'use client';
import { useAuth } from '@/hooks/useAuth';
import { redirect } from 'next/navigation';
export function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { user, isLoading } = useAuth();
if (isLoading) return <div>Loading...</div>;
if (!user) redirect('/login');
return <>{children}</>;
}
Role-Based Access Control
// Check user role
function RequireRole({ role, children }: { role: string; children: React.ReactNode }) {
const { user } = useAuth();
if (user?.role !== role) return <div>Access denied</div>;
return <>{children}</>;
}
// Usage
<RequireRole role="admin">
<AdminDashboard />
</RequireRole>
Login Form Example
'use client';
import { useState } from 'react';
import { useAuth } from '@/hooks/useAuth';
import { useRouter } from 'next/navigation';
export function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const { login, isLoading } = useAuth();
const router = useRouter();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
try {
await login(email, password);
router.push('/dashboard');
} catch (err) {
setError(err instanceof Error ? err.message : 'Login failed');
}
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)}
placeholder="Email" required className="w-full border rounded px-3 py-2" />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)}
placeholder="Password" required className="w-full border rounded px-3 py-2" />
{error && <p className="text-red-500 text-sm">{error}</p>}
<button type="submit" disabled={isLoading}
className="w-full bg-blue-500 text-white py-2 rounded hover:bg-blue-600 disabled:opacity-50">
{isLoading ? 'Signing in...' : 'Sign In'}
</button>
</form>
);
}
Reference
See references/bkend-patterns.md for the full auth store implementation and advanced patterns.
Related skills