[Web] Implemented SSO for domain admins
Signed-off-by: Kristian Feldsam <feldsam@gmail.com> Revert "[Web] Implemented SSO for domain admins" This reverts commit 6860dc8ebe2c8f53d77df5bca7787f7cb3bb4ee0. Signed-off-by: Kristian Feldsam <feldsam@gmail.com>
This commit is contained in:
		@@ -699,6 +699,38 @@ paths:
 | 
				
			|||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
              type: object
 | 
					              type: object
 | 
				
			||||||
      summary: Create Domain Admin user
 | 
					      summary: Create Domain Admin user
 | 
				
			||||||
 | 
					  /api/v1/add/sso/domain-admin:
 | 
				
			||||||
 | 
					    post:
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        "401":
 | 
				
			||||||
 | 
					          $ref: "#/components/responses/Unauthorized"
 | 
				
			||||||
 | 
					        "200":
 | 
				
			||||||
 | 
					          content:
 | 
				
			||||||
 | 
					            application/json:
 | 
				
			||||||
 | 
					              examples:
 | 
				
			||||||
 | 
					                response:
 | 
				
			||||||
 | 
					                  value:
 | 
				
			||||||
 | 
					                    token: "591F6D-5C3DD2-7455CD-DAF1C1-AA4FCC"
 | 
				
			||||||
 | 
					          description: OK
 | 
				
			||||||
 | 
					          headers: { }
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Single Sign-On
 | 
				
			||||||
 | 
					      description: >-
 | 
				
			||||||
 | 
					        Using this endpoint you can issue a token for Domain Admin user. This token can be used for
 | 
				
			||||||
 | 
					        autologin Domain Admin user by using query_string var sso_token={token}. Token expiration time is 30s
 | 
				
			||||||
 | 
					      operationId: Issue Domain Admin SSO token
 | 
				
			||||||
 | 
					      requestBody:
 | 
				
			||||||
 | 
					        content:
 | 
				
			||||||
 | 
					          application/json:
 | 
				
			||||||
 | 
					            schema:
 | 
				
			||||||
 | 
					              example:
 | 
				
			||||||
 | 
					                username: testadmin
 | 
				
			||||||
 | 
					              properties:
 | 
				
			||||||
 | 
					                username:
 | 
				
			||||||
 | 
					                  description: the username for the admin user
 | 
				
			||||||
 | 
					                  type: object
 | 
				
			||||||
 | 
					              type: object
 | 
				
			||||||
 | 
					      summary: Issue Domain Admin SSO token
 | 
				
			||||||
  /api/v1/edit/da-acl:
 | 
					  /api/v1/edit/da-acl:
 | 
				
			||||||
    post:
 | 
					    post:
 | 
				
			||||||
      responses:
 | 
					      responses:
 | 
				
			||||||
