@ -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 we didn't find an existing user, we'll need to create it
if ( ! $user ) {
if ( ! $user ) {
$user = $this->create_new_user( $subject_identity, $user_claim );
$user = $this->create_new_user( $subject_identity, $user_claim );
if ( is_wp_error( $user ) ) {
return $this->error_redirect( $user );
}
}
}
else {
else {
// allow plugins / themes to take action using current claims on existing user (e.g. update role)
// 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;
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
* 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
* @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
// default username & email to the subject identity
$username = $subject_identity;
$username = $subject_identity;
$email = $subject_identity;
$email = $subject_identity;
$nickname = $subject_identity;
$displayname = $subject_identity;
// allow claim details to determine username
$values_missing = false;
if ( isset( $user_claim['email'] ) ) {
$email = $user_claim['email'];
// allow claim details to determine username, email, nickname and displayname.
$username = $this->get_username_from_claim( $user_claim );
$_email = $this->get_email_from_claim( $user_claim, true );
if ( is_wp_error( $_email ) ) {
if ( is_wp_error( $username ) ){
$values_missing = true;
return $username;
} 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'] );
$user_claim_result = $this->client->request_userinfo( $token_response['access_token'] );
// make sure we didn't get an error
// 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 );
$user_claim = json_decode( $user_claim_result['body'], TRUE );
}
// check for email in claim
$_email = $this->get_email_from_claim( $user_claim, true );
if ( ! isset( $user_claim['email'] ) ) {
if ( is_wp_error( $_email ) ) {
return new WP_Error( 'incomplete-user-claim', __( 'User claim incomplete' ), $user_claim );
return $_email;
}
} else if ( $_email !== null ) {
$email = $_email;
$email = $user_claim['email'];
}
$username = $this->get_username_from_claim( $user_claim );
$_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
// before trying to create the user, first check if a user with the same email already exists
if( $this->settings->link_existing_users ) {
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 );
return $this->update_existing_user( $uid, $subject_identity );
}
}
}
}
// allow other plugins / themes to determine authorization
// allow other plugins / themes to determine authorization
// of new accounts based on the returned user claim
// of new accounts based on the returned user claim
$create_user = apply_filters( 'openid-connect-generic-user-creation-test', TRUE, $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
// 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
// make sure we didn't fail in creating the user
if ( is_wp_error( $uid ) ) {
if ( is_wp_error( $uid ) ) {