@kodeme-io/next-core-auth
v0.8.4
Published
Complete authentication solution for Next.js + Odoo applications with Odoo native auth, OIDC/Authentik, PKCE, and protected route middleware
Downloads
30
Maintainers
Readme
@next-odoo/auth
Authentication module for Next.js + Odoo applications with support for Odoo native authentication and OIDC (Authentik/Keycloak).
Features
- ✅ Dual Authentication - Odoo native + OIDC support
- ✅ Persistent Sessions - Automatic session persistence with Zustand
- ✅ Type Safety - Full TypeScript support
- ✅ Operating Units - Multi-branch/region support
- ✅ React Hook - Easy-to-use
useAuth()hook - ✅ Salesman Types - Canvas, Taking Order, or Both
- ✅ SSR Safe - Works with Next.js server-side rendering
Installation
pnpm add @next-odoo/authUsage
Basic Setup
import { useAuth } from '@next-odoo/auth'
export function LoginPage() {
const { login, isLoading } = useAuth()
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
const formData = new FormData(e.currentTarget)
const success = await login({
username: formData.get('username') as string,
password: formData.get('password') as string,
})
if (success) {
// Redirect to dashboard
router.push('/dashboard')
}
}
return (
<form onSubmit={handleSubmit}>
<input name="username" placeholder="Username" />
<input name="password" type="password" placeholder="Password" />
<button type="submit" disabled={isLoading}>
{isLoading ? 'Logging in...' : 'Login'}
</button>
</form>
)
}Protected Routes
import { useAuth } from '@next-odoo/auth'
import { useRouter } from 'next/navigation'
import { useEffect } from 'react'
export function ProtectedLayout({ children }: { children: React.ReactNode }) {
const { isAuthenticated, isLoading, user } = useAuth()
const router = useRouter()
useEffect(() => {
if (!isLoading && !isAuthenticated) {
router.push('/login')
}
}, [isLoading, isAuthenticated, router])
if (isLoading) {
return <div>Loading...</div>
}
if (!isAuthenticated) {
return null
}
return <>{children}</>
}Access User Information
import { useAuth } from '@next-odoo/auth'
export function UserProfile() {
const { user, logout } = useAuth()
if (!user) return null
return (
<div>
<h1>Welcome, {user.name}</h1>
<p>Email: {user.email}</p>
<p>Login: {user.login}</p>
{user.salesman_type && (
<p>Salesman Type: {user.salesman_type}</p>
)}
{user.default_operating_unit_name && (
<p>Operating Unit: {user.default_operating_unit_name}</p>
)}
<button onClick={logout}>Logout</button>
</div>
)
}Check Permissions
import { useAuth } from '@next-odoo/auth'
export function CustomerApprovalButton() {
const { user } = useAuth()
if (!user?.can_approve_customers) {
return null // Don't show button if user can't approve
}
return (
<button onClick={handleApprove}>
Approve Customer
</button>
)
}API Reference
useAuth()
Main hook for authentication functionality.
Returns:
{
user: User | null // Current authenticated user
sessionId: string | null // Odoo session ID
isAuthenticated: boolean // Authentication status
isLoading: boolean // Loading state
login: (credentials: LoginCredentials) => Promise<boolean>
logout: () => Promise<void>
checkSession: () => Promise<boolean>
}Types
User
interface User {
id: number
name: string
login: string
email: string
is_salesperson: boolean
partner_id: number
salesman_type?: 'canvas' | 'taking_order' | 'both'
can_approve_customers?: boolean
operating_unit_ids?: number[]
default_operating_unit_id?: number
default_operating_unit_name?: string
sale_team_id?: number
sale_team_name?: string
}LoginCredentials
interface LoginCredentials {
username: string
password: string
}Backend Integration
This package expects your Next.js app to have these API routes:
/api/auth/login (POST)
// app/api/auth/login/route.ts
import { NextRequest, NextResponse } from 'next/server'
export async function POST(request: NextRequest) {
const { username, password } = await request.json()
// Call Odoo JSON-RPC to authenticate
const response = await fetch(`${process.env.ODOO_URL}/jsonrpc`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'call',
params: {
service: 'common',
method: 'login',
args: [process.env.ODOO_DB, username, password]
}
})
})
const result = await response.json()
if (result.result) {
return NextResponse.json({
success: true,
sessionId: result.result.session_id,
user: {
id: result.result.uid,
// ... other user fields
}
})
}
return NextResponse.json({ success: false }, { status: 401 })
}/api/auth/logout (POST)
// app/api/auth/logout/route.ts
export async function POST() {
// Clear session cookies/tokens
return NextResponse.json({ success: true })
}OIDC Integration (Optional)
For OIDC authentication with Authentik/Keycloak:
import { OIDCConfig } from '@next-odoo/auth'
const oidcConfig: OIDCConfig = {
issuer: 'https://auth.yourdomain.com',
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
redirectUri: 'https://yourapp.com/api/auth/callback',
scopes: ['openid', 'profile', 'email']
}
// Implement OIDC flow in your API routesStorage Configuration
By default, auth state is persisted to localStorage with the key next-odoo-auth-storage. To customize:
import { useAuthStore } from '@next-odoo/auth'
// Access the store directly for advanced configuration
const authStore = useAuthStore.getState()License
MIT
