I am trying to implement the Sign In with LinkedIn using OpenID API on my website (built under Wordpress). So I am trying to get member profile informations for scope: openid, email, profile (this is the scope I have access to in my Linkedin app).
So far, I managed to get an access token and the necessary scope. This is the information I exchange with LinkedIn, after sending the request:
array(5) {
["access_token"]=>
string(350) "[...]"
["expires_in"]=>
int(5183999)
["scope"]=>
string(20) "email,openid,profile"
["token_type"]=>
string(6) "Bearer"
["id_token"]=>
string(1391) "[...]"
However, at the end, I get the following answer:
array(3) {
["serviceErrorCode"]=>
int(100)
["message"]=>
string(41) "Not enough permissions to access: GET /me"
["status"]=>
int(403)
}
Any idea on how to handle that?
Thanks for your attention, Marc
What I tried is the following (sorry it is the full code, a bit long):
function linkedin_login_button_shortcode() {
// LinkedIn App credentials
$client_id = '[...]';
$client_secret = '[...]';
$redirect_uri = '[...]';
// Generate and store a unique state parameter
$state = bin2hex(random_bytes(16));
$_SESSION['linkedin_state'] = $state; // Store it in the session
// LinkedIn scopes
$scopes = 'openid email profile';
// Check if the authorization code is present in the URL
if (isset($_GET['code'])) {
// Authorization code is present, proceed with token exchange
$authorization_code = sanitize_text_field($_GET['code']);
// Verify the state parameter to prevent CSRF attacks
$state = sanitize_text_field($_GET['state']);
// Verify $state against the stored state value from the initial request
if ($state !== $_SESSION['linkedin_state']) {
// Invalid state, log the error to the browser console
echo '<script>console.error("Invalid state parameter: ' . $state . '");</script>';
exit;
}
// Log the authorization code to the browser console
echo '<script>console.log("Authorization code received: ' . $authorization_code . '"); </script>';
// LinkedIn token exchange endpoint
$token_url = 'https://www.linkedin.com/oauth/v2/accessToken';
// Prepare token exchange request
$token_params = array(
'grant_type' => 'authorization_code',
'code' => $authorization_code,
'redirect_uri' => $redirect_uri,
'client_id' => $client_id,
'client_secret' => $client_secret,
);
// Perform a POST request to exchange the authorization code for tokens
$response = wp_remote_post($token_url, array('body' => $token_params));
$body = wp_remote_retrieve_body($response);
$tokens = json_decode($body, true);
// Check if tokens were successfully obtained
if (isset($tokens['access_token']) && isset($tokens['id_token'])) {
// Tokens obtained, now decode the ID token
$id_token = $tokens['id_token'];
$decoded_id_token = jwt_decode($id_token);
// Extract user information
$linkedin_user_id = $decoded_id_token->sub;
$first_name = $decoded_id_token->given_name;
$last_name = $decoded_id_token->family_name;
$email = $decoded_id_token->email;
// Now, you can use the user information as needed (e.g., create or log in the user)
// ...
// Redirect the user to a desired page (e.g., home page) after successful login
wp_redirect(home_url('/'));
exit;
} else {
// Handle the case where tokens were not obtained successfully
echo 'Error obtaining tokens from LinkedIn.';
}
}
// LinkedIn authorization URL
$linkedin_login_url = 'https://www.linkedin.com/oauth/v2/authorization' .
'?response_type=code' .
'&client_id=' . $client_id .
'&redirect_uri=' . $redirect_uri .
'&state=' . $state .
'&scope=' . $scopes;
// HTML/PHP code for the button
$button_html = '<a href="' . esc_url($linkedin_login_url) . '">
<button>Login with LinkedIn</button>
</a>';
return $button_html;
}
// Register the shortcode
add_shortcode('linkedin_login_button', 'linkedin_login_button_shortcode');
function exchange_linkedin_code_for_tokens($authorization_code) {
// LinkedIn App credentials
$client_id = '[...]';
$client_secret = '[...]';
$redirect_uri = '[...]';
// LinkedIn token exchange endpoint
$token_url = 'https://www.linkedin.com/oauth/v2/accessToken';
// Prepare token exchange request
$token_params = array(
'grant_type' => 'authorization_code',
'code' => $authorization_code,
'redirect_uri' => $redirect_uri,
'client_id' => $client_id,
'client_secret' => $client_secret,
);
// Perform a POST request to exchange the authorization code for tokens
$response = wp_remote_post($token_url, array('body' => $token_params));
$body = wp_remote_retrieve_body($response);
// Check if the request was successful
if (is_wp_error($response)) {
// Handle the error (log it, display a message, etc.)
return false;
}
// Decode the response body
$tokens = json_decode($body, true);
return $tokens;
}
function get_linkedin_profile($access_token) {
// LinkedIn profile endpoint
$profile_url = 'https://api.linkedin.com/v2/me';
// Prepare the request headers
$headers = array(
'Authorization' => 'Bearer ' . $access_token,
'Connection' => 'Keep-Alive',
);
// Perform a GET request to retrieve the LinkedIn profile
$response = wp_remote_get($profile_url, array('headers' => $headers));
$body = wp_remote_retrieve_body($response);
// Check if the request was successful
if (is_wp_error($response)) {
// Handle the error (log it, display a message, etc.)
return false;
}
// Decode the response body
$profile_data = json_decode($body, true);
return $profile_data;
}
function get_user_by_linkedin_id($linkedin_user_id) {
// Check if a user with the given LinkedIn ID exists
$user_query = new WP_User_Query(array(
'meta_key' => 'linkedin_user_id',
'meta_value' => $linkedin_user_id,
'number' => 1, // Limit the query to 1 result
));
$users = $user_query->get_results();
if ($users) {
// Return the first user found (you might need to handle multiple matches differently)
return $users[0]->ID;
}
// No user found with the given LinkedIn ID
return false;
}
function create_user_from_linkedin_profile($linkedin_profile) {
// Extract relevant information from the LinkedIn profile
$linkedin_user_id = $linkedin_profile['id'];
$linkedin_email = $linkedin_profile['email'];
$first_name = $linkedin_profile['first_name'];
$last_name = $linkedin_profile['last_name'];
// Generate a unique username based on LinkedIn user ID
$username = 'linkedin_user_' . $linkedin_user_id;
// Create a new user
$user_id = wp_create_user($username, wp_generate_password(), $linkedin_email);
if (!is_wp_error($user_id)) {
// Update user meta with additional LinkedIn information
update_user_meta($user_id, 'linkedin_user_id', $linkedin_user_id);
update_user_meta($user_id, 'first_name', $first_name);
update_user_meta($user_id, 'last_name', $last_name);
// You can add more fields or customize this based on your needs
return $user_id;
} else {
// Handle the error (you might want to log it or display a message to the user)
return false;
}
}
// Hook into the user registration process after LinkedIn login
add_action('linkedin_login_after_register', 'store_linkedin_profile_info', 10, 2);
function store_linkedin_profile_info($user_id, $linkedin_user_info) {
// Store LinkedIn profile picture URL in user meta
update_user_meta($user_id, 'linkedin_profile_picture', $linkedin_user_info['profile_picture']);
}
// Check if the user is logged in
if (is_user_logged_in()) {
// Retrieve stored LinkedIn profile information
$linkedin_profile_picture = get_user_meta(get_current_user_id(), 'linkedin_profile_picture', true);
// Check if the profile picture URL is available
if ($linkedin_profile_picture) {
echo '<div class="linkedin-profile-picture">';
echo '<img src="' . esc_url($linkedin_profile_picture) . '" alt="LinkedIn Profile Picture">';
echo '</div>';
}
}
// Check if the user clicked "Sign in with LinkedIn"
if (isset($_GET['linkedin_login'])) {
// Initiate LinkedIn OAuth flow
$linkedin_oauth_url = get_linkedin_oauth_url();
wp_redirect($linkedin_oauth_url);
exit;
}
// Check if the LinkedIn callback is being processed
if (isset($_GET['code'])) {
// Exchange the authorization code for access tokens
$linkedin_tokens = exchange_linkedin_code_for_tokens($_GET['code']);
echo '<pre>';
var_dump($linkedin_tokens);
echo '</pre>';
// Retrieve LinkedIn profile information
$linkedin_profile = get_linkedin_profile($linkedin_tokens['access_token']);
// Display LinkedIn profile information for debugging
echo '<pre>';
var_dump($linkedin_profile);
echo '</pre>';
// Check if the user exists
$user_id = get_user_by_linkedin_id($linkedin_profile['id']);
if (!$user_id) {
// User doesn't exist, create a new account
$user_id = create_user_from_linkedin_profile($linkedin_profile);
}
// Log the user in and update the session
wp_set_auth_cookie($user_id, true);
do_action('wp_login', get_user_by('id', $user_id)->user_login);
// Redirect the user to the desired page (e.g., homepage)
wp_redirect(home_url('/'));
exit;
}