|
|
@ -3302,7 +3302,30 @@ more convenient, but provides us with less control.
|
|
|
|
|
|
|
|
|
|
|
|
### Authentication
|
|
|
|
### Authentication
|
|
|
|
|
|
|
|
|
|
|
|
@todo
|
|
|
|
Instead of relying on PHP sessions, we decided to use an authentication flow
|
|
|
|
|
|
|
|
based on JWT tokens (RFC 7519). On successful login, the user is issued an
|
|
|
|
|
|
|
|
access token that they have to send with subsequent requests using the HTTP
|
|
|
|
|
|
|
|
Authorization header (Authorization: Bearer <token>). The token has a limited
|
|
|
|
|
|
|
|
validity period and has to be renewed periodically using a dedicated API
|
|
|
|
|
|
|
|
endpoint.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
To implement this behavior in Nette framework, a new IUserStorage implementation
|
|
|
|
|
|
|
|
was created (`App\Security\UserStorage`), along with an IIdentity and
|
|
|
|
|
|
|
|
authenticators for both our internal login service and CAS. The authenticators
|
|
|
|
|
|
|
|
are not registered in the DI container, they are invoked directly instead. On
|
|
|
|
|
|
|
|
successful authentication, the returned `App\Security\Identity` object is stored
|
|
|
|
|
|
|
|
using the `Nette\Security\User::login()` method. The user storage service works
|
|
|
|
|
|
|
|
with the http request to extract the access token if possible.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The logic of issuing tokens is contained in the `App\Security\AccessManager`
|
|
|
|
|
|
|
|
class. Internally, it uses the Firebase JWT library.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The authentication flow is contained in the `LoginPresenter` class, which serves
|
|
|
|
|
|
|
|
the `/login` endpoint group.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
An advantage of this approach is being able control the authentication process
|
|
|
|
|
|
|
|
completely instead of just receiving session data through a global variable.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Permissions
|
|
|
|
### Permissions
|
|
|
|
|
|
|
|
|
|
|
|