Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
}
},
"branch-alias": {
"dev-master": "2.0.x-dev",
"dev-master": "2.1.x-dev",
"dev-2.0.x": "2.0.x-dev",
"dev-1.0.x": "1.0.x-dev"
}
}
Expand Down
1 change: 1 addition & 0 deletions saml/install/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[saml]
automaticAccountCreation = on
allowSAMLAccountToUseLocalPassword = on
useOnlyNameIDAssertionToAuthenticate = off

[saml:sp]

Expand Down
34 changes: 34 additions & 0 deletions saml/lib/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ class Configuration {
*/
protected $allowSAMLAccountToUseLocalPassword = true;

/**
* @var bool says if the user should be created/authenticated using only the loginAttribute property.
* attributesMapping (Login and E-Mail) will be both overwritten by the loginAttribute value
*/
protected $useOnlyNameIDAssertionToAuthenticate = false;

/**
* @var array list of dao properties that can be used for mapping
*/
Expand All @@ -49,6 +55,12 @@ class Configuration {

protected $idpLabel = '';

/**
* @var string placeholder used to fill login field and mandatory attributes fields if the
* useOnlyNameIDAssertionToAuthenticate property is set to true
*/
protected $nameIdPlaceholder = 'NameID';

/**
* Configuration constructor.
*
Expand Down Expand Up @@ -76,6 +88,10 @@ public function __construct($checkConfig = true, $iniConfig = null)
$this->allowSAMLAccountToUseLocalPassword = $iniConfig->saml['allowSAMLAccountToUseLocalPassword'];
}

if (isset($iniConfig->saml['useOnlyNameIDAssertionToAuthenticate'])) {
$this->useOnlyNameIDAssertionToAuthenticate = $iniConfig->saml['useOnlyNameIDAssertionToAuthenticate'];
}

$this->fixConfigValues($iniConfig);
$spConfig = $iniConfig->{'saml:sp'};

Expand Down Expand Up @@ -443,6 +459,15 @@ function getOrganization()
return $org;
}

/**
* get the nameIdPlaceholder value
* @return string
*/
function getNameIdPlaceholder()
{
return $this->nameIdPlaceholder;
}

/**
* indicates if accounts should be created after authentication if they
* don't exist.
Expand All @@ -462,6 +487,15 @@ function isAllowingSAMLAccountToUseLocalPassword()
return $this->allowSAMLAccountToUseLocalPassword;
}

/**
* says if the user should be created/authenticated using only the loginAttribute property.
* attributesMapping (Login and E-Mail) will be both overwritten by the loginAttribute value
* @return bool
*/
function mustUseOnlyNameIDAssertionToAuthenticate()
{
return $this->useOnlyNameIDAssertionToAuthenticate;
}

function getIdpURL()
{
Expand Down
11 changes: 11 additions & 0 deletions saml/lib/ConfigurationModifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ public function __construct($iniConfig = null)
parent::__construct(false, $iniConfig);
}

/**
* @param bool $onlyNameID
*/
public function setUseOnlyNameIDAssertionToAuthenticate($onlyNameID)
{
$this->useOnlyNameIDAssertionToAuthenticate = !!$onlyNameID;
}

/**
* @param bool $automatic
*/
Expand Down Expand Up @@ -199,6 +207,9 @@ public function save()
$liveConfig->setValues($mapping, 'saml:attributes-mapping');
$appConfig->{'saml:attributes-mapping'} = $mapping;

$liveConfig->setValue('useOnlyNameIDAssertionToAuthenticate', $this->useOnlyNameIDAssertionToAuthenticate, 'saml');
$appConfig->saml['useOnlyNameIDAssertionToAuthenticate'] = $this->useOnlyNameIDAssertionToAuthenticate;

$liveConfig->setValue('automaticAccountCreation', $this->automaticAccountCreation, 'saml');
$appConfig->saml['automaticAccountCreation'] = $this->automaticAccountCreation;

Expand Down
7 changes: 7 additions & 0 deletions saml/lib/Saml.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ function processLoginResponse($request)

$loginAttr = $this->config->getSAMLAttributeForLogin();
$attributes = $auth->getAttributes();

if($this->config->mustUseOnlyNameIDAssertionToAuthenticate()){
$attributes = array();
$loginAttr = $this->config->getNameIdPlaceholder();
$attributes[$loginAttr] = array($auth->getNameId());
}

if (empty($attributes)) {
throw new LoginException(
\jLocale::get('saml~auth.authentication.error.saml.attributes.missing', array($loginAttr)),
Expand Down
19 changes: 16 additions & 3 deletions samladmin/controllers/attrmapping.classic.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ public function initform()
$form = jForms::create('attrmapping');
$this->setupForm($form, $config);

// nameIdPlaceholder
$form->setData('nameIdPlaceholder', $config->getNameIdPlaceholder());
$form->setData('login', $config->getSAMLAttributeForLogin());
$form->setData('useOnlyNameIDAssertionToAuthenticate', $config->mustUseOnlyNameIDAssertionToAuthenticate());
$form->setData('automaticAccountCreation', $config->isAutomaticAccountCreation());
$form->setData('allowSAMLAccountToUseLocalPassword', $config->isAllowingSAMLAccountToUseLocalPassword());
$rep = $this->getResponse('redirect');
Expand All @@ -81,7 +84,7 @@ public function edit()

$tpl = new jTpl();
$tpl->assign('attrform', $form);
//$rep->addJSLink(jUrl::get('samladmin~config:asset', array('file'=>'sp.js')));
$rep->addJSLink(jUrl::get('samladmin~config:asset', array('file'=>'attr.js')));
$rep->body->assign('MAIN', $tpl->fetch('attrmapping'));
$rep->body->assign('selectedMenuItem', 'samlconfig');
return $rep;
Expand All @@ -102,18 +105,28 @@ function save()
$listOfField = $this->setupForm($form, $config);

$form->initFromRequest();
$daoProperties = $config->getAuthorizedDaoPropertiesForMapping();

if($this->request->getParam("useOnlyNameIDAssertionToAuthenticate")){
$form->setData('login',$config->getNameIdPlaceholder());
foreach ($form->getControls() as $name => $mctrl) {
if($mctrl->required && substr($name,0,5) == 'attr_'){
$form->setData($name,$config->getNameIdPlaceholder());
}
}
}

if (!$form->check()) {
$rep->action = 'samladmin~attrmapping:edit';
return $rep;
}

$config = new \Jelix\Saml\ConfigurationModifier();
$config->setSAMLAttributeForLogin($form->getData('login'));
$config->setUseOnlyNameIDAssertionToAuthenticate($form->getData('useOnlyNameIDAssertionToAuthenticate'));
$config->setAutomaticAccountCreation($form->getData('automaticAccountCreation'));
$config->setAllowSAMLAccountToUseLocalPassword($form->getData('allowSAMLAccountToUseLocalPassword'));

$daoProperties = $config->getAuthorizedDaoPropertiesForMapping();

/** @var jFormsControlGroup $groupCtrl */
$mapping = array();
foreach($listOfField as $ctrlRef) {
Expand Down
7 changes: 7 additions & 0 deletions samladmin/forms/attrmapping.form.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<form xmlns="http://jelix.org/ns/forms/1.1">

<hidden ref="nameIdPlaceholder" />

<input ref="login" type="string" required="true">
<label locale="samladmin~admin.attrmapping.form.login.label"/>
</input>
Expand All @@ -9,6 +11,11 @@
<label locale="samladmin~admin.attrmapping.form.attrsgroup.label" />
</group>

<checkbox ref="useOnlyNameIDAssertionToAuthenticate">
<label locale="samladmin~admin.attrmapping.form.useOnlyNameIDAssertionToAuthenticate.label"/>
<help locale="samladmin~admin.attrmapping.form.useOnlyNameIDAssertionToAuthenticate.help"/>
</checkbox>

<checkbox ref="automaticAccountCreation">
<label locale="samladmin~admin.attrmapping.form.automaticAccountCreation.label"/>
</checkbox>
Expand Down
2 changes: 2 additions & 0 deletions samladmin/locales/en_US/admin.UTF-8.properties
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ attrmapping.title=Configuration of SAML accounts
attrmapping.error.not.set=Configuration of SAML attributes is not completed
attrmapping.form.login.label=SAML attribute containing the id/login of the user
attrmapping.form.attrsgroup.label=list of SAML attributes corresponding to each user properties
attrmapping.form.useOnlyNameIDAssertionToAuthenticate.label=Ignore attributes from SAML response and use only the NameID assertion to create or authenticate the user
attrmapping.form.useOnlyNameIDAssertionToAuthenticate.help=Some IP (Identity provider) might not be configured to forward user's attributes. WARNING: if checked, the mandatory fields required in the attributes section used to create the local user will be filled with the NameID value.
attrmapping.form.automaticAccountCreation.label=User accounts are automatically created if they don't exist into the application, when user use SAML to authenticate themselves
attrmapping.form.allowSAMLAccountToUseLocalPassword.label=Users using SAML can also use their local accounts of the application to login

Expand Down
6 changes: 6 additions & 0 deletions samladmin/templates/attrmapping.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
{ctrl_label 'attrsgroup'}
{ctrl_control 'attrsgroup'}
</div>

<p>
{ctrl_control 'useOnlyNameIDAssertionToAuthenticate'}
{ctrl_label 'useOnlyNameIDAssertionToAuthenticate'}
</p>

<p>
{ctrl_control 'automaticAccountCreation'}
{ctrl_label 'automaticAccountCreation'}
Expand Down
25 changes: 25 additions & 0 deletions samladmin/www/attr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
$(document).ready(()=>{

document.getElementById('jforms_samladmin_attrmapping').addEventListener('jformsready', ()=>{
let form = jFormsJQ.getForm('jforms_samladmin_attrmapping').element;
let onlyNameIdCheckbox = form.elements['useOnlyNameIDAssertionToAuthenticate'];
let nameIdPlaceholder = form.elements['nameIdPlaceholder'].value;
if (onlyNameIdCheckbox) {
onlyNameIdCheckbox.addEventListener('change', (e)=>{
return useOnlyNameIDAssertionToAuthenticateChange(e.target.checked);
})

useOnlyNameIDAssertionToAuthenticateChange(onlyNameIdCheckbox.checked);
}

function useOnlyNameIDAssertionToAuthenticateChange(checked){
let attrRequired = document.querySelectorAll("#jforms_samladmin_attrmapping_attrsgroup input.jforms-required");
let nameIdFileds = [form.login, ...attrRequired];

nameIdFileds.forEach((f)=>{
f.value = checked ? nameIdPlaceholder : f.value;
f.disabled = checked ? true : false;//!f.disabled;
})
}
})
})