@@ -5586,6 +5618,8 @@ tags:
 | 
				
			|||||||
    description: Manage DKIM keys
 | 
					    description: Manage DKIM keys
 | 
				
			||||||
  - name: Domain admin
 | 
					  - name: Domain admin
 | 
				
			||||||
    description: Create or udpdate domain admin users
 | 
					    description: Create or udpdate domain admin users
 | 
				
			||||||
 | 
					  - name: Single Sign-On
 | 
				
			||||||
 | 
					    description: Issue tokens for users
 | 
				
			||||||
  - name: Address Rewriting
 | 
					  - name: Address Rewriting
 | 
				
			||||||
    description: Create BCC maps or recipient maps
 | 
					    description: Create BCC maps or recipient maps
 | 
				
			||||||
  - name: Outgoing TLS Policy Map Overrides
 | 
					  - name: Outgoing TLS Policy Map Overrides
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -405,3 +405,64 @@ function domain_admin($_action, $_data = null) {
 | 
				
			|||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					function domain_admin_sso($_action, $_data) {
 | 
				
			||||||
 | 
					  global $pdo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  switch ($_action) {
 | 
				
			||||||
 | 
					    case 'check':
 | 
				
			||||||
 | 
					      $token = $_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $stmt = $pdo->prepare("SELECT `t1`.`username` FROM `da_sso` AS `t1` JOIN `admin` AS `t2` ON `t1`.`username` = `t2`.`username` WHERE `t1`.`token` = :token AND `t1`.`created` > DATE_SUB(NOW(), INTERVAL '30' SECOND) AND `t2`.`active` = 1 AND `t2`.`superadmin` = 0;");
 | 
				
			||||||
 | 
					      $stmt->execute(array(
 | 
				
			||||||
 | 
					        ':token' => preg_replace('/[^a-zA-Z0-9-]/', '', $token)
 | 
				
			||||||
 | 
					      ));
 | 
				
			||||||
 | 
					      $return = $stmt->fetch(PDO::FETCH_ASSOC);
 | 
				
			||||||
 | 
					      return empty($return['username']) ? false : $return['username'];
 | 
				
			||||||
 | 
					    case 'issue':
 | 
				
			||||||
 | 
					      if ($_SESSION['mailcow_cc_role'] != "admin") {
 | 
				
			||||||
 | 
					        $_SESSION['return'][] = array(
 | 
				
			||||||
 | 
					          'type' => 'danger',
 | 
				
			||||||
 | 
					          'log' => array(__FUNCTION__, $_action, $_data),
 | 
				
			||||||
 | 
					          'msg' => 'access_denied'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $username = $_data['username'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $stmt = $pdo->prepare("SELECT `username` FROM `domain_admins`
 | 
				
			||||||
 | 
					        WHERE `username` = :username");
 | 
				
			||||||
 | 
					      $stmt->execute(array(':username' => $username));
 | 
				
			||||||
 | 
					      $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if ($num_results < 1) {
 | 
				
			||||||
 | 
					        $_SESSION['return'][] = array(
 | 
				
			||||||
 | 
					          'type' => 'danger',
 | 
				
			||||||
 | 
					          'log' => array(__FUNCTION__, $_action, $_data),
 | 
				
			||||||
 | 
					          'msg' => array('object_doesnt_exist', htmlspecialchars($username))
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $token = implode('-', array(
 | 
				
			||||||
 | 
					        strtoupper(bin2hex(random_bytes(3))),
 | 
				
			||||||
 | 
					        strtoupper(bin2hex(random_bytes(3))),
 | 
				
			||||||
 | 
					        strtoupper(bin2hex(random_bytes(3))),
 | 
				
			||||||
 | 
					        strtoupper(bin2hex(random_bytes(3))),
 | 
				
			||||||
 | 
					        strtoupper(bin2hex(random_bytes(3)))
 | 
				
			||||||
 | 
					      ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $stmt = $pdo->prepare("INSERT INTO `da_sso` (`username`, `token`)
 | 
				
			||||||
 | 
					            VALUES (:username, :token)");
 | 
				
			||||||
 | 
					      $stmt->execute(array(
 | 
				
			||||||
 | 
					        ':username' => $username,
 | 
				
			||||||
 | 
					        ':token' => $token
 | 
				
			||||||
 | 
					      ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // perform cleanup
 | 
				
			||||||
 | 
					      $pdo->query("DELETE FROM `da_sso` WHERE created < DATE_SUB(NOW(), INTERVAL '30' SECOND);");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return ['token' => $token];
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ function init_db_schema() {
 | 
				
			|||||||
  try {
 | 
					  try {
 | 
				
			||||||
    global $pdo;
 | 
					    global $pdo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $db_version = "23122022_1445";
 | 
					    $db_version = "06012023_1924";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
 | 
					    $stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
 | 
				
			||||||
    $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
 | 
					    $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
 | 
				
			||||||
@@ -664,6 +664,19 @@ function init_db_schema() {
 | 
				
			|||||||
        ),
 | 
					        ),
 | 
				
			||||||
        "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
 | 
					        "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 | 
					      "da_sso" => array(
 | 
				
			||||||
 | 
					        "cols" => array(
 | 
				
			||||||
 | 
					          "username" => "VARCHAR(255) NOT NULL",
 | 
				
			||||||
 | 
					          "token" => "VARCHAR(255) NOT NULL",
 | 
				
			||||||
 | 
					          "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        "keys" => array(
 | 
				
			||||||
 | 
					          "primary" => array(
 | 
				
			||||||
 | 
					            "" => array("token", "created")
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
      "imapsync" => array(
 | 
					      "imapsync" => array(
 | 
				
			||||||
        "cols" => array(
 | 
					        "cols" => array(
 | 
				
			||||||
          "id" => "INT NOT NULL AUTO_INCREMENT",
 | 
					          "id" => "INT NOT NULL AUTO_INCREMENT",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,15 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					// SSO Domain Admin
 | 
				
			||||||
 | 
					if (!empty($_GET['sso_token'])) {
 | 
				
			||||||
 | 
					  $username = domain_admin_sso('check', $_GET['sso_token']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($username !== false) {
 | 
				
			||||||
 | 
					    $_SESSION['mailcow_cc_username'] = $username;
 | 
				
			||||||
 | 
					    $_SESSION['mailcow_cc_role'] = 'domainadmin';
 | 
				
			||||||
 | 
					    header('Location: /mailbox');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (isset($_POST["verify_tfa_login"])) {
 | 
					if (isset($_POST["verify_tfa_login"])) {
 | 
				
			||||||
  if (verify_tfa_login($_SESSION['pending_mailcow_cc_username'], $_POST)) {
 | 
					  if (verify_tfa_login($_SESSION['pending_mailcow_cc_username'], $_POST)) {
 | 
				
			||||||
    $_SESSION['mailcow_cc_username'] = $_SESSION['pending_mailcow_cc_username'];
 | 
					    $_SESSION['mailcow_cc_username'] = $_SESSION['pending_mailcow_cc_username'];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -288,6 +288,18 @@ if (isset($_GET['query'])) {
 | 
				
			|||||||
        case "domain-admin":
 | 
					        case "domain-admin":
 | 
				
			||||||
          process_add_return(domain_admin('add', $attr));
 | 
					          process_add_return(domain_admin('add', $attr));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					        case "sso":
 | 
				
			||||||
 | 
					          switch ($object) {
 | 
				
			||||||
 | 
					            case "domain-admin":
 | 
				
			||||||
 | 
					              $data = domain_admin_sso('issue', $attr);
 | 
				
			||||||
 | 
					              if($data) {
 | 
				
			||||||
 | 
					                echo json_encode($data);
 | 
				
			||||||
 | 
					                exit(0);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              process_add_return($data);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
        case "admin":
 | 
					        case "admin":
 | 
				
			||||||
          process_add_return(admin('add', $attr));
 | 
					          process_add_return(admin('add', $attr));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user