Во-первых, вам необходимо зарегистрировать свое приложение в Linkedin.

После регистрации вам будут предоставлены client_id и client_secret, которые мы будем использовать позже в коде. Кроме того, мы укажем URL-адреса перенаправления, которые linkedin будет вызывать для проверки входа.

В вашем HTML-коде создайте ссылку со следующими параметрами:

https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=123456789&redirect_uri=https%3A%2F%2Fwww.example.com%2Fauth%2Flinkedin&state=987654321&scope=r_basicprofile

response_type, всегда должен быть кодом.

client_id - открытый ключ для идентификации вашего приложения.

redirect_uri - это URL-адрес, который вы указали при регистрации приложения.

scope - права доступа, которые приложение запрашивает r_basicprofile . Следующие поля могут быть запрошены https://developer.linkedin.com/docs/fields/basic-profile.

Давайте сначала создадим базовый пользовательский интерфейс, который будет предоставлять кнопку входа в LinkedIn.

Код пользовательского интерфейса доступен по адресу https://github.com/cssmiles/linkedinoauth_web

class App extends Component {
    render() {
        const authurl = "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=77arqe48ycj44b&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fauth&state=2522abcde12345&scope=r_basicprofile";
        return (
            <div className="App">
                <a href={authurl}><img src="signin.png" alt="Sign in with Linkedin"/></a>
            </div>
        );
    }
}

После того, как пользователь войдет в систему и примет и авторизует приложение, Linkedin API вызовет наш URL-адрес перенаправления (http: // localhost: 5000 / auth).

Чтобы обработать ответ Linkedin, мы напишем небольшое приложение узла.

Полный бэкэнд-код доступен по адресу https://github.com/cssmiles/linkedinoauth.

В маршруте аутентификации найдите параметр запроса для параметров состояния и кода. Чтобы получить фактический токен доступа для доступа к данным профиля, вам сначала нужно взять предоставленный код и отправить обратно секретный ключ. Как только рукопожатие будет выполнено, linkedin предоставит access_token со сроком действия. В последующем вызове нам нужно передать это, чтобы получить доступ к данным профиля.

app.get('/auth', function (req, res) {
    // This is the redirect URI which linkedin will call to and provide state and code to verify
    /**
     *
     * Attached to the redirect_uri will be two important URL arguments that you need to read from the request:

     code — The OAuth 2.0 authorization code.
     state — A value used to test for possible CSRF attacks.
     */
  

    //TODO: validate state here to secure against CSRF
    var error = req.query.error;
    var error_description = req.query.error_description;
    var state = req.query.state;
    var code = req.query.code;
    if (error) {
        next(new Error(error));
    }
    /**
     *
     * The code is a value that you will exchange with LinkedIn for an actual OAuth 2.0 access
     * token in the next step of the authentcation process.  For security reasons, the authorization code
     * has a very short lifespan and must be used within moments of receiving it - before it expires and
     * you need to repeat all of the previous steps to request another.
     */
    //once the code is received handshake back with linkedin to send over the secret key
    handshake(req.query.code, res);
})

В рукопожатии метод предоставляет Linkedin закрытый ключ client_secret, чтобы гарантировать правильного получателя. Ниже приведены все параметры публикации, которые необходимо предоставить linkedin.

function handshake(code, ores) {

    //set all required post parameters
    var data = querystring.stringify({
        grant_type: "authorization_code",
        code: code,
        redirect_uri: OauthParams.redirect_uri,//should match as in Linkedin application setup
        client_id: OauthParams.client_id,
        client_secret: OauthParams.client_secret// the secret
    });

    var options = {
        host: 'www.linkedin.com',
        path: '/oauth/v2/accessToken',
        protocol: 'https:',
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': Buffer.byteLength(data)
        }
    };
    
    var req = http.request(options, function (res) {
         var data = '';
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            data += chunk;

        });
        res.on('end', function () {
            //once the access token is received store in DB
            insertTodb(JSON.parse(data), function (id) {
                //need to find better way and proper authetication for the user
                ores.redirect('https://localhost:3000/dashboard/' + id);
            });
        });
        req.on('error', function (e) {
            console.log("problem with request: " + e.message);
        });

    });
    req.write(data);
    req.end();


}

Как только вы получите access_token, сохраните его в БД (например, mongodb).

function insertTodb(token, callback) {
    
    MongoClient.connect(url, function (err, db) {
        var collection = db.collection('documents');
        collection.insertOne(
            token
            , function (err, result) {
                //assert.equal(err, null);
                callback(result.ops[0]._id);

            });

    });

Когда у вас есть запись, вы можете перенаправить пользователя на соответствующий маршрут, указав идентификатор (uid, полученный от linkedin или ваш собственный).

При любом последующем вызове клиент может вызвать нашу конечную точку (: 5000 / profiledata) с идентификатором и может получить полные данные профиля.

//profile data endpoint will call api with required parameters
var
    options = {
        host: 'api.linkedin.com',
        path: '/v1/people/~:(id,first-name,last-name,headline,picture-url,location,industry,current-share,num-connections,summary,specialties,positions)?format=json',
        protocol: 'https:',
        method: 'GET',
        headers: {
            "Authorization": 'Bearer ' + obj.access_token

        }
    };
    var
    req = http.request(options, function (res) {
        res.setEncoding('utf8');
        var data = '';
        res.on('data', function (chunk) {
            data += chunk;
        });
        res.on('end', function () {
            callback(JSON.parse(data));
            console.log('No more data in response.');
        });
        req.on('error', function (e) {
            console.log("problem with request: " + e.message);
        });

    });
    req.end();

Это быстрая и грязная реализация доступа к linkedin api, которая не заботится о сценариях ошибок, аутентификации возвращающихся пользователей, истечении срока действия и передовых методах.

удачного взлома!