npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@idio/linkedin

v1.4.0

Published

The LinkedIn OAuth Login Routes For The Idio Web Server.

Downloads

2

Readme

@idio/linkedin

npm version

@idio/linkedin is The LinkedIn OAuth Login Routes For The Idio Web Server.

yarn add -E @idio/linkedin

Table Of Contents

API

The package is available by importing its default and named functions:

import linkedin, {
  linkedInButton, query, getUser,
} from '@idio/linkedin'

linkedin(  router: Router,  config: Config,): void

Sets up the /auth/linkedin and /auth/linkedin/redirect paths on the router to enable LinkedIn App Login. The session middleware needs to be installed to remember the state. The state is destroyed after the redirect.

Config: Options for the program.

| Name | Type | Description | Default | | ------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------- | | client_id* | string | The app's client id. | - | | client_secret* | string | The app's client secret. | - | | path | string | The server path to start the login flaw and use for redirect (${path}/redirect). | /auth/linkedin | | scope | string | The scope to ask permissions for. | r_liteprofile | | finish | (ctx, token, user) => {} | The function to complete the authentication that receives the token and the data about the user, such as name and id. The default function redirects to /. | setSession; redirect; | | error | (ctx, error, error_description, next) => {} | The function to be called in case of error. If not specified, the middleware will throw an internal server error. | throw; | | session | Middleware | The configured session middleware in case the session property is not globally available on the context. | - |

import linkedIn, { query, linkedInButton, getUser } from '@idio/linkedin'
import idioCore from '@idio/core'

const Server = async () => {
  const { url, router, app, middleware: {
    session,
  } } = await idioCore({
    session: {
      keys: [process.env.SESSION_KEY],
    },
    logger: { use: true },
  }, { port: 0 })
  router.get('/', async (ctx) => {
    const u = await userDiv(ctx.session.user)
    ctx.body = `<!doctype html>
    <html>
      <body>
        ${u}
        <hr>
        &copy;Art Deco, 2019
      </body>
    </html>`
  })
  router.get('/signout', session, (ctx) => {
    ctx.session = null
    ctx.redirect('/')
  })
  linkedIn(router, {
    session,
    client_id: process.env.LINKEDIN_ID,
    client_secret: process.env.LINKEDIN_SECRET,
    scope: 'r_liteprofile,r_basicprofile',
    error(ctx, error) {
      ctx.redirect(`/?error=${error}`)
    },
    async finish(ctx, token, user) {
      const { positions: { values: pos } } = await query({
        token,
        path: 'people/~:(positions)',
        version: 'v1',
      })
      const positions = pos.map(({
        title,
        company: { id, name },
        location: { name: location } ,
      }) => {
        return {
          id, name, title,
          location: location.replace(/,\s*$/, ''),
        }
      })
      ctx.session.token = token
      ctx.session.user = getUser(user)
      ctx.session.positions = positions
      ctx.redirect('/')
    },
  })
  app.use(router.routes())
  return { app, url }
}

