WebアプリケーションへのLinkedIn OAuthの追加(外部ライブラリなし)



導入
最近のプロジェクトはLinkedIn Oauthに私を得ました、そして、男の子は最初に頭痛でした!そして、今日、私はその頭痛からあなたを救おうとします.だから、始めましょう!

セットアップ
我々は、ユーザーへの認証のための当社のWebアプリケーションを表すLinkedInアプリケーションを必要とするでしょう(LinkedInアプリケーションを作成).また、我々のアプリのページが必要です.私は知っている、この😑)

最小限の詳細とページのURLを入力ボックスでページを作成した後、我々はほとんどのアプリを作成完了です

私たちがURLの上で我々のアプリを見るならば、それ

Authセクションでは、いくつかの興味深いものが表示されます.ここでは、AuthアプリケーションにリダイレクトURIを提供する必要があります.

注意: Redirect URIは、認証後にLinkedInをリダイレクトするWebアプリケーションの一部の絶対URLパスです.
私はURLを与えているので、ここで、私は私のローカルマシン上のWebアプリをホストしていますhttp://localhost:3000 , 他のルートやURLを指定できます.
私は、私たちが非常にしばしばそれを必要としているように、あなたのアプリケーションの環境変数にリダイレクトURIを格納することを提案します、そして、また、ENV変数は異なる値(すなわち生産と開発)で異なる環境でそれらを使うのを許容する基本的な定数変数を組織する方法を提案されます.
今、最終的なセットアップステップに来る.我々はAuthタブでここで見ることができるように我々のアプリにoAuthのスコープ/パーミッションを与えていない.

我々のアプリへのアクセス許可を与えるために、我々は製品のタブで行く必要があります.LinkedIn我々のアプリを確認し、いくつかの瞬間の後、製品はそれに追加する必要があります😑). 完了すると、それは“auth”タブに反映されます

フィル!それはセットアップの多くだった!楽しみに移動しましょう;

