Page MenuHomePhabricator

D7525.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1085,6 +1085,7 @@
'PhabricatorAuthProviderOAuthTwitch' => 'applications/auth/provider/PhabricatorAuthProviderOAuthTwitch.php',
'PhabricatorAuthProviderPassword' => 'applications/auth/provider/PhabricatorAuthProviderPassword.php',
'PhabricatorAuthProviderPersona' => 'applications/auth/provider/PhabricatorAuthProviderPersona.php',
+ 'PhabricatorAuthProviderShibboleth' => 'applications/auth/provider/PhabricatorAuthProviderShibboleth.php',
'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.php',
'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php',
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
@@ -3423,6 +3424,7 @@
'PhabricatorAuthProviderOAuthTwitch' => 'PhabricatorAuthProviderOAuth',
'PhabricatorAuthProviderPassword' => 'PhabricatorAuthProvider',
'PhabricatorAuthProviderPersona' => 'PhabricatorAuthProvider',
+ 'PhabricatorAuthProviderShibboleth' => 'PhabricatorAuthProvider',
'PhabricatorAuthRegisterController' => 'PhabricatorAuthController',
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
diff --git a/src/applications/auth/provider/PhabricatorAuthProviderShibboleth.php b/src/applications/auth/provider/PhabricatorAuthProviderShibboleth.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/provider/PhabricatorAuthProviderShibboleth.php
@@ -0,0 +1,246 @@
+<?php
+
+final class PhabricatorAuthProviderShibboleth
+ extends PhabricatorAuthProvider {
+
+ private $adapter;
+
+ public function getProviderName() {
+ return pht('Shibboleth');
+ }
+
+ public function getDescriptionForCreate() {
+ return pht(
+ 'Configure a trust relationship for Shibboleth (Single Sign On) '.
+ 'autheticated users to automatically log in to Phabricator.');
+ }
+
+ public function getDefaultProviderConfig() {
+ return parent::getDefaultProviderConfig();
+ }
+
+ public function getAdapter() {
+ if (!$this->adapter) {
+ $conf = $this->getProviderConfig();
+
+
+ $adapter = id(new PhutilAuthAdapterShibboleth())
+ ->setShibSessionIdField(
+ $conf->getProperty(self::KEY_SHIB_SESSION_ID_FIELD))
+ ->setShibApplicationIdField(
+ $conf->getProperty(self::KEY_SHIB_APPLICATION_ID_FIELD))
+ ->setUseridField(
+ $conf->getProperty(self::KEY_USERID_FIELD))
+ ->setUsernameField(
+ $conf->getProperty(self::KEY_USERNAME_FIELD))
+ ->setRealnameField(
+ $conf->getProperty(self::KEY_REALNAME_FIELD))
+ ->setEmailField(
+ $conf->getProperty(self::KEY_EMAIL_FIELD))
+ ->setPageURIPattern(
+ $conf->getProperty(self::KEY_PAGE_URI_PATTERN))
+ ->setImageURIPattern(
+ $conf->getProperty(self::KEY_IMAGE_URI_PATTERN));
+ $this->adapter = $adapter;
+ }
+ return $this->adapter;
+ }
+
+ protected function renderLoginForm(AphrontRequest $request, $mode) {
+ $viewer = $request->getUser();
+
+ $dialog = id(new AphrontDialogView())
+ ->setSubmitURI($this->getLoginURI())
+ ->setUser($viewer);
+
+ if ($mode == 'link') {
+ $dialog->setTitle(pht('Link Shibboleth Account'));
+ $dialog->addSubmitButton(pht('Link Accounts'));
+ $dialog->addCancelButton($this->getSettingsURI());
+ } else if ($mode == 'refresh') {
+ $dialog->setTitle(pht('Refresh Shibboleth Account'));
+ $dialog->addSubmitButton(pht('Refresh Account'));
+ $dialog->addCancelButton($this->getSettingsURI());
+ } else {
+ if ($this->shouldAllowRegistration()) {
+ $dialog->setTitle(pht('Login or Register with Shibboleth'));
+ $dialog->addSubmitButton(pht('Login or Register'));
+ } else {
+ $dialog->setTitle(pht('Login with Shibboleth'));
+ $dialog->addSubmitButton(pht('Login'));
+ }
+ if ($mode == 'login') {
+ $dialog->addCancelButton($this->getStartURI());
+ }
+ }
+
+ $errors = array();
+ if ($request->isHTTPPost()) {
+ $errors[] = pht('Invalid Shibboleth session.');
+ }
+
+ if ($errors) {
+ $errors = id(new AphrontErrorView())->setErrors($errors);
+ }
+
+ $dialog->appendChild($errors);
+
+ return $dialog;
+ }
+
+ public function processLoginRequest(
+ PhabricatorAuthLoginController $controller) {
+
+ $request = $controller->getRequest();
+ $response = null;
+ $account = null;
+
+ $adapter = $this->getAdapter();
+ $headers = array();
+ $header_names = $adapter->getHeaderNames();
+ foreach ($header_names as $h) {
+ $headers[$h] = $request->getHTTPHeader($h);
+ }
+ if (! $adapter->setUserDataFromRequest($headers)) {
+ $response = $controller->buildProviderPageResponse(
+ $this,
+ $this->renderLoginForm($request, 'login'));
+ return array($account, $response);
+ }
+
+ $account_id = $adapter->getAccountID();
+
+ return array($this->loadOrCreateAccount($account_id), $response);
+ }
+
+
+ const KEY_SHIB_SESSION_ID_FIELD = 'shibboleth:session_id_field';
+ const KEY_SHIB_APPLICATION_ID_FIELD = 'shibboleth:application_id_field';
+ const KEY_USERID_FIELD = 'shibboleth:userid_field';
+ const KEY_USERNAME_FIELD = 'shibboleth:username_field';
+ const KEY_REALNAME_FIELD = 'shibboleth:realname_field';
+ const KEY_EMAIL_FIELD = 'shibboleth:email_field';
+ const KEY_PAGE_URI_PATTERN = 'shibboleth:page_uri_pattern';
+ const KEY_IMAGE_URI_PATTERN = 'shibboleth:image_uri_pattern';
+
+ private function getPropertyKeys() {
+ return array_keys($this->getPropertyLabels());
+ }
+
+ private function getPropertyLabels() {
+ return array(
+ self::KEY_SHIB_SESSION_ID_FIELD => pht('Session ID field name'),
+ self::KEY_SHIB_APPLICATION_ID_FIELD => pht('Application ID field name'),
+ self::KEY_USERID_FIELD => pht('User ID field name'),
+ self::KEY_USERNAME_FIELD => pht('Username field name'),
+ self::KEY_REALNAME_FIELD => pht('Real name field name'),
+ self::KEY_EMAIL_FIELD => pht('User email field name'),
+ self::KEY_PAGE_URI_PATTERN => pht('User page URI pattern'),
+ self::KEY_IMAGE_URI_PATTERN => pht('User image URI pattern'),
+ );
+ }
+
+ public function readFormValuesFromProvider() {
+ $properties = array();
+ foreach ($this->getPropertyLabels() as $key => $ignored) {
+ $properties[$key] = $this->getProviderConfig()->getProperty($key);
+ }
+ return $properties;
+ }
+
+ public function readFormValuesFromRequest(AphrontRequest $request) {
+ $values = array();
+ foreach ($this->getPropertyKeys() as $key) {
+ $values[$key] = $request->getStr($key);
+ }
+
+ return $values;
+ }
+
+ public function processEditForm(
+ AphrontRequest $request,
+ array $values) {
+ $errors = array();
+ $issues = array();
+ return array($errors, $issues, $values);
+ }
+
+ public function extendEditForm(
+ AphrontRequest $request,
+ AphrontFormView $form,
+ array $values,
+ array $issues) {
+
+ $labels = $this->getPropertyLabels();
+
+ $captions = array(
+ self::KEY_SHIB_SESSION_ID_FIELD => pht('Session ID field name'),
+ self::KEY_SHIB_APPLICATION_ID_FIELD => pht('Application ID field name'),
+ self::KEY_USERID_FIELD => pht('User ID field name'),
+ self::KEY_USERNAME_FIELD => pht('Username field name'),
+ self::KEY_REALNAME_FIELD => pht('Real name field name'),
+ self::KEY_EMAIL_FIELD => pht('User email field name'),
+ self::KEY_PAGE_URI_PATTERN => pht('User page URI pattern'),
+ self::KEY_IMAGE_URI_PATTERN => pht('User image URI pattern'),
+ );
+
+ foreach ($labels as $key => $label) {
+ $caption = idx($captions, $key);
+ $value = idx($values, $key);
+
+ $control = null;
+ $control = id(new AphrontFormTextControl())
+ ->setName($key)
+ ->setLabel($label)
+ ->setCaption($caption)
+ ->setValue($value);
+
+ $form->appendChild($control);
+ }
+ }
+
+ public function renderConfigPropertyTransactionTitle(
+ PhabricatorAuthProviderConfigTransaction $xaction) {
+
+ $author_phid = $xaction->getAuthorPHID();
+ $old = $xaction->getOldValue();
+ $new = $xaction->getNewValue();
+ $key = $xaction->getMetadataValue(
+ PhabricatorAuthProviderConfigTransaction::PROPERTY_KEY);
+
+ $labels = $this->getPropertyLabels();
+ if (isset($labels[$key])) {
+ $label = $labels[$key];
+
+ if (!strlen($old)) {
+ return pht(
+ '%s set the "%s" value to "%s".',
+ $xaction->renderHandleLink($author_phid),
+ $label,
+ $new);
+ } else {
+ return pht(
+ '%s changed the "%s" value from "%s" to "%s".',
+ $xaction->renderHandleLink($author_phid),
+ $label,
+ $old,
+ $new);
+ }
+ }
+
+ return parent::renderConfigPropertyTransactionTitle($xaction);
+ }
+
+ public static function getShibbolethProvider() {
+ $providers = self::getAllEnabledProviders();
+
+ foreach ($providers as $provider) {
+ if ($provider instanceof PhabricatorAuthProviderShibboleth) {
+ return $provider;
+ }
+ }
+
+ return null;
+ }
+
+}

File Metadata

Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/hc/ct/gtl33dohczec5j7d
Default Alt Text
D7525.diff (9 KB)

Event Timeline