Skip to content

eggjs-community/egg-passport-dingtalk

Repository files navigation

egg-passport-dingtalk

NPM version build status Test coverage David deps Known Vulnerabilities npm download

dingtalk passport plugin for egg

Install

$ npm i egg-passport egg-passport-dingtalk --save

Usage

// {app_root}/config/plugin.js
exports.passport = {
  enable: true,
  package: 'egg-passport'
}

exports.passportDingtalk = {
  enable: true,
  package: 'egg-passport-dingtalk',
};

Configuration

apply the app from https://open-dev.dingtalk.com/#/loginAndShareApp

// {app_root}/config/config.default.js
exports.passportDingtalk = {
    key: 'your-key',
    secret: 'your-secret',
    // default is /callback/dingtalk
    callbackURL: '/callback/dingtalk',
    // default is /passport/dingtalk
    loginURL: '/passport/dingtalk',
    oauthPageConfig: {
      title: 'your-dingtalk-oauth-page-title',
      logo: 'your-app-icon',
      slogan: 'your-app-slogan',
    },
    // Your custom dingtalk oauth page, if this is set, the default oauthPageConfig will be invalid
    customLoginURL: '/auth',    
};

see config/config.default.js for more detail.

// {app_root}/config/config.default.js
exports.passportDingtalk = {
};
key value note
key string required
secret string required
callbackURL string default is '/callback/dingtalk' optional
loginURL string default is '/passport/dingtalk' optional
oauthPageConfig.title string optional
oauthPageConfig.logo string optional
oauthPageConfig.slogan string optional
customLoginURL string optional
If this is set, then you should render the oauth page by yourself

Example

Login with dingtalk

// app/router.js
module.exports = app => {
  app.get('/', 'home.index');

  // authenticates routers
  app.passport.mount('dingtalk', app.config.passportDingtalk);
  // this is a passport router helper, it's equal to the below codes
  //
  // const dingtalk = app.passport.authenticate('dingtalk');
  // app.get('/passport/dingtalk', dingtalk);
  // app.get('/passport/dingtalk/callback', dingtalk);
};

Notice: The dingtalk is different with github or twitter, it need to be rendered by yourself. Luckily, we provide a nice default page for you.

Authenticate Requests

Usually, you could write a middleware to handle if a request need to be login, example will like below:

// app/router.js
module.exports = app => {
  app.get('/', app.middleware.needLogin(null, app), 'home.index');
};

About how to write a middleware, please refer this

// app/middleware/need-login.js
module.exports = (options, app) => {
  return async function needLogin (ctx, next) {
     const passportDingtalkConfig = app.config.passportDingtalk;
     if (!ctx.isAuthenticated()) {
       return ctx.redirect(passportDingtalkConfig.loginURL);
     }
     await next();   
  }
}

Then you visit the path '/', it will redirect you to the login page;

Integrated with DB verify or serializeUser

// app/router.js
module.exports = app => {
  app.get('/', 'home.index');

  // authenticates routers
  app.passport.mount('dingtalk', app.config.passportDingtalk);

  app.passport.verify(async (ctx, user) => {
    // find user from database
    //
    // Authorization Table
    // column   | desc
    // ---      | --
    // provider | provider name, like github, twitter, facebook, weibo and so on
    // uid      | provider unique id
    // user_id  | current application user id
    const auth = await ctx.model.Authorization.findOne({
      uid: user.id,
      provider: user.provider,
    });
    const existsUser = await ctx.model.User.findOne({ id: auth.user_id });
    if (existsUser) {
      return existsUser;
    }
    // call user service to register a new user
    const newUser = await ctx.service.user.register(user);
    return newUser;
  });
};

passport API supported

See https://github.com/eggjs-community/egg-passport#apis.

extent application

  • app.passport.mount(strategy, options): Mount the login and the login callback routers to use the given strategy.
  • app.passport.authenticate(strategy, options): Create a middleware that will authorize a third-party account using the given strategy name, with optional options.
  • app.passport.verify(handler): Verify authenticated user
  • app.passport.serializeUser(handler): Serialize user before store into session
  • app.passport.deserializeUser(handler): Deserialize user after restore from session

extend context

  • ctx.user: get the current authenticated user
  • ctx.isAuthenticated(): Test if request is authenticated
  • * ctx.login(user[, options]): Initiate a login session for user.
  • ctx.logout(): Terminate an existing login session

Questions & Suggestions

Please open an issue here.

License

MIT