Authentication and Authorization: create users, handle login, protect pages
Subsections
- User Login
-
Login both with normal or ajax request
- User Registration
-
Registering new users
Description
The Yada Framework uses Spring Security to implement authentication (identifying the current user) and authorization (limiting access to web pages according to the user role). The YadaWebSecurity library must be added to the classpath in order for this to work.
Cross Site Request Forgery (CSRF) prevention is currently disabled by default |
Setup
The WebConfig
class must extend YadaWebSecurityConfig
instead of YadaWebConfig
:
@ComponentScan(basePackages = { "com.example.web" })
public class WebConfig extends YadaWebSecurityConfig {
The required YadaWebSecurity entities must also be added to persistence.xml
in order to create the DB schema:
<persistence-unit name="yadaPersistenceUnit">
<class>net.yadaframework.security.persistence.entity.YadaSocialCredentials</class>
<class>net.yadaframework.security.persistence.entity.YadaUserCredentials</class>
<class>net.yadaframework.security.persistence.entity.YadaUserProfile</class>
<class>net.yadaframework.security.persistence.entity.YadaRegistrationRequest</class>
<class>net.yadaframework.security.persistence.entity.YadaAutoLoginToken</class>
Some security parameters must be configured in conf.webapp.prod.xml
:
<config>
<security>
<sessionTimeoutMinutes>240</sessionTimeoutMinutes> (1)
<passwordLength min='5' max='128' /> (2)
<encodePassword>true</encodePassword> (3)
<maxFailedAttempts>10</maxFailedAttempts> (4)
<failedAttemptsLockoutMinutes>10</failedAttemptsLockoutMinutes> (5)
<autologinExpirationHours>48</autologinExpirationHours> (6)
<roles> (7)
<role>
<id>8</id>
<key>ADMIN</key>
</role>
<role>
<id>2</id>
<key>USER</key>
</role>
</roles>
</security>
1 | this value must be the same used in the web.xml <session-config><session-timeout> tag and is for checking session expiration |
2 | values for password validation |
3 | when true, passwords are encrypted in the database |
4 | the number of consecutive failed login attempts before an account is locked out |
5 | the number of minutes to wait for a locked out account before a new login attempt can be made |
6 | the validity time of autologin links |
7 | list of roles that users can have |
The list of roles defines an id and a key for every role a user can have in the application. A user can have more than one role. Role ids are just integer numbers with no special meaning, but they must be unique. Role keys can be any word that reminds of the activity the user can perform on the site. In this example, "USER" is any user with no particular privileges, and "ADMIN" is a site administrator. Role names should be specific to the application domain. For example, a "MANAGER" could handle users, a "GUEST" could have limited access, a "TEACHER" could see the score editing form. It’s important not to change either the id or the key once the application goes to production because these values are stored in the database.
User Profile
Every web application handles a specific kind of user with different attributes like name, address, age etc.
All user attributes are known as a "user profile".
The Yada Framework provides the YadaUserProfile
class with basic attributes like firstName
or avatar
image.
The web application must subclass it with its own UserProfile
class in order to add application-specific
attributes:
@Entity
public class UserProfile extends YadaUserProfile {
@Column(length = 32)
String nickname; // This is an example of UserProfile customization
The user login name is always the email address. Together with the password it is stored in the userCredentials
attribute of YadaUserProfile
, of type YadaUserCredentials
.
Root user
Usually, in a web application, users either register themselves or are added by an administrator.
In any case, there must be an initial user with administrator rights that is already in the database
when the application starts for the first time.
This can be implemented by subclassing YadaUserSetup
in any bean, for example a "Setup" bean:
@Component
public class Setup extends YadaUserSetup<UserProfile> {
Just by doing this, the users defined in the configuration will be created, if not there already,
at each application startup.
This configuration in conf.webapp.prod.xml
creates one "admin" user (but it doesn’t have to be just one):
<config>
<setup>
<users>
<user>
<nickname>admin</nickname> <!-- This is an example of UserProfile customization -->
<email>admin@EXAMPLE.com</email>
<password>changeit</password>
<locale>en_US</locale>
<timezone>Europe/Rome</timezone>
<role>USER</role>
<role>ADMIN</role>
</user>
</users>
</setup>
The xml user definition can contain all attributes defined in the application-specific UserProfile class: they will be set using reflection.
When a <password> is not provided, the user will be created with a random password that can only be known if <encodePassword> is false by reading the database directly. When the password is encoded, the only way of performing login is by resetting the password using the password recovery procedure that must have been implemented. |
Sensitive data like the password of a production user or of a email provider can be stored in a server-specific file that by
default is located in For example, if the security.properties file contains
Do not use dots in variable names or interpolation won’t work. |
To delete all users (for development test):
delete from YadaUserCredentials_roles;
delete yup, yuc FROM YadaUserProfile yup join YadaUserCredentials yuc on yup.userCredentials_id = yuc.id;
Authorization
The SecurityConfig
class is where the application endpoints are protected so that only specific roles can
access specific pages.
The default implementation allows users with "ADMIN" role to access the /admin
path and with "USER" role
to access the /user
path. This can of course be changed as needed.
- Credentials expiration. See YadaAuthenticationFailureHandler.onAuthenticationFailure() - Multiple SecurityConfig - UserProfileDao