Security
Dictionary terms
- Base permission - basic permission, e.g.
READ
,CREATE
,UPDATE
,DELETE
- Group permission - group permission could contain base permissions. Group is related to some domain object, e.g.
IDENTITY
,ROLE
- Authority - Group + base permission, e.g.
IDENTITY_READ
,ROLE_CREATE
. Authority is granted to identity by authentication.
API authentication
API access requires the user to be authenticated, excluding a few public endpoints. We can divide the sign in into two parts:
- authentication - the user proves his identity
- authorization - the user has access to given resource
Authentication
Authentication is implemented through a request filterchain. The filters must always follow specified behavior:
- if credentials are OK, continue to authorization
- if credentials do not match, pass request to another filter in chain
In reality there is only one authentication servlet filter - AuthenticationFilter
. Others filters are Spring beans implementing IdmAuthenticationFilter
interface. An exception in filters is the ExtendExpirationFilter
, which is another servlet filter handling the extension of expiration date of JWT tokens. This filter also controls possible exceptions in authentication flow.
API endpoints
There are 2 endpoints for successful user login:
- /authentication - POST, public - authentication, returns JWT token
- /authentication/remote-auth - GET, secured - authentication against external service, returns JWT token and expects the user to be successfully authenticated by one of filters
And one endpoint for user logout:
- /authentication - DELETE - logout with used JWT token (⇒ disable used JWT token)
Implemented authentication filters
Filter do not check authorization or user's permissions, just validate the request data, transform these and pass them to Authentication Managers. There are following filters in IdM core (the core module):
- BasicIdMAuthenticationFilter
- HTTP Basic authentication, login, and password are base64 encoded in HTTP header "Authorization" prefixed by "Basic ", according to RFC 2617
- internal API transforms the login and password and passes them to Authorization Manager
- enabled by default
- JwtIdMAuthenticationFilter
- validates IdM JWT token (read as "jot")
- tokens without expiration are taken as valid
- HMAC256
- enabled by default
- SsoIdmAuthenticationFilter
- used mainly for AD SSO authentication, expects configured web server in front of IdM which handles Kerberos authentication
- processes the result of the authentication in the HTTP header "REMOTE_USER"
- disabled by default, can be enabled by the configuration property
idm.sec.core.authentication-filter.core-sso-authentication-filter.enabled=true
- external authentication server
- CzechIdM is ready to authenticate users based on external resource
- external filters are based on the same principles mentioned above
- primary purpose is to issue the internal IdM JWT token to user using the remote-auth endpoint
- filter behaves quite permissively - if user accesses other endpoints then those for authentication, the filter signs the user in for each request and completes the request (if the user is authorized)
Authorization and JWT token
User authorization is checked on the API endpoint layer and enforced by Spring Security. The content of IdM JWT:
- currentUsername - effective user's login
- originalUsername - logged user's login
- currentIdentityId - effective user's ID
- originalIdentityId - logged user's ID
- exp - token expiration date
- iat - issued at date
All IdM JWT tokens are signed using HMAC256 algorithm. The symmetric encryption key is configuration property of CzechIdM, stored as "idm.sec.security.jwt.secret.token". Default token expiration time is 10 minutes. JWT tokens are persisted in database (IdmToken
entity) with assigned authorities. When identity is logged out, token is disabled. Disabled and expired tokens are purged periodically by internal scheduled task.
Backend of CzechIdM supports immediate detection of user's authorization change. Each modification type is implemented as application event processor, for further details please check the source code and tests :) When user's authorization changes, then persisted tokens, which user owns, are disabled ⇒ user is logged out. Types of modifications:
- removal of role, which carries application permissions ⇒ user losses some permission.
- disabling the user
- role's permissions change - revokes tokens of all users which have the role assigned
TokenManager
TokenManager
is used for creating IdM tokens. Token can be created for different purpose (token type). When token is used, can be disabled (e.g. logout, one time usage).
Token expiration extension
By default both frontend (FE) and backend (BE) automatically extend the expiration of IdM JWT. In case of successful GET request on API, the token expiration is extended on BE and passed in HTTP response (watch out for CORS, has to be explicitly allowed, since the HTTP header is called "CIDMST"). FE (RestApiService.js
) automatically disassembles the response looking for auth. token. If token is present, it is set as new token which shall be used for new API requests (done in App.js
). Expiration is extended in one minute window - when token has expiration at least one minute older than new one (prevent to persist token every api call).
Developer tip: do not trust the console, especially while working with promises:
static printHeadersOK(response) { console.log(response.headers.get('CIDMST')); prints header value } static printHeadersWRONG(response) { console.log(response.headers); // prints '{}', object looks empty }
SSO
SSO support on FE is implemented by issuing the internal IdM JWT without the need to type in user's credentials. This is done by sending a "prerequest" onto secured /authentication/remote-auth endpoint, accessible only to authenticated users. The authentication itself must be done in one of auth filters.
We expect either HTTP header or Cookie to be the bearer of the remote authentication data. When the user accesses IdM, FE first tries to sign him in using the remote-auth
. The remote-auth
attempt is done only on first access to CzechIdM, token expiration, authority change or user login.
SSO authentication to AD domain can be configured with the help of SsoIdmAuthenticationFilter and Apache web server, which is installed in front of IdM. For more details about SSO configuration see SSO install guide.