Сначала вам нужно установить базу данных Redis на свой компьютер, загрузить ее отсюда для пользователей Linux и отсюда, чтобы установить версию для Windows, и мы будем использовать настольное приложение Redis Manager, установите его отсюда.

Теперь нам нужно настроить наш сервер node.js на использование базы данных redis.

OAuth 2 с реализацией Redis

  • app.js
var express = require('express'),
        bodyParser = require('body-parser'),
        oauthserver = require('oauth2-server');
     
    var app = express();
     
    app.use(bodyParser.urlencoded({ extended: true }));
     
    app.use(bodyParser.json());
     
  app.oauth = oauthserver({
  model: require('./routes/Oauth2/model.js'), // See below for specification 
  grants: ['refresh_token','client_credentials', 'password'],
  accessTokenLifetime: config.accessTokenLifetime,//60 * 60 * 24,
  debug: true
});
// When a user requested an oauth token
app.all('/oauth/token', app.oauth.grant());
     
    // Each get, post, put or delete should have app.oauth.authorise() function to authenticate
    app.get('/', app.oauth.authorise(), function (req, res) {
     // Your behaviour goes here
      res.send('Secret area');
    });
     
    app.use(app.oauth.errorHandler());
     
    app.listen(3000);
  • routes / Oauth2 / model.js
var model = module.exports,
      util = require('util'),
      redis = require('redis');
var db = redis.createClient();
var keys = {
  token: 'tokens:%s',
  client: 'clients:%s',
  refreshToken: 'refresh_tokens:%s',
  grantTypes: 'clients:%s:grant_types',
  user: 'users:%s'
};
model.getAccessToken = function (bearerToken, callback) {
  db.hgetall(util.format(keys.token, bearerToken), function (err, token) {
if (err){console.log(err); return callback(err);}
        if (!token){ return callback();}
        callback(null, {
          accessToken: token.accessToken,
          clientId: token.clientId,
          expires: token.expires ? new Date(token.expires) : null,
          userId: token.userId
        });
      });
    };
model.getUserFromClient = function (clientId, clientSecret, callback) {
  db.hgetall(util.format(keys.client, clientId), function (err, client) {
    if (err) return callback(err);
    if (!client || client.clientSecret !== clientSecret) return callback();
    callback(null, {
      clientId: client.clientId,
      clientSecret: client.clientSecret
    });
  });
};
model.getRefreshToken = function (bearerToken, callback) {
  db.hgetall(util.format(keys.refreshToken, bearerToken), function (err, token) {
    if (err) return callback(err);
    if (!token) return callback();
    callback(null, {
      refreshToken: token.accessToken,
      clientId: token.clientId,
      expires: token.expires ? new Date(token.expires) : null,
      userId: token.userId
    });
  });
};
model.grantTypeAllowed = function (clientId, grantType, callback) {
  db.sismember(util.format(keys.grantTypes, clientId), grantType, callback);
};
model.saveAccessToken = function (accessToken, clientId, expires, user, callback) {
  db.hmset(util.format(keys.token, accessToken), {
    accessToken: accessToken,
    clientId: clientId,
    expires: expires ? expires.toISOString() : null,
    userId: user.id? user.id : ''
  }, callback);
};
model.saveRefreshToken = function (refreshToken, clientId, expires, user, callback) {
  db.hmset(util.format(keys.refreshToken, refreshToken), {
    refreshToken: refreshToken,
    clientId: clientId,
    expires: expires ? expires.toISOString() : null,
    userId: user.id? user.id: ''
  }, callback);
};
model.getUser = function (username, password, callback) {
  db.hgetall(util.format(keys.user, username), function (err, user) {
    if (err) return callback(err);
    if (!user || password !== user.password) return callback();
    callback(null, {
      id: username
    });
  });
};

Вам нужно только установить Redis на свой компьютер и запустить следующий файл

#! /usr/bin/env node
var db = require('redis').createClient();
db.multi()
//  .hmset('users:username', {
//    id: 'username',
//    username: 'username',
//    password: 'password'
//  })
  .hmset('clients:IphoneMobile', {
    clientId: 'IphoneMobile',
    clientSecret: 'password_shared_between_server_and_mobile_app'
  })
  .sadd('clients:IphoneMobile:grant_types', [ //You can choose your own set of credentials you want to be accessed by the frontend
    //password: frontend will request token via username and password
    'password',
    // refresh_token oauth will return a refresh_token and expire date will be used to refresh current user token after expiration
    'refresh_token'
  ])
  .exec(function (errs) {
    if (errs) {
      console.error(errs[0].message);
      return process.exit(1);
    }
    console.log('Client and user added successfully');
    process.exit();
  });

Примечание: этот файл будет запускаться только один или два раза, чтобы указать учетные данные для вашего внешнего интерфейса для запроса токена.

Запрос будет следующим:

Заголовок:

  1. авторизация: базовая, за которой следует пароль, установленный при первой настройке redis:

а. clientId + secretId для base64

  1. Форма данных:
  • имя пользователя: пользователь, который запрашивает токен
  • пароль: пароль пользователя
  • grant_type: в зависимости от того, какие параметры вы хотите, я выбираю пароль, который принимает только имя пользователя и пароль, которые будут созданы в redis, данные в redis будут такими, как показано ниже:
{
  "access_token":"1d3fe602da12a086ecb2b996fd7b7ae874120c4f",
  "token_type":"bearer", // Will be used to access api + access+token e.g. bearer 1d3fe602da12a086ecb2b996fd7b7ae874120c4f
  "expires_in":3600,
  "refresh_token":"b6ad56e5c9aba63c85d7e21b1514680bbf711450"
}

Итак, нам нужно вызвать наш api и получить некоторые защищенные данные с помощью нашего только что созданного токена доступа, см. Ниже:

когда срок действия токена истекает, api выдаст ошибку о том, что срок действия токена истекает, и у вас не будет доступа ни к одному из вызовов api, см. изображение ниже:

Давайте посмотрим, что делать, если срок действия токена истекает. Позвольте мне сначала объяснить это вам, если срок действия токена доступа истекает, в redis существует refresh_token, который ссылается на просроченный access_token Итак, нам нужно снова вызвать oauth / token с помощью refresh_token grant_type и установить авторизация на Basic clientId: clientsecret (до base 64!) и, наконец, отправка refresh_token, это сгенерирует новый access_token с новыми данными об истечении срока действия.

На следующем рисунке показано, как получить новый токен доступа:

[1]: https://redis.io/download
[2]: https://github.com/ServiceStack/redis-windows
[3]: https: / /redisdesktop.com/download
[4]: https://i.stack.imgur.com/8kn1X.png
[5]: https: //i.stack.imgur .com / D7TCi.png
[6]: https://i.stack.imgur.com/5C93O.png
[7]: https: //i.stack.imgur .com / ijnIf.png
[8]: https://i.stack.imgur.com/mECkH.png