More flexible identity settings.

isekai
Moriyoshi Koizumi 8 years ago
parent e723799397
commit 0bbfc3437f

@ -367,6 +367,9 @@ class OpenID_Connect_Generic_Client_Wrapper {
// if we didn't find an existing user, we'll need to create it
if ( ! $user ) {
$user = $this->create_new_user( $subject_identity, $user_claim );
if ( is_wp_error( $user ) ) {
return $this->error_redirect( $user );
}
}
else {
// allow plugins / themes to take action using current claims on existing user (e.g. update role)
@ -579,7 +582,81 @@ class OpenID_Connect_Generic_Client_Wrapper {
return $username;
}
/**
* Get a nickname
*
* @param $user_claim array
*
* @return string
*/
private function get_nickname_from_claim( $user_claim ) {
$desired_nickname = null;
// allow settings to take first stab at nickname
if ( !empty( $this->settings->nickname_key ) && isset( $user_claim[ $this->settings->nickname_key ] ) ) {
$desired_nickname = $user_claim[ $this->settings->nickname_key ];
}
return $desired_nickname;
}
/**
* Build a string from the user claim according to the specified format.
*
* @param $format string
* @param $user_claim array
*
* @return string
*/
private function format_string_with_claim( $format, $user_claim, $error_on_missing_key = false ) {
$matches = null;
$string = '';
$i = 0;
if ( preg_match_all( '/\{[^}]*\}/u', $format, $matches, PREG_OFFSET_CAPTURE ) ) {
foreach ( $matches[ 0 ] as $match ) {
$key = substr($match[ 0 ], 1, -1);
$string .= substr( $format, $i, $match[ 1 ] - $i );
if ( ! isset( $user_claim[ $key ] ) ) {
if ( $error_on_missing_key ) {
return new WP_Error( 'incomplete-user-claim', __( 'User claim incomplete' ), $user_claim );
}
} else {
$string .= $user_claim[ $key ];
}
$i = $match[ 1 ] + strlen( $match[ 0 ] );
}
}
$string .= substr( $format, $i );
return $string;
}
/**
* Get a displayname
*
* @param $user_claim array
*
* @return string
*/
private function get_displayname_from_claim( $user_claim, $error_on_missing_key = false ) {
if ( ! empty( $this->settings->displayname_format ) ) {
return $this->format_string_with_claim( $this->settings->displayname_format, $user_claim, $error_on_missing_key );
}
return null;
}
/**
* Get an email
*
* @param $user_claim array
*
* @return string
*/
private function get_email_from_claim( $user_claim, $error_on_missing_key = false ) {
if ( ! empty( $this->settings->email_format ) ) {
return $this->format_string_with_claim( $this->settings->email_format, $user_claim, $error_on_missing_key );
}
return null;
}
/**
* Create a new user from details in a user_claim
*
@ -588,22 +665,46 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return \WP_Error | \WP_User
*/
function create_new_user( $subject_identity, $user_claim){
function create_new_user( $subject_identity, $user_claim ) {
// default username & email to the subject identity
$username = $subject_identity;
$email = $subject_identity;
$nickname = $subject_identity;
$displayname = $subject_identity;
// allow claim details to determine username
if ( isset( $user_claim['email'] ) ) {
$email = $user_claim['email'];
$username = $this->get_username_from_claim( $user_claim );
if ( is_wp_error( $username ) ){
return $username;
}
$values_missing = false;
// allow claim details to determine username, email, nickname and displayname.
$_email = $this->get_email_from_claim( $user_claim, true );
if ( is_wp_error( $_email ) ) {
$values_missing = true;
} else if ( $_email !== null ) {
$email = $_email;
}
$_username = $this->get_username_from_claim( $user_claim );
if ( is_wp_error( $_username ) ) {
$values_missing = true;
} else if ( $_username !== null ) {
$username = $_username;
}
$_nickname = $this->get_nickname_from_claim( $user_claim, true );
if ( is_wp_error( $_nickname ) ) {
$values_missing = true;
} else if ( $_nickname !== null) {
$nickname = $_nickname;
}
// if no email exists, attempt another request for userinfo
else if ( isset( $token_response['access_token'] ) ) {
$_displayname = $this->get_displayname_from_claim( $user_claim, true );
if ( is_wp_error( $_displayname ) ) {
$values_missing = true;
} else if ( $_displayname !== null ) {
$displayname = $_displayname;
}
// attempt another request for userinfo if some values are missing
if ( $values_missing && isset( $token_response['access_token'] ) ) {
$user_claim_result = $this->client->request_userinfo( $token_response['access_token'] );
// make sure we didn't get an error
@ -612,23 +713,48 @@ class OpenID_Connect_Generic_Client_Wrapper {
}
$user_claim = json_decode( $user_claim_result['body'], TRUE );
}
// check for email in claim
if ( ! isset( $user_claim['email'] ) ) {
return new WP_Error( 'incomplete-user-claim', __( 'User claim incomplete' ), $user_claim );
}
$email = $user_claim['email'];
$username = $this->get_username_from_claim( $user_claim );
$_email = $this->get_email_from_claim( $user_claim, true );
if ( is_wp_error( $_email ) ) {
return $_email;
} else if ( $_email !== null ) {
$email = $_email;
}
$_username = $this->get_username_from_claim( $user_claim );
if ( is_wp_error( $_username ) ) {
return $_username;
} else if ( $_username !== null ) {
$username = $_username;
}
$_nickname = $this->get_nickname_from_claim( $user_claim, true );
if ( is_wp_error( $_nickname ) ) {
return $_nickname;
} else if ( $_nickname === null) {
$nickname = $username;
}
$_displayname = $this->get_displayname_from_claim( $user_claim, true );
if ( is_wp_error( $_displayname ) ) {
return $_displayname;
} else if ( $_displayname === null ) {
$displayname = $nickname;
}
// before trying to create the user, first check if a user with the same email already exists
if( $this->settings->link_existing_users ) {
if( $uid = email_exists( $email ) ) {
if ( $this->settings->identify_with_username) {
$uid = username_exists( $username );
} else {
$uid = email_exists( $email );
}
if ( $uid ) {
return $this->update_existing_user( $uid, $subject_identity );
}
}
// allow other plugins / themes to determine authorization
// of new accounts based on the returned user claim
$create_user = apply_filters( 'openid-connect-generic-user-creation-test', TRUE, $user_claim );
@ -638,7 +764,17 @@ class OpenID_Connect_Generic_Client_Wrapper {
}
// create the new user
$uid = wp_create_user( $username, wp_generate_password( 32, TRUE, TRUE ), $email );
$uid = wp_insert_user(
array(
'user_login' => $username,
'user_pass' => wp_generate_password( 32, TRUE, TRUE ),
'user_email' => $email,
'display_name' => $displayname,
'nickname' => $nickname,
'first_name' => isset( $user_claim[ 'given_name' ] ) ? $user_claim[ 'given_name' ]: '',
'last_name' => isset( $user_claim[ 'family_name' ] ) ? $user_claim[ 'family_name' ]: '',
)
);
// make sure we didn't fail in creating the user
if ( is_wp_error( $uid ) ) {

@ -124,9 +124,36 @@ class OpenID_Connect_Generic_Settings_Page {
'type' => 'checkbox',
'section' => 'authorization_settings',
),
'nickname_key' => array(
'title' => __( 'Nickname Key' ),
'description' => __( 'Where in the user claim array to find the user\'s nickname. Possible standard values: preferred_username, name, or sub.' ),
'example' => 'preferred_username',
'type' => 'text',
'section' => 'client_settings',
),
'email_format' => array(
'title' => __( 'Email Formatting' ),
'description' => __( 'String from which the user\'s email address is built. Specify "{email}" as long as the user claim contains an email claim.' ),
'example' => '{email}',
'type' => 'text',
'section' => 'client_settings',
),
'displayname_format' => array(
'title' => __( 'Display Name Formatting' ),
'description' => __( 'String from which the user\'s display name is built.' ),
'example' => '{given_name} {family_name}',
'type' => 'text',
'section' => 'client_settings',
),
'identify_with_username' => array(
'title' => __( 'Identify with User Name' ),
'description' => __( 'If checked, the user\' identity will be determined by the user name instead of the email address.' ),
'type' => 'checkbox',
'section' => 'client_settings',
),
'link_existing_users' => array(
'title' => __( 'Link Existing Users' ),
'description' => __( 'If a WordPress account already exists with the same email address as a newly-authenticated user over OpenID Connect, login as that user instead of generating an error.' ),
'description' => __( 'If a WordPress account already exists with the same identity as a newly-authenticated user over OpenID Connect, login as that user instead of generating an error.' ),
'type' => 'checkbox',
'section' => 'user_settings',
),

@ -196,7 +196,11 @@ class OpenID_Connect_Generic {
'no_sslverify' => 0,
'http_request_timeout' => 5,
'identity_key' => 'preferred_username',
'nickname_key' => 'preferred_username',
'email_format' => '{email}',
'displayname_format' => '',
'identify_with_username' => false,
// plugin settings
'enforce_privacy' => 0,
'alternate_redirect_uri' => 0,

Loading…
Cancel
Save