LinkedIn: default to the scopes Community Management API grants
The approved app has no OpenID Connect product, so openid/profile/r_organization_admin would fail. Use r_basicprofile + rw_organization_admin and read the member from /v2/me. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3aff447011
commit
1307146921
@ -54,24 +54,28 @@ export default {
|
|||||||
console: "https://www.linkedin.com/developers/apps",
|
console: "https://www.linkedin.com/developers/apps",
|
||||||
steps: [
|
steps: [
|
||||||
"Create an app at linkedin.com/developers/apps and link it to your company's LinkedIn Page (the Page admin must verify it).",
|
"Create an app at linkedin.com/developers/apps and link it to your company's LinkedIn Page (the Page admin must verify it).",
|
||||||
"Products tab: add “Sign In with LinkedIn using OpenID Connect” and “Share on LinkedIn” (instant).",
|
"Products tab: request “Community Management API” for posting to clients' company Pages (LinkedIn reviews it; your company Page must be verified).",
|
||||||
"For posting to clients' company Pages, also request “Community Management API” (LinkedIn reviews it; your company Page must be verified).",
|
|
||||||
"Auth tab: add the Redirect URL shown below, then copy the Client ID and Client Secret here.",
|
"Auth tab: add the Redirect URL shown below, then copy the Client ID and Client Secret here.",
|
||||||
],
|
],
|
||||||
note: "Until Community Management API is approved, set Scopes to “openid profile w_member_social” so you can post to personal profiles only.",
|
note: "Without Community Management API (personal profiles only): add “Sign In with LinkedIn using OpenID Connect” and “Share on LinkedIn”, and set Scopes to “openid profile w_member_social”.",
|
||||||
},
|
},
|
||||||
auth: {
|
auth: {
|
||||||
authorizeUrl: "https://www.linkedin.com/oauth/v2/authorization",
|
authorizeUrl: "https://www.linkedin.com/oauth/v2/authorization",
|
||||||
tokenUrl: "https://www.linkedin.com/oauth/v2/accessToken",
|
tokenUrl: "https://www.linkedin.com/oauth/v2/accessToken",
|
||||||
scopes: ["openid", "profile", "w_member_social", "r_organization_admin", "w_organization_social", "r_organization_social"],
|
// The scopes Community Management API grants (it can't be combined with the OpenID Connect product).
|
||||||
|
scopes: ["r_basicprofile", "w_member_social", "rw_organization_admin", "w_organization_social", "r_organization_social"],
|
||||||
},
|
},
|
||||||
formats: { TEXT: true, IMAGE: true, CAROUSEL: true, REELS: true },
|
formats: { TEXT: true, IMAGE: true, CAROUSEL: true, REELS: true },
|
||||||
limits: { caption: 3000, images: 20 },
|
limits: { caption: 3000, images: 20 },
|
||||||
targetLabel: "Post as",
|
targetLabel: "Post as",
|
||||||
|
|
||||||
async identify(tokens) {
|
async identify(tokens) {
|
||||||
|
if (/\bopenid\b/.test(tokens.scope || "")) {
|
||||||
const { data } = await request("LinkedIn", `${API}/v2/userinfo`, { token: tokens.accessToken });
|
const { data } = await request("LinkedIn", `${API}/v2/userinfo`, { token: tokens.accessToken });
|
||||||
return { id: data.sub, name: data.name, username: null, avatar: data.picture || null, url: null };
|
return { id: data.sub, name: data.name, username: null, avatar: data.picture || null, url: null };
|
||||||
|
}
|
||||||
|
const { data } = await request("LinkedIn", `${API}/v2/me`, { token: tokens.accessToken });
|
||||||
|
return { id: data.id, name: [data.localizedFirstName, data.localizedLastName].filter(Boolean).join(" ") || "LinkedIn member", username: null, avatar: null, url: null };
|
||||||
},
|
},
|
||||||
|
|
||||||
/** The person, plus every company Page they administer (needs Community Management API). */
|
/** The person, plus every company Page they administer (needs Community Management API). */
|
||||||
|
|||||||
@ -139,7 +139,7 @@ test("sign-in URLs carry the right client id, scopes and PKCE per platform", ()
|
|||||||
test("LinkedIn: connect, list company Pages, post image to a company Page", async () => {
|
test("LinkedIn: connect, list company Pages, post image to a company Page", async () => {
|
||||||
reset();
|
reset();
|
||||||
const { conn } = await connect("linkedin", "acme", { identify: [
|
const { conn } = await connect("linkedin", "acme", { identify: [
|
||||||
["GET", "https://api.linkedin.com/v2/userinfo", json({ sub: "abc", name: "Pat Lee", picture: "https://p" })],
|
["GET", "https://api.linkedin.com/v2/me", json({ id: "abc", localizedFirstName: "Pat", localizedLastName: "Lee" })],
|
||||||
["GET", "https://api.linkedin.com/rest/organizationAcls", json({ elements: [{ organization: "urn:li:organization:42" }] })],
|
["GET", "https://api.linkedin.com/rest/organizationAcls", json({ elements: [{ organization: "urn:li:organization:42" }] })],
|
||||||
["GET", "https://api.linkedin.com/rest/organizations/42", json({ localizedName: "Acme Co" })],
|
["GET", "https://api.linkedin.com/rest/organizations/42", json({ localizedName: "Acme Co" })],
|
||||||
] });
|
] });
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user