From the simple viewpoint, authentication mechanism in CzechIdM can be divided into three areas:
The First access part is simply a request to the /authentication
endpoint, which is handled by LoginController. The authentication is then processed by configured authenticators (for more details see Authenticators). The result of the successful authentication is a JWT token, which is returned to the frontend client through HTTP headers.
Following requests need to contain the information about the user who makes the request. So the client appends the JWT token to the request CIDMST
HTTP header or adds token to url cidmst
parameter (both ways are supported). The AuthenticationFilter
intercepts every request and lets all configured IdmAuthenticationFilter
s process the request. One of them is JwtIdMAuthenticationFilter
, which verifies the JWT token, retrieves the user name from it and authenticates that user.
Of course, following requests can't use the same JWT token forever, because it contains also the expiration date of the token. Therefore, the ExtendExpirationFilter intercepts every requests. This filter verifies current JWT token and creates a new one with extended expiration date. The frontend saves this new JWT token and uses it for following requests.
SSO is an additional ability of the filter mechanism, which can be implemented if desired. Since the filters intercept every request to a secured endpoint, they are also called when the endpoint /authentication/remote-auth
is requested the first time the user comes to CzechIdM (it is requested, because the frontend is so implemented). So there can be some instance of IdmAuthenticationFilter
which will e.g. check some cookie or HTTP header, send its value to some external authority and obtain corresponding user name. The filter then authenticates this user, creates the JWT token a returns it. In the end, the user is authenticated to CzechIdM, even if no credentials of the local CzechIdM user were given to the authentication endpoint.
Components implementing Authenticator are used as an authentication chain. Every such component checks authentication against some authority, see the actual list of authenticators.
Every authenticator defines how the result of its authentication should be processed. For possible types of results see (AuthenticationResponseEnum):
When the authenticator throws an exception, the authentication chain may continue or be broken depending on its defined result type (see results' type). If the authenticator doesn't return any valid object of type LoginDto (i.e. return NULL), the authentication chain continues.
The authenticators are ordered. They are processed in defined order in the implementation of the class AuthenticationManager. The authentication manager also checks the module to which the authenticator belongs. Authenticators from inactive modules are removed from the authentication chain.
DefaultCoreAuthenticator is the standard authenticator of IdM. It checks LoginDto against user name and password in the local IdM repository.
The service LoginService is called in this authenticator.
The result type of this authenticator is SUFFICIENT, it's order is 0.
DefaultAccAuthenticator checks the LoginDto against an end system. Users use their internal IdM login and their password from the end system.
The end system is defined in the configuration attribute (the UUID of the end system):
# ID system against which to authenticate idm.sec.security.auth.systemId=
First, the authenticator tries to find an end system with given UUUID. If such system doesn't exist, the authentication returns NULL. Otherwise, the authenticator finds the mapped attribute of the system which is marked as Authentication attr.
.
Authentication attr.
in the system mapping, the identifier attribute is used by default.
Next, the authenticator finds the identity for given login. All accounts of this identity for the given system are processed and the method Authenticate is called for them one-by-one. The processing is stopped after the first successful authentication.
The result type of this authenticator is SUFFICIENT. It's order is 10, which means that this authenticator would be processed after DefaultCoreAuthenticator
When users want to change their password in IdM, they will be required to fill their old password (unless the configuration attribute requireOldPassword is set differently, see below). It's possible that their local password in CzechIdM is distinct from their password in end systems. In such situation, users must use the password which satisfies the authentication chain (the same authentication chain that is used during authentication - same rules, same order of processing). If the (old) password is validated successfully, users can change their password.
The configuration attribute idm.pub.core.identity.passwordChange.requireOldPassword= determines whether the users are required to fill in the old password when changing their password. The possible values are: