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