docs: function setupResourceServer(app, options, models) {
  
      function checkAccessToken(req, accessToken, done) {
          debug('Verifying access token %s', accessToken);
          models.AccessTokens.find(accessToken, function (err, token) {
              if (err || !token) {
                  return done(err);
              }
  
              debug('Access token found: %j', token);
  
              if (isExpired(token)) {
                  return done(new TokenError('Access token is expired',
                      'invalid_grant'));
              }
  
              var userId = token.userId || token.resourceOwner;
              var appId = token.appId || token.clientId;
  
              var user, app;
              async.parallel([
                  function lookupUser(done) {
                      if (userId == null) {
                          return process.nextTick(done);
                      }
                      models.Users.find(userId, function (err, u) {
                          if (err) {
                              return done(err);
                          }
                          if (!u) {
                              return done(
                                  new TokenError('Access token has invalid user id: ' +
                                      userId, 'invalid_grant'));
                          }
                          debug('User found: %s', userInfo(u));
                          user = u;
                          done();
                      });
                  },
                  function lookupApp(done) {
                      if (appId == null) {
                          return process.nextTick(done);
                      }
                      models.Clients.find(appId, function (err, a) {
                          if (err) {
                              return done(err);
                          }
                          if (!a) {
                              return done(
                                  new TokenError('Access token has invalid app id: ' + appId,
                                      'invalid_grant'));
                          }
                          debug('Client found: %s', clientInfo(a));
                          app = a;
                          done();
                      });
                  }], function (err) {
                  if (err) {
                      return done(err);
                  }
                  if (options.addHttpHeaders) {
                      var prefix = 'X-OAUTH2-';
                      if (typeof options.addHttpHeaders === 'string') {
                          prefix = options.addHttpHeaders;
                      }
                      if (appId != null) {
                          req.headers[prefix + 'CLIENT-ID'] = appId;
                      }
                      if (userId != null) {
                          req.headers[prefix + 'USER-ID'] = userId;
                      }
                  }
                  var authInfo =
                  {accessToken: token, user: user, app: app, client: app};
                  done(null, user || {}, authInfo);
              });
          });
      }
  
      var verifyAccessToken = checkAccessToken;
      if (typeof options.checkAccessToken === 'function') {
          verifyAccessToken = options.checkAccessToken;
      }
  
      function accessTokenValidator(req, accessToken, done) {
          verifyAccessToken(req, accessToken, function (err, user, info) {
              if (!err && info) {
                  req.accessToken = info.accessToken;
              }
              done(err, user, info);
          });
      }
  
      /**
       * BearerStrategy
       *
       * This strategy is used to authenticate users based on an access token (aka a
       * bearer token).  The user must have previously authorized a client
       * application, which is issued an access token to make requests on behalf of
       * the authorizing user.
       */
      passport.use('copress-oauth2-bearer',
          new BearerStrategy({passReqToCallback: true}, accessTokenValidator)
      );
  
      passport.use('copress-oauth2-mac',
          new MacStrategy({passReqToCallback: true, jwtAlgorithm: 'HS256'},
              function (req, accessToken, done) {
                  accessTokenValidator(req, accessToken, function (err, user, info) {
                      if (err || !user) {
                          return done(err, user, info);
                      }
                      var client = info && info.client;
                      var secret = client.clientSecret || client.restApiKey;
                      try {
                          var token = jwt.verify(accessToken, 'HS256', secret);
                          debug('JWT token verified: %j', token);
                      } catch (err) {
                          debug('Fail to verify JWT: %j', err);
                          done(err);
                      }
                      done(null, user, info);
                  });
              })
      );
  
      /**
       * Return the middleware chain to enforce oAuth 2.0 authentication and
       * authorization
       * @param {Object} [options] Options object
       * - scope
       * - jwt
       */
      function authenticate(options) {
          options = options || {};
  
          var authenticators = [
              passport.authenticate(['copress-oauth2-bearer', 'copress-oauth2-mac'],
                  options)];
          if (options.scopes || options.scope) {
              authenticators.push(scopeValidator(options));
          }
          authenticators.push(oauth2Provider.errorHandler());
          return authenticators;
      }
  
      return authenticate;
  }