diff --git a/docs/en/developer.md b/docs/en/developer.md index 0db56fd..183840e 100644 --- a/docs/en/developer.md +++ b/docs/en/developer.md @@ -21,6 +21,7 @@ We assume ADFS 2.0 or greater is used as an IdP. - [Service Provider (SP)](#service-provider-sp) - [Identity Provider (IdP)](#identity-provider-idp) - [Additional configuration for Azure AD](#additional-configuration-for-azure-ad) + - [User groups mapping](#user-groups-mapping) - [GUID Transformation](#guid-transformation) - [Establish trust](#establish-trust) - [Configure SilverStripe Authenticators](#configure-silverstripe-authenticators) @@ -37,6 +38,7 @@ We assume ADFS 2.0 or greater is used as an IdP. - [Adjust the requested AuthN contexts](#adjust-the-requested-authn-contexts) - [Create your own SAML configuration for completely custom settings](#create-your-own-saml-configuration-for-completely-custom-settings) - [Additional GET Query Params for SAML](#additional-get-query-params-for-saml) + - [Automatically redirect after authentication](#automatically-redirect-after-authentication) - [Resources](#resources) @@ -151,6 +153,22 @@ SilverStripe\SAML\Extensions\SAMLMemberExtension: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Email' ``` +### User groups mapping + +By default, any new users logged in using SSO will not have any groups assigned to them. User groups can be enabled via + +```yml +SilverStripe\SAML\Services\SAMLConfiguration: + map_user_group: true +``` + +and specify the claims field to map + +```yml +SilverStripe\SAML\Helpers\SAMLUserGroupMapper: + group_claims_field: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/groups' +``` + ### GUID Transformation If you prefer to receive the GUID in lower-case or upper-case format you can use the @@ -392,6 +410,14 @@ SilverStripe\SAML\Services\SAMLConfiguration: this configuration allows you to add two GET query parameters to endpoint request URL: `https://your-idp.com/singleSignOnService/saml2?someGetQueryParameter=value&AnotherParameter=differentValue&SAMLRequest=XYZ....` +### Automatically redirect after authentication +If the user has CMS permission and you want to redirect to the CMS after successful authentication, you can set the default login destination via: + +```yaml +SilverStripe\Security\Security: + default_login_dest: 'admin' +``` + ## Resources - [ADFS Deep-Dive: Onboarding Applications](http://blogs.technet.com/b/askpfeplat/archive/2015/03/02/adfs-deep-dive-onboarding-applications.aspx) diff --git a/src/Control/SAMLController.php b/src/Control/SAMLController.php index 85ddcc9..8373a50 100644 --- a/src/Control/SAMLController.php +++ b/src/Control/SAMLController.php @@ -5,29 +5,28 @@ use Exception; use function gmmktime; - +use function uniqid; use OneLogin\Saml2\Auth; use OneLogin\Saml2\Constants; -use OneLogin\Saml2\Utils; use OneLogin\Saml2\Error; +use OneLogin\Saml2\Utils; use Psr\Log\LoggerInterface; +use SilverStripe\Control\Controller; +use SilverStripe\Control\Director; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Core\Config\Config; +use SilverStripe\Core\Injector\Injector; use SilverStripe\ORM\ValidationResult; use SilverStripe\SAML\Authenticators\SAMLAuthenticator; use SilverStripe\SAML\Authenticators\SAMLLoginForm; use SilverStripe\SAML\Helpers\SAMLHelper; -use SilverStripe\Control\Controller; -use SilverStripe\Control\Director; -use SilverStripe\Control\HTTPResponse; -use SilverStripe\Core\Injector\Injector; +use SilverStripe\SAML\Helpers\SAMLUserGroupMapper; use SilverStripe\SAML\Model\SAMLResponse; use SilverStripe\SAML\Services\SAMLConfiguration; use SilverStripe\Security\IdentityStore; use SilverStripe\Security\Member; use SilverStripe\Security\Security; -use function uniqid; - /** * Class SAMLController * @@ -212,6 +211,14 @@ public function acs() // Both SAML and LDAP identify Members by the same GUID field. $member->write(); + $mapUserGroup = Config::inst()->get(SAMLConfiguration::class, 'map_user_group'); + // Map user groups + if ($mapUserGroup) { + $mapper = SAMLUserGroupMapper::singleton(); + + $member = $mapper->map($attributes, $member); + } + // Hook for modifying login behaviour $this->extend('updateLogin'); diff --git a/src/Helpers/SAMLUserGroupMapper.php b/src/Helpers/SAMLUserGroupMapper.php new file mode 100644 index 0000000..d58b5a8 --- /dev/null +++ b/src/Helpers/SAMLUserGroupMapper.php @@ -0,0 +1,65 @@ + '%$' . SAMLConfiguration::class, + ]; + + /** + * Check if group claims field is set and assigns member to group + * + * @param [] $attributes + * @param Member $member + * @return Member + */ + public function map($attributes, $member): Member + { + $groups = $this->config()->get('group_claims_field'); + + if (!isset($attributes[$groups])) { + return $member; + } + + // Get groups from saml response + $groupTitles = $attributes[$groups]; + + foreach ($groupTitles as $groupTitle) { + // Get Group object by Title + $group = DataObject::get_one(Group::class, [ + '"Group"."Title"' => $groupTitle + ]); + + // Create group if it doesn't exist yet + if (!$group) { + $group = new Group(); + $group->Title = $groupTitle; + $group->write(); + } + + $member->Groups()->add($group); + } + + return $member; + } +}