const userDiv = async (user) => {
  if (!user) {
    const { idioCommon, style, button } = await linkedInButton()
    return `
    <style>
      ${idioCommon}
      ${style}
    </style>
    <div class="User">
      <p>Welcome.</p>
      ${button}
    </div>`
  }
  const img = `<img src="${user.profilePicture}" width="50">`
  return `
    <div class="User">
      ${img} Hello, ${user.firstName} ${user.lastName}!
      <a href="/signout">Sign out</a>
    </div>`
}
[+] LINKEDIN_ID [+] LINKEDIN_SECRET [+] SESSION_KEY 
http://localhost:65210 
  <-- GET /auth/linkedin
  --> GET /auth/linkedin 302 35ms 487b
{ body: 'Redirecting to <a href="https://www.linkedin.com/oauth/v2/authorization?state=7739&amp;response_type=code&amp;client_id=86986rqg6dmn58&amp;redirect_uri=http%3A%2F%2Flocalhost%3A65210%2Fauth%2Flinkedin%2Fredirect&amp;scope=r_liteprofile%2Cr_basicprofile">https://www.linkedin.com/oauth/v2/authorization?state=7739&amp;response_type=code&amp;client_id=86986rqg6dmn58&amp;redirect_uri=http%3A%2F%2Flocalhost%3A65210%2Fauth%2Flinkedin%2Fredirect&amp;scope=r_liteprofile%2Cr_basicprofile</a>.',
  headers: 
   { location: 'https://www.linkedin.com/oauth/v2/authorization?state=7739&response_type=code&client_id=86986rqg6dmn58&redirect_uri=http%3A%2F%2Flocalhost%3A65210%2Fauth%2Flinkedin%2Fredirect&scope=r_liteprofile%2Cr_basicprofile',
     'content-type': 'text/html; charset=utf-8',
     'content-length': '487',
     'set-cookie': 
      [ 'koa:sess=eyJzdGF0ZSI6NzczOSwiX2V4cGlyZSI6MTU0NzAzODExNTUxOSwiX21heEFnZSI6ODY0MDAwMDB9; path=/; httponly',
        'koa:sess.sig=w_PIzlf56BzzK4-XTnXWKCD0oMc; path=/; httponly' ],
     date: 'Tue, 08 Jan 2019 12:48:35 GMT',
     connection: 'close' },
  statusCode: 302,
  statusMessage: 'Found' }

 > Redirect to Dialog https://www.linkedin.com/oauth/v2/authorization?state=7739&response_type=code&client_id=86986rqg6dmn58&redirect_uri=http%3A%2F%2Flocalhost%3A65210%2Fauth%2Flinkedin%2Fredirect&scope=r_liteprofile%2Cr_basicprofile

finish

The config allows to set the finish function that can be used to alter the logic of setting the token on the session or performing additional operations such as storing a new user in the database. The default sets the token on the ctx.session and also sets the user data such as name and id in the ctx.session.user property.

error

The error property of the config represent the function to be called in case of an error such as when the user cancelled the authorisation request. It can be used to redirect to the path and set the error text and description in the query parameters. When default handler is used, the @idio/linkedin middleware will throw internally.

getUser(  user: *,): User

When data is requested from /me route for the lite profile, the results will come back containing a lot of metadata such as names' locales and an array with profile pictures of different sizes. The getUser method returns those properties as strings.

User: The normalised user data from the /me path.

| Name | Type | Description | | ------------------- | -------- | ------------------------------- | | id* | string | The user ID. | | firstName* | string | The user's first name. | | lastName* | string | The user's last name. | | profilePicture* | string | The URL to the profile picture. |

async query(  config: QueryConfig,): *

The query method allows to query the LinkedIn API. The v2 version of the API only allows to query basic data with the r_liteprofile permission. The other methods of the API are not pubic. This package will automatically query the /me route to find out the user's name and profile picture, therefore specifying the r_liteprofile scope is required. The v1 version which is used to query positions with the r_basicprofile scope will be switched off in March 2019.

QueryConfig: Options for Query.

| Name | Type | Description | Default | | ---------- | -------- | ------------------------------------------------- | ------- | | token* | string | The access token with appropriate permissions. | - | | path* | string | The API endpoint. | - | | data* | * | The object containing data to query the API with. | - | | version | string | The version of the API to query. | v2 |

linkedInButton(): { idioCommon, style, button }

The package provides the implementation of the Sign-In button with CSS and HTML. It was added in favour of the static image button to be able to switch background color on hover, and instead of an SVG button because problems will arise when placing SVG into an a element.

| Button | Source | | --------------------------------------- | -------------------------------------------------------------------------------------------- | | Default Button | The default Linked In button from https://developer.linkedin.com/downloads. | | Idio Linkedin Button | Idio's button CSS+HTML implementation. It supports hover, active and focus properties. |

Copyright

(c) Idio 2019