mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
321 lines
11 KiB
ReStructuredText
321 lines
11 KiB
ReStructuredText
|
|
Configure Chill for calendar sync 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). When calendar sync is configured without SSL, 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
|
|
--------------
|
|
|
|
The sync processe might be configured in the same app, or into a different app.
|
|
|
|
The synchronization processes use Oauth2.0 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.
|
|
|
|
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.
|
|
|
|
|