mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
331 lines
12 KiB
ReStructuredText
331 lines
12 KiB
ReStructuredText
|
|
Configure Chill for calendar and absence synchronisation and SSO with Microsoft Graph (Outlook)
|
|
===============================================================================================
|
|
|
|
Chill offers the possibility to:
|
|
|
|
* authenticate users using Microsoft Graph, with relatively small adaptations;
|
|
* synchronize calendar in both ways (`see the user manual for a large description of the feature <https://gitea.champs-libres.be/Chill-project/manuals>`_).
|
|
|
|
Both can be configured separately (synchronising calendars without SSO, or SSO without calendar).
|
|
|
|
Please note that the user's email address is the key to associate Chill's users with Microsoft's ones.
|
|
|
|
Configure SSO
|
|
-------------
|
|
|
|
On Azure side
|
|
*************
|
|
|
|
Configure an app with the Azure interface, and give it the name of your choice.
|
|
|
|
Grab the tenant's ID for your app, which is visible on the main tab "Vue d'ensemble":
|
|
|
|
.. figure:: ./saml_login_id_general.png
|
|
|
|
This the variable which will be named :code:`SAML_IDP_APP_UUID`.
|
|
|
|
Go to the "Single sign-on" ("Authentication unique") section. Choose "SAML" as protocol, and fill those values:
|
|
|
|
.. figure:: ./saml_login_1.png
|
|
|
|
1. The :code:`entityId` seems to be arbitrary. This will be your variable :code:`SAML_ENTITY_ID`;
|
|
2. The url response must be your Chill's URL appended by :code:`/saml/acs`
|
|
3. The only used attributes is :code:`emailaddress`, which must match the user's email one.
|
|
|
|
.. figure:: ./saml_login_2.png
|
|
|
|
You must download the certificate, as base64. The format for the download is :code:`cer`: you will remove the first and last line (the ones with :code:`-----BEGIN CERTIFICATE-----` and :code:`-----END CERTIFICATE-----`), and remove all the return line. The final result should be something as :code:`MIIAbcdef...XyZA=`.
|
|
|
|
This certificat will be your :code:`SAML_IDP_X509_CERT` variable.
|
|
|
|
The url login will be filled automatically with your tenant id.
|
|
|
|
Do not forget to provider user's accesses to your app, using the "Utilisateurs et groupes" tab:
|
|
|
|
.. figure:: ./saml_login_appro.png
|
|
|
|
|
|
You must know have gathered all the required variables for SSO:
|
|
|
|
.. code-block::
|
|
|
|
SAML_BASE_URL=https://test.chill.be # must be
|
|
SAML_ENTITY_ID=https://test.chill.be # must match the one entered
|
|
SAML_IDP_APP_UUID=42XXXXXX-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
SAML_IDP_X509_CERT: MIIC...E8u3bk # truncated
|
|
|
|
Configure chill app
|
|
*******************
|
|
|
|
* add the bundle :code:`hslavich/oneloginsaml-bundle`
|
|
* add the configuration file (see example above)
|
|
* configure the security part (see example above)
|
|
* add a user SAML factory into your src, and register it
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
# config/packages/hslavich_onelogin.yaml
|
|
|
|
parameters:
|
|
saml_base_url: '%env(resolve:SAML_BASE_URL)%'
|
|
saml_entity_id: '%env(resolve:SAML_ENTITY_ID)%'
|
|
saml_idp_x509cert: '%env(resolve:SAML_IDP_X509_CERT)%'
|
|
saml_idp_app_uuid: '%env(resolve:SAML_IDP_APP_UUID)%'
|
|
|
|
|
|
hslavich_onelogin_saml:
|
|
# Basic settings
|
|
idp:
|
|
entityId: 'https://sts.windows.net/%saml_idp_app_uuid%/'
|
|
singleSignOnService:
|
|
url: 'https://login.microsoftonline.com/%saml_idp_app_uuid%/saml2'
|
|
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
|
singleLogoutService:
|
|
url: 'https://login.microsoftonline.com/%saml_idp_app_uuid%/saml2'
|
|
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
|
x509cert: '%saml_idp_x509cert%'
|
|
sp:
|
|
entityId: '%saml_entity_id%'
|
|
assertionConsumerService:
|
|
url: '%saml_base_url%/saml/acs'
|
|
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
|
|
singleLogoutService:
|
|
url: '%saml_base_url%/saml/'
|
|
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
|
privateKey: ''
|
|
# Optional settings.
|
|
baseurl: '%saml_base_url%/saml'
|
|
strict: true
|
|
debug: true
|
|
security:
|
|
nameIdEncrypted: false
|
|
authnRequestsSigned: false
|
|
logoutRequestSigned: false
|
|
logoutResponseSigned: false
|
|
wantMessagesSigned: false
|
|
wantAssertionsSigned: false
|
|
wantNameIdEncrypted: false
|
|
requestedAuthnContext: true
|
|
signMetadata: false
|
|
wantXMLValidation: true
|
|
signatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
|
|
digestAlgorithm: 'http://www.w3.org/2001/04/xmlenc#sha256'
|
|
contactPerson:
|
|
technical:
|
|
givenName: 'Tech User'
|
|
emailAddress: 'techuser@example.com'
|
|
support:
|
|
givenName: 'Support User'
|
|
emailAddress: 'supportuser@example.com'
|
|
organization:
|
|
en:
|
|
name: 'Example'
|
|
displayname: 'Example'
|
|
url: 'http://example.com'
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
# config/security.yaml
|
|
# merge this with other existing configurations
|
|
|
|
security:
|
|
|
|
|
|
providers:
|
|
saml_provider:
|
|
# Loads user from user repository
|
|
entity:
|
|
class: Chill\MainBundle\Entity\User
|
|
property: username
|
|
|
|
firewalls:
|
|
|
|
|
|
default:
|
|
# saml part:
|
|
saml:
|
|
username_attribute: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
|
|
# weird behaviour in dev environment... configuration seems different
|
|
# username_attribute: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
|
|
# Use the attribute's friendlyName instead of the name
|
|
use_attribute_friendly_name: false
|
|
user_factory: user_from_saml_factory
|
|
persist_user: true
|
|
check_path: saml_acs
|
|
login_path: saml_login
|
|
logout:
|
|
path: /saml/logout
|
|
|
|
|
|
.. code-block:: php
|
|
|
|
// src/Security/SamlFactory.php
|
|
|
|
namespace App\Security;
|
|
|
|
use Chill\MainBundle\Entity\User;
|
|
use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlTokenInterface;
|
|
use Hslavich\OneloginSamlBundle\Security\User\SamlUserFactoryInterface;
|
|
|
|
class UserSamlFactory implements SamlUserFactoryInterface
|
|
{
|
|
public function createUser(SamlTokenInterface $token)
|
|
{
|
|
$attributes = $token->getAttributes();
|
|
$user = new User();
|
|
$user->setUsername($attributes['http://schemas.microsoft.com/identity/claims/displayname'][0]);
|
|
$user->setLabel($attributes['http://schemas.microsoft.com/identity/claims/displayname'][0]);
|
|
$user->setPassword('');
|
|
$user->setEmail($attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'][0]);
|
|
$user->setAttributes($attributes);
|
|
|
|
return $user;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Configure sync and calendar access
|
|
----------------------------------
|
|
|
|
The purpose of this configuration is the following:
|
|
|
|
- let user read their calendar and shared calendar within Chill (with the same permissions as the one configured in Outlook / Azure);
|
|
- allow chill instance to write appointment ("Rendez-vous") into their calendar, and invite other users to their appointment;
|
|
- allow chill instance to be notified if an appoint is added or removed by the user within another interface than Chill: if the appointment match another one created in the Chill interface, the date and time are updated in Chill;
|
|
- allow chill instance to read the absence of the user and, if set, mark the user as absent in Chill;
|
|
|
|
The sync processe might be configured in the same app, or into a different app on the Azure side.
|
|
|
|
The synchronization processes use Oauth 2.0 / OpenID Connect for authentication and authorization.
|
|
|
|
.. note::
|
|
|
|
Two flows are in use:
|
|
|
|
* we authenticate "on behalf of a user", to allow users to see their own calendar or other user's calendar into the web interface.
|
|
|
|
Typically, when the page is loaded, Chill first check that an authorization token exists. If not, the user is redirected to Microsoft Azure for authentification and a new token is grabbed (most of the times, this is transparent for users).
|
|
|
|
* Chill also acts "as a machine", to synchronize calendars with a daemon background.
|
|
|
|
One can access the configuration using this screen (it is quite well hidden into the multiple of tabs):
|
|
|
|
.. figure:: ./oauth_app_registration.png
|
|
|
|
You can find the oauth configuration on the "Securité > Autorisations" tab, and click on "application registration" (not translated).
|
|
|
|
Add a redirection URI for you authentification:
|
|
|
|
.. figure:: ./oauth_api_authentification.png
|
|
|
|
The URI must be "your chill public url" with :code:`/connect/azure/check` at the end.
|
|
|
|
Allow some authorizations for your app:
|
|
|
|
.. figure:: ./oauth_api_autorisees.png
|
|
|
|
Take care of the separation between autorization "on behalf of a user" (déléguée), or "for a machine" (application).
|
|
|
|
Some explanation:
|
|
|
|
* Users must be allowed to read their user profile (:code:`User.Read`), and the profile of other users (:code:`User.ReadBasicAll`);
|
|
* They must be allowed to read their calendar (:code:`Calendars.Read`), and the calendars shared with them (:code:`Calendars.Read.Shared`);
|
|
|
|
The sync daemon must have write access:
|
|
|
|
* the daemon must be allowed to read all users and their profile, to establish a link between them and the Chill's users: (:code:`Users.Read.All`);
|
|
* it must also be allowed to read and write into the calendars (:code:`Calendars.ReadWrite.All`);
|
|
* for sending invitation to other users, the permission (:code:`Mail.Send`) must be granted;
|
|
* and, for reading the absence status of the user and sync it with chill, it must be able to read the mailboxSettings (:code:`MailboxSettings.Read`).
|
|
|
|
At this step, you might choose to accept those permissions for all users, or let them do it by yourself.
|
|
|
|
Grab your client id:
|
|
|
|
.. figure:: ./oauth_api_client_id.png
|
|
|
|
This will be your :code:`OAUTH_AZURE_CLIENT_ID` variable.
|
|
|
|
|
|
Generate a secret:
|
|
|
|
.. figure:: ./oauth_api_secret.png
|
|
|
|
This will be your :code:`OAUTH_AZURE_CLIENT_SECRET` variable.
|
|
|
|
And get you azure's tenant id, which is the same as the :code:`SAML_IDP_APP_UUID` (see above).
|
|
|
|
Your variables will be:
|
|
|
|
.. code-block::
|
|
|
|
OAUTH_AZURE_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
OAUTH_AZURE_CLIENT_TENANT=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
OAUTH_AZURE_CLIENT_SECRET: 3-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
|
|
Then, configure chill:
|
|
|
|
Enable the calendar sync with microsoft azure:
|
|
|
|
.. code-block:: yaml
|
|
|
|
# config/packages/chill_calendar.yaml
|
|
|
|
chill_calendar:
|
|
remote_calendars_sync:
|
|
microsoft_graph:
|
|
enabled: true
|
|
|
|
and configure the oauth client:
|
|
|
|
.. code-block:: yaml
|
|
|
|
# config/packages/knp_oauth2_client.yaml
|
|
knpu_oauth2_client:
|
|
clients:
|
|
azure:
|
|
type: azure
|
|
client_id: '%env(OAUTH_AZURE_CLIENT_ID)%'
|
|
client_secret: '%env(OAUTH_AZURE_CLIENT_SECRET)%'
|
|
redirect_route: chill_calendar_remote_connect_azure_check
|
|
redirect_params: { }
|
|
tenant: '%env(OAUTH_AZURE_CLIENT_TENANT)%'
|
|
url_api: 'https://graph.microsoft.com/'
|
|
default_end_point_version: '2.0'
|
|
|
|
|
|
You can now process for the first api authorization on the application side, (unless you did it in the Azure interface), and get a first token, by using :
|
|
|
|
:code:`bin/console chill:calendar:msgraph-grant-admin-consent`
|
|
|
|
This will generate a url that you can use to grant your app for your tenant. The redirection may fails in the browser, but this is not relevant: if you get an authorization token in the CLI, the authentication works.
|
|
|
|
Run the processes to synchronize
|
|
--------------------------------
|
|
|
|
The calendar synchronization is processed using symfony messenger. It seems to be intersting to configure a queue (in the postgresql database it is the most simple way), and to run a worker for synchronization, at least in production.
|
|
|
|
The association between chill's users and Microsoft's users is done by this cli command:
|
|
|
|
.. code-block::
|
|
|
|
bin/console chill:calendar:msgraph-user-map-subscribe
|
|
|
|
This command:
|
|
|
|
* will associate the Microsoft's user metadata in our database;
|
|
* and, most important, create a subscription to get notification when the user alter his calendar, to sync chill's event and ranges in sync.
|
|
|
|
The subscription least at most 3 days. This command should be runned:
|
|
|
|
* at least each time a user is added;
|
|
* and, at least, every three days.
|
|
|
|
In production, we advise to run it at least every day to get the sync working.
|
|
|
|
|