Skip to content

Commit 5e981d0

Browse files
csharpfritzCopilot
andcommitted
fix: remove openid/profile scopes and use /v2/me for member URN
LinkedIn OAuth was failing because openid and profile scopes require the 'Sign In with LinkedIn' product. Community Management API only provides r_member_social and w_member_social. Also switch ResolveMemberUrn from /v2/userinfo (OpenID) to /v2/me (LinkedIn REST API) which works with r_member_social scope. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2808389 commit 5e981d0

File tree

2 files changed

+9
-7
lines changed

2 files changed

+9
-7
lines changed

src/TagzApp.Blazor/Service_LinkedInOAuth.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public static class Service_LinkedInOAuth
1414
private const string LinkedInTokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken";
1515

1616
// Required scopes: r_member_social reads posts (needs Community Management API product)
17-
private static readonly string[] RequiredScopes = ["openid", "profile", "w_member_social", "r_member_social"];
17+
private static readonly string[] RequiredScopes = ["r_member_social", "w_member_social"];
1818

1919
public static void MapLinkedInOAuthEndpoints(this WebApplication app)
2020
{

src/TagzApp.Providers.LinkedIn/LinkedInProvider.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,22 +249,24 @@ public Task StopAsync()
249249
return null;
250250
}
251251

252-
using var request = new HttpRequestMessage(HttpMethod.Get, $"{LinkedInApiBase}/v2/userinfo");
252+
using var request = new HttpRequestMessage(HttpMethod.Get, $"{LinkedInApiBase}/v2/me");
253253
request.Headers.Add("Authorization", $"Bearer {_configuration.AccessToken}");
254+
request.Headers.Add("LinkedIn-Version", "202401");
255+
request.Headers.Add("X-Restli-Protocol-Version", "2.0.0");
254256

255257
var response = await _httpClient.SendAsync(request);
256258
Interlocked.Increment(ref _dailyCallCount);
257259

258260
if (!response.IsSuccessStatusCode)
259261
{
260-
_logger.LogError("LinkedIn userinfo call failed: {StatusCode} {Reason}", (int)response.StatusCode, response.ReasonPhrase);
262+
_logger.LogError("LinkedIn me call failed: {StatusCode} {Reason}", (int)response.StatusCode, response.ReasonPhrase);
261263
return null;
262264
}
263265

264-
var userInfo = await response.Content.ReadFromJsonAsync<JsonElement>();
265-
if (userInfo.TryGetProperty("sub", out var sub))
266+
var meResponse = await response.Content.ReadFromJsonAsync<JsonElement>();
267+
if (meResponse.TryGetProperty("id", out var id))
266268
{
267-
var memberId = sub.GetString();
269+
var memberId = id.GetString();
268270
if (!string.IsNullOrEmpty(memberId))
269271
{
270272
var urn = $"urn:li:person:{memberId}";
@@ -273,7 +275,7 @@ public Task StopAsync()
273275
}
274276
}
275277

276-
_logger.LogError("LinkedIn userinfo response missing 'sub' field");
278+
_logger.LogError("LinkedIn me response missing 'id' field");
277279
return null;
278280
}
279281
catch (Exception ex)

0 commit comments

Comments
 (0)