Coder Social home page Coder Social logo

userauth's Introduction

koa-userauth

NPM version

koa user auth abstraction layer middleware.

Install

npm install koa-userauth

Usage

koa-userauth is dependent on koa-session or koa-generic-session.

var koa = require('koa');
var userauth = require('koa-userauth');
var session = require('koa-generic-session');

var app = new koa();
app.keys = ['i m secret'];

app.use(session());
app.use(userauth({
  match: '/user',
  // auth system login url
  loginURLFormatter: function (url) {
    return 'http://login.demo.com/login?redirect=' + url;
  },
  // login callback and getUser info handler
  getUser: async ctx => {
    var token = this.query.token;
    // get user
    return user;
  }
}));

Arguments

If options.match or options.ignore is String instance, we will use path-match transfer it to Regex instance.

/**
 * User auth middleware.
 *
 * @param {Object} [options]
 *  - {String|Regex|Function(pathname, ctx)} match, detect which url need to check user auth.
 *      `''` empty string meaning match all, @see `path-match` package.
 *  - {String|Regex|Function(pathname, ctx)} ignore, detect which url no need to check user auth.
 *      If `match` exists, this argument will be ignored.
 *  - {Function(url, rootPath, ctx)} loginURLFormatter, format the login url.
 *  - {String} [rootPath], custom app url root path, default is '/'.
 *  - {String} [loginPath], default is '/login'.
 *  - {String} [loginCallbackPath], default is `options.loginPath + '/callback'`.
 *  - {String} [logoutPath], default is '/logout'.
 *  - {String} [userField], logined user field name on `this.session`, default is 'user', `this.session.user`.
 *  - {Async Function (ctx)} getUser, get user function, must get user info with `req`.
 *  - {Async Function (ctx, user)} [loginCallback], you can handle user login logic here,return [user, redirectUrl]
 *  - {Function(ctx)} [loginCheck], return true meaning logined. default is `true`.
 *  - {Async Function (ctx, user)} [logoutCallback], you can handle user logout logic here.return redirectUrl
 *  - {Function(ctx)} [getRedirectTarget], customize how to get the redirect target after login
 * @return {Async Function (next)} userauth middleware
 * @public
 */

Login flow

  1. unauth user, redirect to $loginPath?redirect=$currentURL
  2. user visit $loginPath, redirect to options.loginURLFormatter() return login url.
  3. user visit $loginCallbackPath, handler login callback logic.
  4. If user login callback check success, will set req.session[userField], and redirect to $currentURL.
  5. If login check callback error, next(err).
  6. user visit $logoutPath, set req.session[userField] = null, and redirect back.

userauth flow

Source image file

License

MIT

userauth's People

Contributors

cyjake avatar dead-horse avatar denghongcai avatar fengmk2 avatar hustxiaoc avatar mahnunchik avatar moldauder avatar ngot avatar popomore avatar snyk-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

userauth's Issues

回跳URL中不允许包含/login

function formatReferer(ctx, pathname, rootPath) {
  var query = ctx.query;
  var referer = query.redirect || ctx.get('referer') || rootPath;
  if (referer[0] !== '/') {
    // ignore protocol://xxx/abc
    referer = rootPath;
  } else if (referer.indexOf(pathname) >= 0) {
    referer = rootPath;
  }
  return referer;
}

其中referer.indexOf(pathname) >= 0是否应该改为referer.startsWith(pathname)更加合适?
因回跳的url中可能会包含/login字符串,这种情况会引起误判。

有循环重定向的可能

if (!this.session) {
      debug('this.session not exists');
      // ignore not match path
      if (!loginRequired) {
        debug('not match needLogin path, %j', this.path);
        return yield next;
      }
      debug('relogin again');
      return yield loginHandler.call(this, next);
    }

    // get login path
    if (this.path === options.loginPath) {
      debug('match login path');
      return yield loginHandler.call(this, next);
    }

场景:

loginPath=/login
loginHost=demo.xxx.com
浏览器中输入demo.xxx.com/login (带有部分cookie),这是就能跳过第一个判断if (!this.session)
而 if (this.path === options.loginPath) 符合条件!
最终就会执行到loginHandler 的 redirect(this, loginURL);
@fengmk2

[feat] fetch get json request return 403 not 302

Describe the feature

When we use fetch to get json data from server,userauth return 302 with redirect url。Fetch will throw TypeError: failed to fetch caused by cors error. It's better to throw 403 with login expired message to make frontend do the re-login easily.

needLogin判断逻辑纠正

return function* userauth(next) {
    var loginRequired = !!needLogin(this.path, this);
    debug('url: %s, path: %s, loginPath: %s, session exists: %s, login required: %s',
      this.url, this.path, options.loginPath, !!this.session, loginRequired);

    if (!this.session) {
      debug('this.session not exists');
      // ignore not match path
      if (!loginRequired) {
        debug('not match needLogin path, %j', this.path);
        return yield* next;
      }
      debug('relogin again');
      return yield* loginHandler.call(this, next);
    }

if (!this.session) 这个判断逻辑能否改成

if (!loginRequired) {
      debug('not match needLogin path, %j', this.path);
      return yield* next;
    } else if (loginRequired && !this.session) {
      debug('this.session not exists');
      debug('relogin again');
      return yield* loginHandler.call(this, next);
    }

因为needLogin这个判断逻辑本身就是让业务方自己去判断是否要走登录校验,如果这里加了只允许已经登录过的逻辑才能走进来,就不太合理了。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.