Login & Logout
Learn how to implement secure login and logout functionality using Laravel Passport with Nuxt Umbu.
Basic Login
The loginWith method provides a simple way to authenticate users with Laravel Passport.
Using the Composable
<template>
<form @submit.prevent="handleLogin">
<div>
<label for="email">Email</label>
<input
id="email"
v-model="credentials.email"
type="email"
required
/>
</div>
<div>
<label for="password">Password</label>
<input
id="password"
v-model="credentials.password"
type="password"
required
/>
</div>
<button type="submit" :disabled="loading">
{{ loading ? 'Signing in...' : 'Sign In' }}
</button>
</form>
</template>
<script setup>
const { loginWith } = useAuth()
const credentials = ref({
email: '',
password: ''
})
const loading = ref(false)
const handleLogin = async () => {
try {
loading.value = true
await loginWith('client', credentials.value)
// User is now logged in and redirected
} catch (error) {
console.error('Login failed:', error)
// Handle login error
} finally {
loading.value = false
}
}
</script>
Login Response
When login succeeds, the response contains:
interface AuthResponse {
token: string // OAuth2 access token
expires: string // Token expiration timestamp
refresh_token: string // Token for refreshing access
}
Custom Login Endpoint
You can customize the login endpoint in your configuration:
export default defineNuxtConfig({
auth: {
provider: 'passport',
strategies: {
client: {
endpoints: {
login: {
url: '/oauth/token',
method: 'POST',
alias: 'oauth-token'
}
}
}
}
}
})
Basic Logout
The logout method handles session termination and cleanup.
Simple Logout Implementation
<template>
<div v-if="loggedIn">
<p>Welcome, {{ user?.name }}!</p>
<button @click="handleLogout">
Sign Out
</button>
</div>
</template>
<script setup>
const { loggedIn, user, logout } = useAuth()
const handleLogout = async () => {
try {
await logout('client')
// User is now logged out and redirected
} catch (error) {
console.error('Logout failed:', error)
// Handle logout error
}
}
</script>
Advanced Login with Error Handling
<script setup>
const { loginWith } = useAuth()
const credentials = ref({
email: '',
password: ''
})
const error = ref('')
const loading = ref(false)
const handleLogin = async () => {
error.value = ''
loading.value = true
try {
await loginWith('client', credentials.value)
// Success - user will be redirected automatically
} catch (err) {
// Handle different error types
if (err.statusCode === 401) {
error.value = 'Invalid credentials'
} else if (err.statusCode === 422) {
error.value = 'Validation error'
} else {
error.value = 'Login failed. Please try again.'
}
} finally {
loading.value = false
}
}
</script>
Login with Remember Me
Implement "Remember Me" functionality by extending the credentials:
<script setup>
const credentials = ref({
email: '',
password: '',
remember: false
})
const handleLogin = async () => {
await loginWith('client', credentials.value)
}
</script>
Note: The
remembervalue must be honored by your backend login endpoint and Laravel Passport/session configuration to change token or session lifetime. This example depends on this existing backend contract - ensure your server is configured to handle therememberparameter appropriately.
Multiple Authentication Strategies
Configure multiple strategies for different user types:
export default defineNuxtConfig({
auth: {
provider: 'passport',
strategies: {
admin: {
endpoints: {
login: { url: '/api/admin/login', method: 'POST' },
user: { url: '/api/admin/user', method: 'GET' }
},
redirect: {
login: '/admin/dashboard',
logout: '/admin/login'
}
},
customer: {
endpoints: {
login: { url: '/api/customer/login', method: 'POST' },
user: { url: '/api/customer/user', method: 'GET' }
},
redirect: {
login: '/customer/dashboard',
logout: '/customer/login'
}
}
}
}
})
<script setup>
const { loginWith } = useAuth()
const adminCredentials = ref({
email: 'admin@example.com',
password: ''
})
const customerCredentials = ref({
email: 'customer@example.com',
password: ''
})
const credentials = ref({
email: '',
password: ''
})
// Admin login
const handleAdminLogin = async () => {
await loginWith('admin', adminCredentials.value)
}
// Customer login
const handleCustomerLogin = async () => {
await loginWith('customer', customerCredentials.value)
}
</script>
Server-Side Login
For server-side operations, use the server API:
export default defineEventHandler(async (event) => {
const { strategyName, value } = await readBody(event)
try {
const response = await $fetch('/oauth/token', {
method: 'POST',
body: {
grant_type: 'password',
client_id: process.env.AUTH_CLIENT_ID,
client_secret: process.env.AUTH_CLIENT_SECRET,
username: value.email,
password: value.password
}
})
return response
} catch (error) {
throw createError({
statusCode: 401,
statusMessage: 'Invalid credentials'
})
}
})
Logout with Custom Redirect
<script setup>
const { logout } = useAuth()
const handleLogout = async () => {
// Override the default redirect
await logout('client', { redirect: '/custom-goodbye' })
}
</script>
Authentication State
Monitor authentication state changes:
<script setup>
const { loggedIn, user } = useAuth()
// Watch for auth state changes
watch(loggedIn, (isLoggedIn) => {
if (isLoggedIn) {
console.log('User logged in:', user.value)
} else {
console.log('User logged out')
}
})
</script>
Error Handling Best Practices
Common Login Errors
| Error | Description | Solution |
|---|---|---|
401 | Invalid credentials | Check email/password |
422 | Validation error | Validate input format |
500 | Server error | Check server logs |
Network Error | Connection failed | Check API connectivity |
Error Handling Component
<template>
<div v-if="error" class="error-message">
{{ error }}
<button @click="error = ''">×</button>
</div>
</template>
<script setup>
const error = ref('')
const handleLogin = async () => {
try {
await loginWith('client', credentials)
} catch (err) {
error.value = getErrorMessage(err)
}
}
const getErrorMessage = (err) => {
switch (err.statusCode) {
case 401: return 'Invalid email or password'
case 422: return 'Please check your input'
case 429: return 'Too many attempts. Try again later.'
default: return 'Login failed. Please try again.'
}
}
</script>
Next: Learn about Token Management for handling token refresh and expiration.