Skip to content

Commit

Permalink
feat: IdP Post
Browse files Browse the repository at this point in the history
  • Loading branch information
hweihwang committed Jun 28, 2024
1 parent 1a18095 commit ad1a2da
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
41 changes: 34 additions & 7 deletions lib/Controller/SAMLController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace OCA\User_SAML\Controller;

use Exception;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use OC\Core\Controller\ClientFlowLoginController;
Expand Down Expand Up @@ -177,9 +178,9 @@ protected function assertGroupMemberships(): void {
* @OnlyUnauthenticatedUsers
* @NoCSRFRequired
*
* @throws \Exception
* @throws Exception
*/
public function login(int $idp = 1): Http\RedirectResponse {
public function login(int $idp = 1) {
$originalUrl = (string)$this->request->getParam('originalUrl', '');
if (!$this->trustedDomainHelper->isTrustedUrl($originalUrl)) {
$originalUrl = '';
Expand All @@ -192,6 +193,31 @@ public function login(int $idp = 1): Http\RedirectResponse {

$returnUrl = $originalUrl ?: $this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.login');
$ssoUrl = $auth->login($returnUrl, [], false, false, true);

$method = $this->request->getParam('method', 'get');
if ($method === 'post') {
$query = parse_url($ssoUrl, PHP_URL_QUERY);
parse_str($query, $params);
$samlRequest = $params['SAMLRequest'];
$relayState = $params['RelayState'] ?? '';
$sigAlg = $params['SigAlg'] ?? '';
$signature = $params['Signature'] ?? '';

$nonce = base64_encode(random_bytes(16));
$ssoUrl = explode('?', $ssoUrl)[0];

$response = new Http\TemplateResponse($this->appName, 'login_post', [
'ssoUrl' => $ssoUrl,
'samlRequest' => $samlRequest,
'relayState' => $relayState,
'sigAlg' => $sigAlg,
'signature' => $signature,
'nonce' => $nonce,
], 'guest');
$response->addHeader('Content-Security-Policy', "script-src 'self' 'nonce-$nonce' 'strict-dynamic' 'unsafe-eval';");
return $response;
}

$response = new Http\RedirectResponse($ssoUrl);

// Small hack to make user_saml work with the loginflows
Expand Down Expand Up @@ -257,7 +283,7 @@ public function login(int $idp = 1): Http\RedirectResponse {
}
break;
default:
throw new \Exception(
throw new Exception(
sprintf(
'Type of "%s" is not supported for user_saml',
$type
Expand Down Expand Up @@ -314,7 +340,7 @@ public function assertionConsumerService(): Http\RedirectResponse {
// Decrypt and deserialize
try {
$cookie = $this->crypto->decrypt($cookie);
} catch (\Exception) {
} catch (Exception) {
$this->logger->debug('Could not decrypt SAML cookie', ['app' => 'user_saml']);
return new Http\RedirectResponse($this->urlGenerator->getAbsoluteURL('/'));
}
Expand Down Expand Up @@ -394,7 +420,7 @@ public function assertionConsumerService(): Http\RedirectResponse {
}
} catch (NoUserFoundException) {
throw new \InvalidArgumentException('User "' . $this->userBackend->getCurrentUserId() . '" is not valid');
} catch (\Exception $e) {
} catch (Exception $e) {
$this->logger->critical($e->getMessage(), ['exception' => $e, 'app' => $this->appName]);
$response = new Http\RedirectResponse($this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned'));
$response->invalidateCookie('saml_data');
Expand Down Expand Up @@ -450,7 +476,7 @@ public function singleLogoutService(): Http\RedirectResponse {

$idp = $decoded['idp'] ?? null;
$pass = true;
} catch (\Exception) {
} catch (Exception) {
}
} else {
// standard request : need read CRSF check
Expand Down Expand Up @@ -617,7 +643,8 @@ private function getSSOUrl(string $redirectUrl, string $idp): string {
[
'requesttoken' => $csrfToken->getEncryptedValue(),
'originalUrl' => $originalUrl,
'idp' => $idp
'idp' => $idp,
'method' => 'post',
]
);

Expand Down
15 changes: 15 additions & 0 deletions templates/login_post.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<form action="<?= $_['ssoUrl'] ?>" method="post">
<input type="hidden" name="SAMLRequest" value="<?= $_['samlRequest'] ?>" />
<input type="hidden" name="RelayState" value="<?=$_['relayState'] ?>" />
<input type="hidden" name="SigAlg" value="<?= $_['sigAlg'] ?>" />
<input type="hidden" name="Signature" value="<?= $_['signature'] ?>" />
<noscript>
<p>JavaScript is disabled. Click the button below to continue.</p>
<input type="submit" value="Continue" />
</noscript>
</form>
<script nonce="<?= $_['nonce'] ?>">
document.addEventListener('DOMContentLoaded', function() {
document.forms[0].submit()
})
</script>

0 comments on commit ad1a2da

Please sign in to comment.