認証フロー
LinkedIn Authには3段階認証プロセスがあります.
  • 承認を得るcode (フロントエンドで行われる)
  • コードを交換するaccess_token (バックエンドが必要)
  • エクスチェンジaccess_token ユーザーの詳細(電子メール、名前など)を取得するには(バックエンドが必要です)

  • バックエンドを必要とするものは何ですか?
    ステップ2と3で作られる要請からの応答は、ありませんAccess-Control-Allow-Origin ヘッダ.これは、ブラウザがこれらのタイプのリクエストをブロックするとき、LinkedInのサーバによって返送されたデータを読むことができないことを意味しますhere .
    したがって、ブラウザで動作していない何かが必要です.

    コード

    ステップ1authorization_code )
    認証コードを取得するには、次のパラメータを使用してユーザーにこのURLをリダイレクトする必要があります.

    (the state パラメータが不要です.
    ユーザをリダイレクトする最終URLは次のようになります.
    `https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=${process.env.REACT_APP_CLIENTID}&redirect_uri=${process.env.REACT_APP_REDIRECT_URI}&scope=r_liteprofile,r_emailaddress`
    
    今、我々は、我々がフェッチされるフロントエンドに移動することができますauthorization_code , 私はここで反応を使用していますが、あなたも純粋なvanillajsを使用することができます.
    // App.js
    export default function App() {
    
      const linkedinRedirectUrl = `https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=${process.env.REACT_APP_CLIENTID}&redirect_uri=${process.env.REACT_APP_REDIRECT_URI}&scope=r_liteprofile,r_emailaddress`
    
      const handleLinkedinLogin = () => {
        window.location.href = linkedinRedirectUrl
      }
    
      return (
        <div className="App">
          <button onClick={handleLinkedinLogin}>
            Login with LinkedIn
          </button>
        </div>
      );
    }
    
    ボタンをクリックしてください.

    動く!
    をクリックして我々のアプリのホームページにリダイレクトをクリックしますが、アドレスバーで何か別のです!

    thatsコード!

    ステップ2authorization_code )
    さて、この手順では、リダイレクションの後にコードを取得しなければなりません.だから私はuseEffect 取得するcode それがすべてのページ荷の上でアドレスバーに存在するならば.
    // App.js
    import { useEffect } from 'react'
    
    export default function App() {
    
      const linkedinRedirectUrl = `https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=${process.env.REACT_APP_CLIENTID}&redirect_uri=${process.env.REACT_APP_REDIRECT_URI}&scope=r_liteprofile,r_emailaddress`
    
      useEffect(() => {
        let windowUrl = window.location.href
        if (windowUrl.includes('code=')) {
          let codeMatch = windowUrl.match(/code=([a-zA-Z0-9_\-]+)/)
          // And to those who hate regex...
          // YES I used regex here! B*TCHES!
          // Anyway, I prefer learning it, quite POWERFUL as shown
    
        }
    
      }, [])
    
      const handleLinkedinLogin = () => {
        window.location.href = linkedinRedirectUrl
      }
    
      return (
        <div className="App">
          <button onClick={handleLinkedinLogin}>
            Login with LinkedIn
          </button>
        </div>
      );
    }
    
    私が使用したそのregexについて、それはちょうど小文字のアルファベット(A - Z)、大文字のアルファベット(A - Z)、アンダースコアとハイフンであるキャラクタのグループをピックアップすることを意味します.ページを再読み込みするとcode .
    今、リクエストを要求するバックエンドが必要ですaccess_token 交換code と要求のユーザー情報をaccess_token . それを造りましょう!

    ステップ3 (ユーザデータを取得する)access_token )
    エンドポイントのバックエンドコードは、access_token & ユーザ情報.
    require('dotenv').config()
    const cors = require('cors')
    const axios = require('axios')
    
    const app = require('express')()
    app.use(cors())
    
    app.get('/user', async (req, res) => {
        try {
            const code = req.headers.auth_code
            if (!code) throw new Error('No code provided')
    
            // This request gets access_token
            let accessTokenResponse = await axios.get(`https://www.linkedin.com/oauth/v2/accessToken?grant_type=authorization_code&code=${code}&client_id=${process.env.CLIENTID}&client_secret=${process.env.CLIENT_SECRET}&redirect_uri=${process.env.REDIRECT_URI}`)
    
            // This request gets user info from access_token (given in the headers of the request)
            let userInfoResponse = await axios.get('https://api.linkedin.com/v2/me', {
                headers: {
                    'Authorization': `Bearer ${accessTokenResponse.data.access_token}`
                }
            })
    
            return res.status(200).json(userInfoResponse.data)
    
        } catch (err) {
            console.log(err)
            return res.status(400).json({ message: 'Error authenticating' })
    
        }
    })
    
    app.listen(3001, () => console.log('Server started'))
    
    エンドポイントのすべてのセットアップ!このエンドポイントにGETリクエストを作成するためにブロックを追加しますuseEffect 我々のフロントエンドの.
    // App.js
    import axios from 'axios'
    import { useEffect } from 'react'
    
    export default function App() {
    
      const linkedinRedirectUrl = `https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=${process.env.REACT_APP_CLIENTID}&redirect_uri=${process.env.REACT_APP_REDIRECT_URI}&scope=r_liteprofile,r_emailaddress`
    
      useEffect(() => {
        let windowUrl = window.location.href
        if (windowUrl.includes('code=')) {
          let codeMatch = windowUrl.match(/code=([a-zA-Z0-9_\-]+)/)
    
          axios.get('http://localhost:3001/user', {
            headers: {
              auth_code: codeMatch[1]
            }
          })
          .then(res => {
            console.log(res.data)
    
          })
          .catch(console.log)
    
        }
    
      }, [])
    
      const handleLinkedinLogin = () => {
        window.location.href = linkedinRedirectUrl
      }
    
      return (
        <div className="App">
          <button onClick={handleLinkedinLogin}>
            Login with LinkedIn
          </button>
        </div>
      );
    }
    
    ヒント:印刷を試みるcodeMatch 変数は、whatsの上で進行中の考えを得るために.match() 方法
    さて、もう一度「LinkedInでのログイン」ボタンをクリックしてみましょう.