or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# passport-linkedin

1

2

passport-linkedin is a Passport authentication strategy for integrating LinkedIn OAuth 1.0a authentication into Node.js applications. It allows applications to authenticate users through their LinkedIn accounts with configurable permission scopes and profile field selection.

3

4

## Package Information

5

6

- **Package Name**: passport-linkedin

7

- **Package Type**: npm

8

- **Language**: JavaScript

9

- **Installation**: `npm install passport-linkedin`

10

11

## Core Imports

12

13

```javascript

14

// Default import (recommended)

15

const LinkedInStrategy = require('passport-linkedin');

16

```

17

18

Alternative imports:

19

20

```javascript

21

// Named import

22

const { Strategy } = require('passport-linkedin');

23

24

// Explicit Strategy property access

25

const LinkedInStrategy = require('passport-linkedin').Strategy;

26

```

27

28

## Basic Usage

29

30

```javascript

31

const passport = require('passport');

32

const LinkedInStrategy = require('passport-linkedin');

33

34

passport.use(new LinkedInStrategy({

35

consumerKey: 'YOUR_LINKEDIN_API_KEY',

36

consumerSecret: 'YOUR_LINKEDIN_SECRET_KEY',

37

callbackURL: 'http://localhost:3000/auth/linkedin/callback'

38

},

39

function(token, tokenSecret, profile, done) {

40

// User authentication logic

41

User.findOrCreate({ linkedinId: profile.id }, function (err, user) {

42

return done(err, user);

43

});

44

}

45

));

46

47

// Routes

48

app.get('/auth/linkedin', passport.authenticate('linkedin'));

49

50

app.get('/auth/linkedin/callback',

51

passport.authenticate('linkedin', { failureRedirect: '/login' }),

52

function(req, res) {

53

// Successful authentication

54

res.redirect('/');

55

});

56

```

57

58

## Architecture

59

60

passport-linkedin extends Passport's OAuth 1.0a strategy with LinkedIn-specific customizations:

61

62

- **OAuth1 Foundation**: Built on `passport-oauth1` for standard OAuth 1.0a protocol handling

63

- **LinkedIn API Integration**: Configured with LinkedIn-specific endpoints and request modifications

64

- **Scope Handling**: Custom implementation to handle LinkedIn's URL parameter-based scope requests

65

- **Profile Normalization**: Converts LinkedIn API responses to standardized Passport profile format

66

- **Field Mapping**: Flexible system for requesting specific LinkedIn profile fields

67

- **Error Handling**: LinkedIn-specific error detection and OAuth error wrapping

68

69

## Capabilities

70

71

### LinkedIn Strategy

72

73

Creates a new LinkedIn authentication strategy for Passport.

74

75

```javascript { .api }

76

/**

77

* LinkedIn authentication strategy constructor

78

* @param {Object} options - Configuration options

79

* @param {Function} verify - Verification callback function

80

*/

81

function Strategy(options, verify);

82

```

83

84

**Options:**

85

86

```javascript { .api }

87

interface StrategyOptions {

88

/** LinkedIn API consumer key (required) */

89

consumerKey: string;

90

/** LinkedIn API consumer secret (required) */

91

consumerSecret: string;

92

/** OAuth callback URL (required) */

93

callbackURL: string;

94

/** Specific profile fields to request (optional) */

95

profileFields?: string[];

96

/** Request token URL (optional) */

97

requestTokenURL?: string;

98

/** Access token URL (optional) */

99

accessTokenURL?: string;

100

/** User authorization URL (optional) */

101

userAuthorizationURL?: string;

102

/** Session key for OAuth tokens (optional) */

103

sessionKey?: string;

104

}

105

```

106

107

**Verify Callback:**

108

109

```javascript { .api }

110

/**

111

* Verification callback function

112

* @param {string} token - OAuth access token

113

* @param {string} tokenSecret - OAuth token secret

114

* @param {Object} profile - User profile object

115

* @param {Function} done - Completion callback

116

*/

117

function verify(token, tokenSecret, profile, done);

118

```

119

120

### Extended Permissions

121

122

Request extended permissions using the scope parameter during authentication.

123

124

```javascript

125

// Single scope

126

app.get('/auth/linkedin',

127

passport.authenticate('linkedin', { scope: 'r_fullprofile' }));

128

129

// Multiple scopes

130

app.get('/auth/linkedin',

131

passport.authenticate('linkedin', {

132

scope: ['r_basicprofile', 'r_emailaddress']

133

}));

134

```

135

136

### Profile Field Selection

137

138

Configure specific profile fields to request from LinkedIn API.

139

140

```javascript

141

passport.use(new LinkedInStrategy({

142

consumerKey: 'YOUR_API_KEY',

143

consumerSecret: 'YOUR_SECRET',

144

callbackURL: 'http://localhost:3000/auth/linkedin/callback',

145

profileFields: ['id', 'first-name', 'last-name', 'email-address', 'headline']

146

},

147

function(token, tokenSecret, profile, done) {

148

// Handle authentication

149

return done(null, profile);

150

}

151

));

152

```

153

154

### Strategy Methods

155

156

#### authenticate

157

158

Handles the OAuth authentication flow and processes LinkedIn responses. Extends the base OAuth1 strategy authentication with LinkedIn-specific error handling.

159

160

