Add Login
In this guide, you’ll learn how to create a login view using Hilla and React.
|
Warning
|
Never Use Hard-Coded Credentials In Production
In-memory authentication is convenient for development, but production applications must use a more secure approach, such as JDBC authentication, LDAP authentication, or OAuth 2.0. Refer to the Spring Security Reference Manual for more details.
|
Client Configuration
Vaadin includes a client-side security extension that integrates with Spring Security on the server. To configure it, follow these steps:
-
Create a user information endpoint on the server.
-
Set up a React context in the frontend.
-
Enable the context in the
Appcomponent.
Create a User Information Endpoint
Since authentication happens on the server, you need a way to pass user information to the client. To achieve this, create a @BrowserCallable service that returns user details:
Source code
Java
@BrowserCallable
public class UserInfoService {
@PermitAll 1
public @NonNull UserInfo getUserInfo() {
var auth = SecurityContextHolder.getContext().getAuthentication(); 2
var authorities = auth.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.toList();
return new UserInfo(auth.getName(), authorities); 3
}
}-
Allows all authenticated users to access
getUserInfo(). -
Retrieves user details from Spring Security.
-
Returns user information to the client.
Vaadin does not provide a built-in user information type, so you need to define your own:
Source code
Java
public record UserInfo(
@NonNull String name,
@NonNull Collection<String> authorities
) {
}You can include additional user details (e.g., email, avatar) in this type and access them in React.
Setup the Authentication Context
Now, configure a React context to store authentication details, using Vaadin’s helper configureAuth():
Source code
frontend/security/auth.ts
import { configureAuth } from '@vaadin/hilla-react-auth';
import { UserInfoService } from "Frontend/generated/endpoints";
const auth = configureAuth(UserInfoService.getUserInfo) 1
export const useAuth = auth.useAuth 2
export const AuthProvider = auth.AuthProvider 3-
Uses
UserInfoServiceto fetch user details from the server. -
useAuthis a React hook that provides authentication state within views. -
AuthProvideris a React context provider.
Enable the Authentication Context
Next, wrap the root component with <AuthProvider>. First, move index.tsx from src/main/frontend/generated to src/main/frontend. Then, modify it as follows:
Source code
frontend/index.tsx
import { createElement } from 'react';
import { createRoot } from 'react-dom/client';
import { RouterProvider } from 'react-router';
import { router } from 'Frontend/generated/routes.js';
import { AuthProvider } from "Frontend/security/auth";
function App() {
return (
<AuthProvider>
<RouterProvider router={router} />
</AuthProvider>
);
}
...The Login View
The login view is a standard Hilla view. The easiest way to implement one is by using the LoginForm component:
Source code
frontend/views/login.tsx
import { LoginForm } from "@vaadin/react-components";
import { ViewConfig } from "@vaadin/hilla-file-router/types.js";
import { useSearchParams } from "react-router";
export const config: ViewConfig = {
skipLayouts: true, 1
menu: {
exclude: true 2
}
}
export default function LoginView() {
const [searchParams] = useSearchParams()
const hasError = searchParams.has("error"); 3
return (
<main className="flex justify-center items-center w-full h-full">
<LoginForm error={hasError} action="login"/> 4
</main>
)
}-
Disables auto layout to prevent the login view from being embedded in a router layout.
-
Excludes the login view from the navigation menu.
-
Detects if the
?errorquery parameter is present. -
Instructs the login form to send a
POSTrequest to/loginfor authentication.
Spring Security’s form login mechanism automatically processes authentication requests sent to /login. When authentication fails, the user is redirected back to the login page with ?error, which the login view handles.
Server Configuration
To instruct Spring Security to use your login view, modify your security configuration:
Source code
SecurityConfig.java
SecurityConfig.java@EnableWebSecurity
@Configuration
@Import(VaadinAwareSecurityContextHolderStrategyConfiguration.class)
class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// Configure Vaadin's security using VaadinSecurityConfigurer
http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
configurer.loginView("/login");
});
return http.build();
}
...
}Now, when a user tires to access a protected view, they’ll be redirected to the login page.
|
Important
| By default, Vaadin permits access to Hilla views and router layouts, and denies access to Flow views and router layouts. This is covered in more detail in the Protect Views guide. |