Zum Inhalt

Configuring tine for Single Sign On (SSO)

tine as Single Sign On Identity Provider (SSO IdP)

tine can act as SSO identity provider for oidc and SAML2

1) Install SSO application

  • Go to setup.php and make sure SSO is installed
  • In the UI go to Admin > Applications > SSO and make sure SSO is activated
  • Installing SSO will automatically generate the necessary certificates
  • SSO will automatically rotate the certificates every 6 months

2) Generate keys manually

call the tine cli: tine20.php --method=SSO.generateKey

To check if you have valid certificates, you can call these URLs: * https://my.tine.url/sso/saml2/idpmetadata * https://my.tine.url/sso/oauth2/certs

3) Create config

./conf.d/sso.inc.php
<?php

return [
    'SSO' => [
        'pwdLessLogin' => 'both',
        'oauth2' => [
            'enabled' => true,
        ],
        'saml2' => [
            'enabled' => true,
            'tineLogout' => true,
        ],
    ],
];

4) Clear config cache

clearCache
#! /bin/sh

docker-compose exec --user tine20 web sh -c "cd /usr/share/tine20/ && php setup.php --config=\$TINE20_CONFIG_PATH --clear_cache -v"

5) Configure relaying parties

SSO Relaying parties can be configured per UI in the admin module or via cli using curl

- UI

Go to Admin > Applications > SSO and open the tab RELYING PARTIES in the SSO configuration dialog.

- CLI

Login
#! /bin/sh

URL=http://web:4000/
USER=tine20admin
read PASS

TMP=$(curl -s $URL \
  -H 'Content-Type: application/json' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'X-Tine20-ClientAssetHash: 64558b09a551cee0fac4c9f1dcd5c7a3ac5c0e34' \
  -H 'X-Tine20-Request-Type: JSON' \
  --insecure \
  -d '{"jsonrpc":"2.0","method":"Tinebase.login","params":{"username":"'"$USER"'","password":"'"$PASS"'"},"id":0}' \
  | jq  -r '.result.sessionId, .result.jsonKey')

i=0
for line in $TMP; do
  if [ $i -eq 0 ]; then
    SESSIONID="$line"
  else
    JSONKEY="$line"
  fi
    echo "$line"
    i=$((i+1))
done

export SESSIONID
export JSONKEY
- SAML2

The metadata URL of the tine idp (needed in config of the rp) is https://YOURTINEURL/sso/saml2/idpmetadata .

If not given tine fetches the AssertionConsumerService* and singleLogoutService* properties from the optional metaUrl.

Add SAML2 RP
#! /bin/sh

curl $URL \
  -H 'Content-Type: application/json' \
  -H 'Cookie: TINE20SESSID='"$SESSIONID"'' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'X-Tine20-JsonKey: '"$JSONKEY"'' \
  -H 'X-Tine20-Request-Type: JSON' \
  --insecure \
  -d '{"jsonrpc":"2.0","method":"SSO.saveRelyingParty","params":{"recordData":{
    "name": "saml-test-sp",
    "label": "saml-test-sp",
    "description": "you might test with ghcr.io/beryju/saml-test-sp",
    "logo": null,
    "config_class": "SSO_Model_Saml2RPConfig",
    "config": {
      "name": "saml-test-sp",
      "entityid": "saml-test-sp",
      "metaUrl": "http://localhost:4902/saml/metadata",
      "AssertionConsumerServiceBinding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
      "AssertionConsumerServiceLocation": "http://localhost:4902/saml/acs",
      "singleLogoutServiceLocation": "http://localhost:4902/saml/slo",
      "singleLogoutServiceBinding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
      "attributeMapping": {
        "uid": "accountEmailAddress"
      },
      "customHooks": {
        "postAuthenticate": "/etc/tine20/samlPostAuthHook.php"
      },
      "id": "0"
    }
  },"duplicateCheck":true},"id":3}'

Custom attributes mappings

The mapping tine user attributes => SAML2 attributes can be customized the rp's attributeMapping property (JSON formatted)

