Статьи

Объединение клиентского социального входа в систему и авторизации на стороне сервера с Cordova и Node.js

Я считаю, что это выигрывает титул самого длинного заголовка в мире Так о чем, черт возьми, я говорю? Нетрудно добавить аспект социального входа в приложение Apache Cordova. Я использовал множество плагинов / библиотек в прошлом и по большей части — это просто работает. Однако недавно я столкнулся с проблемой, которую я не знал, как обойти. Учитывая, что ваш мобильный клиент аутентифицирует пользователя по отношению к какому-либо провайдеру OAuth, и если вы  затем разрешите этому пользователю взаимодействовать с вашим сервером, как а) убедиться, что человек, использующий серверный API, аутентифицирован, и б) как вы однозначно идентифицируете это? пользователь? Это немного абстрактно, так как насчет реального примера?

Представьте, что вы создаете мобильное приложение, которое позволяет пользователю писать заметки. Хотя вы можете хранить заметки на клиенте, вам действительно нужно хранить их в своем внутреннем хранилище. Чтобы гарантировать, что только аутентифицированные пользователи имеют доступ к вашим серверным API, вы можете создать свою собственную пользовательскую систему, иметь логин пользователя (конечно, через https), сохранять переменную сеанса с информацией об их учетной записи, а также когда они создают данные (или пытаются читать данные), использовать какой-то первичный ключ, чтобы получить правильные данные.

Это довольно шаблонно. Но что происходит, когда вы входите в социальный логин на стороне клиента? В этом случае мобильное приложение обрабатывает запрос OAuth для поставщика, и поставщик возвращает токен. Таким образом, на стороне клиента вы знаете, что текущий пользователь кошерный. Но когда она отправляет запрос на ваш сервер Node (или ColdFusion, PHP и т. Д.), Как вы справляетесь, зная, что пользователь вошел в систему — и даже лучше — как вы получаете уникальный идентификатор для этого пользователя, чтобы вы могли правильно обрабатывать его операции с данными.

Я немного поискал и наткнулся на этот пост / ответ Stackoverflow:  iOS & node.js: как проверить пройденный токен доступа? , Пользователь Gijs ответил, что разные поставщики OAuth имеют разные способы аутентификации токена доступа. Поэтому идея будет состоять в том, чтобы передать токен вашему внутреннему серверу, проверить его, а затем получить уникальный идентификатор.

Я решил дать этому шанс и построить простое доказательство концепции. Это очень грубо, но дает вам общее представление о том, как вы могли бы сделать это. Для моего POC я решил использовать OpenFB  библиотеку Кристофа  Коэнраэта . Это библиотека JavaScript без плагинов, которая обрабатывает OAuth. Совсем недавно я также использовал  ng-cordova-oauth  , но я хотел попробовать что-то другое. Я создал быстрое приложение Ionic с двумя простыми кнопками:

Название изображения

Первая кнопка запускает процесс OAuth. Я следовал указаниям Кристофа и сначала создал приложение для Facebook:

Название изображения

Код этого довольно прост:

$scope.doLogin = function() {
    console.log("DoLogin");
      openFB.login(
      function(response) {
        if(response.status === 'connected') {
          $scope.token = response.authResponse.accessToken;
          console.log('Token stored: ',response);
          alert('Ok, try to make a call now');
        } else {
          alert('Facebook login failed: ' + response.error);
        }
      }, {scope: 'email'});                
}

Примечание. Я храню токен доступа, чтобы использовать его позже. Далее — нам нужно вызвать сервер. Если я правильно помню, Angular предоставляет способ изменить  все  HTTP-запросы, чтобы включить материал. Сейчас я сохраняю это простым и просто включаю токен как часть поста формы.

$scope.doNode = function() {
    $http.post('http://localhost:3000/test1',{msg:"Hello",token:$scope.token}).
    success(function() {
      console.log('yes im ok');
    }).
    error(function(data,status,headers,config) {
      console.log('error from node');
      console.dir(arguments);      
    });
}

Хорошо, пока все хорошо. Теперь давайте обратимся к стороне узла. Как упоминалось в сообщении StackOverflow, на которое я ссылался выше, вы можете отправить запрос на graph.facebook.com с токеном, и, если вы получите правильный ответ, вы знаете, что все в порядке. Я написал функцию, которую позже смог бы использовать для промежуточного программного обеспечения. Он кэширует тест в области видимости сеанса, который кажется безопасным, но, возможно, это не очень хорошая идея.

Здесь стоит кое-что отметить: я специально прошу вернуть адрес электронной почты. Мой результат выглядит так:

{ email: 'raymondcamden@gmail.com', id: 'abigassnumber' }

Теоретически, идентификатор достаточно уникален. Однако, если я использую несколько разных провайдеров oauth, я могу вместо этого использовать электронную почту в качестве первичного ключа. Это позволит вам войти через Facebook  или  Twitter и иметь те же данные, если вы используете один и тот же адрес электронной почты для обеих учетных записей. Обратите внимание, что я  не  храню этот адрес электронной почты. Я бы в реальном приложении. Наконец, вот маршрут, который я позвонил из мобильного приложения:

app.post('/test1', secure, function(req, res) {
console.log('attempting test1');
var msg = req.body.msg;
console.log('msg was '+msg);
res.send("1");
});

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

Как я уже сказал, это грубо, но мне  кажется,  что это имеет смысл. Как насчет тебя?