Documentation

SSO

LinkedIn

Add Sign In with LinkedIn using OpenID Connect to VitNode. Add the product to a LinkedIn app, register the redirect URL and wire up the adapter.

Add a Continue with LinkedIn button using LinkedIn's current OpenID Connect product. The adapter asks for openid profile email and reads the member from LinkedIn's UserInfo endpoint.

Before you begin

Set up the app

Create an app

In the LinkedIn Developer Portal, press Create app, enter the name and logo people will see, choose your LinkedIn Page and add your privacy policy URL.

Add the OpenID Connect product

Open the Products tab and request Sign In with LinkedIn using OpenID Connect. It is self-serve and is approved immediately. Without it, LinkedIn rejects the openid, profile and email scopes.

Add the redirect URL

On the Auth tab, under OAuth 2.0 settings, add each redirect URL:

EnvironmentRedirect URL
Development (VITNODE_WEB_URL unset)http://localhost:3000/login/sso/linkedin
Productionhttps://your-domain.com/login/sso/linkedin

VitNode builds it from VITNODE_WEB_URL, so it must match exactly. LinkedIn's documentation asks for HTTPS redirect URLs and does not say whether http://localhost is accepted; if the portal refuses it, test through an HTTPS tunnel as described in Callback URLs.

Copy the credentials

The Client ID and Primary Client Secret are at the top of the Auth tab. Keep them server-side:

.env
LINKEDIN_CLIENT_ID=77abcdefghijkl
LINKEDIN_CLIENT_SECRET=xxxxxxxxxxxxxxxx

Add the adapter

Add LinkedInSSOApiPlugin to authorization.ssoAdapters in the API's vitnode.api.config.ts (where it lives), next to any adapters you already have. Keep the rest of the config as it is:

src/vitnode.api.config.ts (excerpt)
import { LinkedInSSOApiPlugin } from '@vitnode/core/api/adapters/sso/linkedin'
import { buildApiConfig } from '@vitnode/core/vitnode.config'

export const vitNodeApiConfig = buildApiConfig({
  // ...
  authorization: {
    ssoAdapters: [
      // ...
      LinkedInSSOApiPlugin({
        clientId: process.env.LINKEDIN_CLIENT_ID,
        clientSecret: process.env.LINKEDIN_CLIENT_SECRET,
      }),
    ],
  },
})

No authorization block yet? Create one with just ssoAdapters, as in the SSO setup. Then restart the dev server, since .env and the API config are only read at start-up.

Check the result

Open /login, press the LinkedIn button under Continue with and allow access. You return to /login/sso/linkedin signed in.

Scopes and profile fields

SettingValue
Scopesopenid profile email
Account IDsub
Email trustedonly with email_verified: true
Profile fieldsavatar, first name, last name

LinkedIn's OpenID configuration lists only pairwise subject IDs, so the same person can get a different sub in another LinkedIn app. Keep one app for production: moving to a new client ID means existing members' links no longer match.

LinkedIn may leave out the email, or mark it unverified. A new member then confirms an address by email; a returning member still signs in by their LinkedIn ID.

VitNode reads UserInfo with the access token it has just received from LinkedIn's token endpoint over TLS, so it does not decode LinkedIn's ID token. LinkedIn notes that this product does not verify identities, so treat a LinkedIn sign-in like any other social account.

Troubleshooting

  • An invalid scope error. The Sign In with LinkedIn using OpenID Connect product is missing from the Products tab.
  • A redirect URI mismatch error. The URL on the Auth tab differs from {VITNODE_WEB_URL}/login/sso/linkedin.
  • The older r_liteprofile and r_emailaddress scopes. LinkedIn retired them in 2023. The adapter never requests them.