Во-первых, вам необходимо зарегистрировать свое приложение в 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, которая не заботится о сценариях ошибок, аутентификации возвращающихся пользователей, истечении срока действия и передовых методах.
удачного взлома!