Authentication
Auth Provider
Use an Auth provider to communicate with your backend. This provider handles login, logout, user identity, and session checks.
The Auth interface defines the contract:
interface Auth {
// Sign in the user
login: (params?: any) => Promise<LoginResult | void>
// Sign out the user
logout: (params?: any) => Promise<LogoutResult | void>
// Check if the user is authenticated
check: (params?: any) => Promise<CheckAuthResult>
// Handle API errors (e.g. 401 Unauthorized)
checkError: (error: any) => Promise<CheckAuthErrorResult>
// Get user identity (optional)
getIdentity?: (params?: any) => Promise<GetIdentityResult>
}
Login
Use useLogin to handle the sign-in process. This composable manages the mutation state and side effects like redirection.
Usage
<script setup lang="ts">
import { useLogin } from '@ginjou/vue'
const { mutate: login, isPending } = useLogin()
function handleSubmit(credentials) {
login(credentials)
}
</script>
<!-- WIP -->
<script>
// ...
</script>
Composition
useLogin composes data composables and actions to provide a complete flow.
- Data Composables: Uses
useMutation(TanStack Query) to manage the request state. - Actions: Calls
auth.loginfrom your provider. - Success Flow:
- Mutation On Success: Invalidates the
authquery to update the UI. - Composable On Success: Redirects the user to the dashboard or the page they were trying to access.
- Mutation On Success: Invalidates the
Logout
Use useLogout to sign out the user.
Usage
<script setup lang="ts">
import { useLogout } from '@ginjou/vue'
const { mutate: logout } = useLogout()
</script>
<!-- WIP -->
<script>
// ...
</script>
Composition
- Data Composables: Uses
useMutation. - Actions: Calls
auth.logout. - Success Flow:
- Mutation On Success: Clears user data from the cache.
- Composable On Success: Redirects the user to the login page.
Check Auth
Use useAuthenticated to check if the current user is logged in. This is often used to protect routes or show/hide UI elements.
Usage
<script setup lang="ts">
import { useAuthenticated } from '@ginjou/vue'
const { data, isLoading } = useAuthenticated()
</script>
<!-- WIP -->
<script>
// ...
</script>
Composition
- Data Composables: Uses
useQueryto fetch authentication status. - Actions: Calls
auth.check.
Identity
Use useGetIdentity to fetch the current user's profile information (e.g. name, avatar, rules).
Usage
<script setup lang="ts">
import { useGetIdentity } from '@ginjou/vue'
const { data: identity } = useGetIdentity()
</script>
<!-- WIP -->
<script>
// ...
</script>
Composition
- Data Composables: Uses
useQueryto fetch identity data. - Actions: Calls
auth.getIdentity.
Check Error
Use useCheckError to automatically handle API errors. This is usually triggered when an API returns an error (like 401 Unauthorized) to determine if the user should be logged out.
Usage
<script setup lang="ts">
import { useCheckError } from '@ginjou/vue'
const { mutate: checkError } = useCheckError()
// Example usage within a query error handler
function handleQueryError(error) {
checkError({ error })
}
</script>
<!-- WIP -->
<script>
// ...
</script>
Composition
- Data Composables: Uses
useMutation. - Actions: Calls
auth.checkError. - Success Flow:
- Composable On Success: If the error confirms the session is invalid, it may trigger
logoutautomatically.
- Composable On Success: If the error confirms the session is invalid, it may trigger
Common Error Patterns
The checkError function examines API errors and determines whether they indicate an authentication failure. Here are common error-handling patterns:
Pattern 1: Auto-Logout on 401 Unauthorized
// In your Auth provider
const auth = {
checkError: async (error) => {
// If 401, session is invalid
if (error.status === 401) {
// Trigger logout
window.location.href = '/login'
return { logout: true }
}
// Otherwise, let the error propagate
return { logout: false }
},
}
Pattern 2: Retry with Refresh Token
const auth = {
checkError: async (error) => {
if (error.status === 401) {
try {
// Attempt to refresh the token
await refreshToken()
return { logout: false } // Retry the request
}
catch {
// Refresh failed - session is truly invalid
return { logout: true }
}
}
return { logout: false }
},
}
Pattern 3: Differentiate Between Error Types
const auth = {
checkError: async (error) => {
if (error.status === 401) {
// Session expired or invalid credentials
return { logout: true }
}
if (error.status === 403) {
// User lacks permissions - don't logout
return { logout: false }
}
if (error.status === 500) {
// Server error - don't logout
return { logout: false }
}
return { logout: false }
},
}
Use Cases
- Session Expiration: Automatically log out when the session expires
- Token Refresh: Attempt token refresh before forcing logout
- Permission Denied: Distinguish between auth failure (401) and access denial (403)
- Network Errors: Handle network-related errors separately from auth errors