forked from Public/pics
Match OIDC users by sub claim, auto-enroll, sync admin from groups
Switch from email-based OIDC matching to the stable `sub` claim. Existing users are migrated by email on first login, new users are auto-enrolled from OIDC claims, and admin status is synced from the IdP's groups claim. Also expose oidc_sub on the admin edit-user page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,15 @@ class Member extends User
|
||||
['email_address' => $email_address]);
|
||||
}
|
||||
|
||||
public static function fromOidcSub($sub)
|
||||
{
|
||||
return Registry::get('db')->queryObject(static::class, '
|
||||
SELECT *
|
||||
FROM users
|
||||
WHERE oidc_sub = :oidc_sub',
|
||||
['oidc_sub' => $sub]);
|
||||
}
|
||||
|
||||
public static function fromId($id_user)
|
||||
{
|
||||
$row = Registry::get('db')->queryAssoc('
|
||||
@@ -73,18 +82,27 @@ class Member extends User
|
||||
'surname' => !empty($data['surname']) ? $data['surname'] : $error |= true,
|
||||
'slug' => !empty($data['slug']) ? $data['slug'] : $error |= true,
|
||||
'emailaddress' => !empty($data['emailaddress']) ? $data['emailaddress'] : $error |= true,
|
||||
'password_hash' => !empty($data['password']) ? Authentication::computeHash($data['password']) : $error |= true,
|
||||
'creation_time' => time(),
|
||||
'ip_address' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '',
|
||||
'is_admin' => empty($data['is_admin']) ? 0 : 1,
|
||||
'reset_key' => '',
|
||||
];
|
||||
|
||||
// Password is required unless oidc_sub is provided.
|
||||
if (!empty($data['password']))
|
||||
$new_user['password_hash'] = Authentication::computeHash($data['password']);
|
||||
elseif (!empty($data['oidc_sub']))
|
||||
$new_user['password_hash'] = '';
|
||||
else
|
||||
$error |= true;
|
||||
|
||||
if (!empty($data['oidc_sub']))
|
||||
$new_user['oidc_sub'] = $data['oidc_sub'];
|
||||
|
||||
if ($error)
|
||||
return false;
|
||||
|
||||
$db = Registry::get('db');
|
||||
$bool = $db->insert('insert', 'users', [
|
||||
$columns = [
|
||||
'first_name' => 'string-30',
|
||||
'surname' => 'string-60',
|
||||
'slug' => 'string-90',
|
||||
@@ -93,8 +111,14 @@ class Member extends User
|
||||
'creation_time' => 'int',
|
||||
'ip_address' => 'string-45',
|
||||
'is_admin' => 'int',
|
||||
'reset_key' => 'string-16'
|
||||
], $new_user, ['id_user']);
|
||||
'reset_key' => 'string-16',
|
||||
];
|
||||
|
||||
if (isset($new_user['oidc_sub']))
|
||||
$columns['oidc_sub'] = 'string-255';
|
||||
|
||||
$db = Registry::get('db');
|
||||
$bool = $db->insert('insert', 'users', $columns, $new_user, ['id_user']);
|
||||
|
||||
if (!$bool)
|
||||
return false;
|
||||
@@ -113,7 +137,7 @@ class Member extends User
|
||||
{
|
||||
foreach ($new_data as $key => $value)
|
||||
{
|
||||
if (in_array($key, ['first_name', 'surname', 'slug', 'emailaddress']))
|
||||
if (in_array($key, ['first_name', 'surname', 'slug', 'emailaddress', 'oidc_sub']))
|
||||
$this->$key = $value;
|
||||
elseif ($key === 'password')
|
||||
$this->password_hash = Authentication::computeHash($value);
|
||||
@@ -132,7 +156,8 @@ class Member extends User
|
||||
slug = :slug,
|
||||
emailaddress = :emailaddress,
|
||||
password_hash = :password_hash,
|
||||
is_admin = :is_admin
|
||||
is_admin = :is_admin,
|
||||
oidc_sub = :oidc_sub
|
||||
WHERE id_user = :id_user',
|
||||
get_object_vars($this));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user