```javascript { .api }

161

/**

162

* Authenticate request using LinkedIn OAuth

163

* @param {Object} req - HTTP request object

164

* @param {Object} options - Authentication options (scope, etc.)

165

* @returns {void} - Calls success(), fail(), or error() on completion

166

*/

167

Strategy.prototype.authenticate(req, options);

168

```

169

170

**Special behavior:**

171

- Detects `oauth_problem=user_refused` query parameter and calls `fail()` for user denial

172

- Delegates to parent OAuth1Strategy for standard OAuth flow

173

- Handles LinkedIn-specific OAuth token request modifications for scope parameter

174

175

#### userProfile

176

177

Retrieves user profile information from LinkedIn API.

178

179

```javascript { .api }

180

/**

181

* Retrieve user profile from LinkedIn

182

* @param {string} token - OAuth access token

183

* @param {string} tokenSecret - OAuth token secret

184

* @param {Object} params - Additional parameters

185

* @param {Function} done - Completion callback with (err, profile)

186

*/

187

Strategy.prototype.userProfile(token, tokenSecret, params, done);

188

```

189

190

#### requestTokenParams

191

192

Returns LinkedIn-specific parameters for request token requests, with special handling for scope parameters.

193

194

```javascript { .api }

195

/**

196

* Return extra LinkedIn-specific parameters for request token request

197

* @param {Object} options - Options containing scope information

198

* @param {string|string[]} options.scope - LinkedIn permission scope(s)

199

* @returns {Object} Parameters object with scope handling

200

*/

201

Strategy.prototype.requestTokenParams(options);

202

```

203

204

**Scope handling:**

205

- String scopes are passed directly: `'r_basicprofile'`

206

- Array scopes are joined with '+': `['r_basicprofile', 'r_emailaddress']``'r_basicprofile+r_emailaddress'`

207

- LinkedIn expects scope as URL query parameter, not in POST body (handled automatically)

208

209

## Types

210

211

### Profile Object

212

213

The profile object returned by LinkedIn contains normalized user information:

214

215

```javascript { .api }

216

interface LinkedInProfile {

217

/** Always 'linkedin' */

218

provider: string;

219

/** LinkedIn user ID */

220

id: string;

221

/** Full display name (firstName + lastName) */

222

displayName: string;

223

/** Name breakdown */

224

name: {

225

/** Last name */

226

familyName: string;

227

/** First name */

228

givenName: string;

229

};

230

/** Email addresses (if requested via profileFields) */

231

emails?: Array<{

232

/** Email address value */

233

value: string;

234

}>;

235

/** Raw API response body */

236

_raw: string;

237

/** Parsed JSON response */

238

_json: {

239

/** LinkedIn user ID */

240

id: string;

241

/** First name from LinkedIn */

242

firstName: string;

243

/** Last name from LinkedIn */

244

lastName: string;

245

/** Email address (if requested) */

246

emailAddress?: string;

247

/** Additional fields based on profileFields configuration */

248

[key: string]: any;

249

};

250

}

251

```

252

253

### Strategy Instance Properties

254

255

```javascript { .api }

256

interface StrategyInstance {

257

/** Strategy name, always 'linkedin' */

258

name: string;

259

}

260

```

261

262

## Profile Field Mapping

263

264

Standard profile field names are mapped to LinkedIn API fields:

265

266

- `'id'``'id'`

267

- `'name'``['first-name', 'last-name']`

268

- `'emails'``'email-address'`

269

270

Unmapped field names are passed directly to the LinkedIn API, allowing access to additional LinkedIn profile data.

271

272

### Profile Field Conversion

273

274

The strategy internally converts profile field names using a mapping system:

275

276

```javascript { .api }

277

/**

278

* Internal method to convert profile field names to LinkedIn API format

279

* @param {string[]} profileFields - Array of profile field names

280

* @returns {string} Comma-separated LinkedIn API field names

281

* @private

282

*/

283

Strategy.prototype._convertProfileFields(profileFields);

284

```

285

286

**Example conversions:**

287

- `['id', 'name', 'emails']``'id,first-name,last-name,email-address'`

288

- `['id', 'headline', 'industry']``'id,headline,industry'` (unmapped fields passed through)

289

290

This enables flexible profile data collection while maintaining compatibility with standard field names.

291

292

## Error Handling

293

294

The strategy handles common error scenarios:

295

296

- **User Denial**: When users deny authorization, the strategy detects `oauth_problem=user_refused` parameter and calls `fail()`

297

- **Profile Fetch Errors**: API errors during profile retrieval are wrapped in `InternalOAuthError` from passport-oauth1

298

- **Invalid Responses**: JSON parsing errors during profile processing are passed to the done callback

299

300

### InternalOAuthError

301

302

```javascript { .api }

303

/**

304

* OAuth-specific error wrapper from passport-oauth1

305

* @param {string} message - Error description

306

* @param {Error} err - Original error object

307

*/

308

class InternalOAuthError extends Error {

309

constructor(message, err);

310

/** OAuth error details */

311

oauthError: Error;

312

}

313

```

314

315

## Scope Values

316

317

Common LinkedIn permission scopes:

318

319

- `r_basicprofile` - Basic profile information

320

- `r_emailaddress` - Email address

321

- `r_fullprofile` - Full profile access

322

- `w_messages` - Send messages

323

- `rw_company_admin` - Company administration

324

325

Multiple scopes are joined with '+' when sent to LinkedIn API.