This document describes the authentication system implemented in the Vitruv UI Methodologist application.
The authentication system provides:
- User sign-up and sign-in functionality
- Automatic token refresh
- Secure API requests with authentication
- Token management and storage
- URL:
POST http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080/api/v1/users/sign-up - Request Body:
{ "email": "string", "roleType": "user", "username": "string", "firstName": "string", "lastName": "string", "password": "string" } - Response:
{ "data": {}, "message": "string" }
- URL:
POST http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080/api/v1/users/login - Request Body:
{ "username": "string", "password": "string" } - Response:
{ "access_token": "string", "refresh_token": "string", "expires_in": 0, "refresh_expires_in": 0, "token_type": "string", "session_state": "string", "scope": "string", "not-before-policy": 0 }
- URL:
POST http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080/api/v1/users/access-token/by-refresh-token - Request Body:
{ "refreshToken": "string" } - Response: Same as sign-in response
import { useAuth } from '../contexts/AuthContext';
function MyComponent() {
const { signIn, signUp, signOut, user, isAuthenticated } = useAuth();
const handleSignIn = async () => {
try {
await signIn('username', 'password');
console.log('Signed in successfully');
} catch (error) {
console.error('Sign in failed:', error);
}
};
const handleSignUp = async () => {
try {
await signUp({
username: 'newuser',
email: 'user@example.com',
password: 'password123',
firstName: 'John',
lastName: 'Doe',
roleType: 'user'
});
console.log('Signed up successfully');
} catch (error) {
console.error('Sign up failed:', error);
}
};
return (
<div>
{isAuthenticated ? (
<div>
<p>Welcome, {user?.username}!</p>
<button onClick={signOut}>Sign Out</button>
</div>
) : (
<div>
<button onClick={handleSignIn}>Sign In</button>
<button onClick={handleSignUp}>Sign Up</button>
</div>
)}
</div>
);
}import { apiService, userApi, projectApi } from '../services/api';
// Using the authenticated service directly
const getData = async () => {
try {
const response = await apiService.authenticatedRequest('/api/v1/some-endpoint');
console.log(response);
} catch (error) {
console.error('API request failed:', error);
}
};
// Using predefined API methods
const getUserProfile = async () => {
try {
const profile = await userApi.getProfile();
console.log(profile);
} catch (error) {
console.error('Failed to get profile:', error);
}
};
const createNewProject = async () => {
try {
const project = await projectApi.createProject({
name: 'My Project',
description: 'A new project'
});
console.log('Project created:', project);
} catch (error) {
console.error('Failed to create project:', error);
}
};The system automatically handles token refresh, but you can also manually refresh tokens:
import { useAuth } from '../contexts/AuthContext';
function TokenRefreshExample() {
const { refreshToken } = useAuth();
const handleManualRefresh = async () => {
try {
const result = await refreshToken();
console.log('Token refreshed:', result);
} catch (error) {
console.error('Token refresh failed:', error);
}
};
return (
<button onClick={handleManualRefresh}>
Refresh Token
</button>
);
}import { useTokenRefresh } from '../hooks/useTokenRefresh';
function TokenManagement() {
const { refreshToken, getValidToken } = useTokenRefresh();
const handleGetValidToken = async () => {
try {
const token = await getValidToken();
if (token) {
console.log('Valid token:', token);
} else {
console.log('No valid token available');
}
} catch (error) {
console.error('Failed to get valid token:', error);
}
};
return (
<div>
<button onClick={handleGetValidToken}>Get Valid Token</button>
</div>
);
}- The system automatically detects when access tokens expire
- Automatically attempts to refresh tokens before they expire
- If refresh fails, the user is automatically signed out
- Tokens are checked every minute
- Refresh is attempted 5 minutes before expiration
- Failed refreshes trigger automatic sign-out
- All authenticated requests automatically include the current token
- Failed requests due to invalid tokens automatically retry after refresh
- Seamless token refresh without user intervention
The backend URL is configured in src/services/auth.ts:
private static readonly LOCAL_API_BASE_URL = 'http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080';Tokens are stored in localStorage with the following keys:
auth.access_token- Current access tokenauth.refresh_token- Current refresh tokenauth.expires_in- Access token expiration timeauth.refresh_expires_in- Refresh token expiration timeauth.token_type- Token type (usually "Bearer")auth.session_state- Session stateauth.scope- Token scopeauth.not_before_policy- Not before policy timestamp
The system provides comprehensive error handling:
- Network errors are caught and displayed to users
- Authentication failures trigger appropriate error messages
- Token refresh failures result in automatic sign-out
- API errors include detailed error messages from the backend
- Tokens are automatically refreshed before expiration
- Failed authentication attempts are handled gracefully
- Secure token storage in localStorage
- Automatic cleanup of expired tokens
- Protection against token reuse attacks
To test the authentication system:
- Ensure your backend server is running on
http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080 - Use the sign-up form to create a new account
- Use the sign-in form to authenticate
- Check the browser's developer tools to see stored tokens
- Test API calls that require authentication
- Wait for token expiration to test automatic refresh
-
Backend Connection Failed
- Ensure your backend server is running on port 9811
- Check that the API endpoints are accessible
-
Token Refresh Fails
- Check that refresh tokens are valid
- Verify the refresh endpoint is working
- Check browser console for detailed error messages
-
Authentication State Lost
- Check localStorage for stored tokens
- Verify token expiration times
- Check for JavaScript errors in the console
Enable debug logging by checking the browser console. The system logs:
- Authentication attempts
- Token refresh operations
- API request details
- Error information
If you're migrating from the old authentication system:
- Update your components to use the new
useAuthhook - Replace direct API calls with the new
apiService - Update any hardcoded authentication logic
- Test the new token refresh functionality
The legacy authentication methods are still available in AuthService.signInLegacy() for backward compatibility.