Example to map user email to SAML2 uid
{
    "uid": "accountEmailAddress"
}

Custom attributes in SAML response

You can add custom attributes which are sent to the rp see customHooks property (JSON formatted) in the rp config.

Example post auth hook
<?php

// example SAML2 post authenticate hook
// adds the users groups to the attributes
$groupCtrl = Tinebase_Group::getInstance();
$userGroups = $groupCtrl->getMultiple($groupCtrl->getGroupMemberships($user->getId()));
$state['Attributes']['groups'] = array_values($userGroups->name); // value must be an array

- OIDC

The OIDC provider url of the tine idp (needed in the config of the rp) is https://YOURTINEURL (no trailing slash).

Add OIDC RP
#! /bin/sh

curl $URL \
  -H 'Accept: */*' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: TINE20SESSID='"$SESSIONID"'' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'X-Tine20-JsonKey: '"$JSONKEY"'' \
  -H 'X-Tine20-Request-Type: JSON' \
  --insecure \
  -d '{"jsonrpc":"2.0","method":"SSO.saveRelyingParty","params":{"recordData":{
    "name": "oidc-test-sp",
    "label": "oidc test service provider",
    "description": "you might test with ghcr.io/beryju/oidc-test-client",
    "logo": "https://openid.net/wordpress-content/uploads/2014/09/openid-r-logo-900x360.png",
    "config_class": "SSO_Model_OAuthOIdRPConfig",
      "config": {
        "redirect_urls": [
          "http://localhost:4901/auth/callback"
        ],
        "secret": "test-secret",
        "is_confidential": false,
        "id": "0"
      }
  },"duplicateCheck":true},"id":3}'

tine as Single Sign On Relaying Party (SSO RP)

tine can act as SSO Relaying Party for OIDC

1) Install SSO application

  • Go to setup.php and make sure SSO is installed
  • In the UI go to Admin > Applications > SSO and make sure SSO is activated

2) Configure identity providers (IdP)

SSO identity providers can be configured per UI in the admin module or via cli using curl

- UI

Go to Admin > Applications > SSO and open the tab EXTERNAL IDENTITY PROVIDERS in the SSO configuration dialog.

- CLI

Login
#! /bin/sh

URL=http://web:4000/
USER=tine20admin
read PASS

TMP=$(curl -s $URL \
  -H 'Content-Type: application/json' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'X-Tine20-ClientAssetHash: 64558b09a551cee0fac4c9f1dcd5c7a3ac5c0e34' \
  -H 'X-Tine20-Request-Type: JSON' \
  --insecure \
  -d '{"jsonrpc":"2.0","method":"Tinebase.login","params":{"username":"'"$USER"'","password":"'"$PASS"'"},"id":0}' \
  | jq  -r '.result.sessionId, .result.jsonKey')

i=0
for line in $TMP; do
  if [ $i -eq 0 ]; then
    SESSIONID="$line"
  else
    JSONKEY="$line"
  fi
    echo "$line"
    i=$((i+1))
done

export SESSIONID
export JSONKEY

NOTE: For following setup to work correctly, a oidc-server-mock to 127.0.0.1 entry is required in /etc/hosts

Add foreign mock IDP
#! /bin/sh

curl $URL \
  -H 'Accept: */*' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: TINE20SESSID='"$SESSIONID"'' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'X-Tine20-JsonKey: '"$JSONKEY"'' \
  -H 'X-Tine20-Request-Type: JSON' \
  --insecure \
  -d '{"jsonrpc":"2.0","method":"SSO.saveExternalIdp","params":{"recordData":{
    "name": "oidc-test-idp",
    "config_class": "SSO_Model_ExIdp_OIdConfig",
    "config": {
      "name": "test idp",
      "provider_url": "http://oidc-server-mock",
      "issuer": "http://oidc-server-mock",
      "client_id": "tine20",
      "client_secret": "tine20"
    },
    "domains": [
      {
        "domain": "mail.test"
      }
    ]
  },"duplicateCheck":true},"id":3}'