How to integrate node-sspi?

Hi there!

How can i integrate node-sspi https://github.com/abbr/nodesspi in the framework?

Best wishes,
René

1 Like

hi,
tries to create middleware and check nodeSSPIObj.authenticate

See: https://adonisjs.com/docs/4.1/middleware

It works! Thank you so much!!! :+1:

1 Like

hi @rbartholomay, may I know how you managed to make this work? I tried using Middlewares, but it crashes the app upon reaching nodeSSPIObj.authenticate().

Thanks.

this is my code i used, perhaps it helps… :slightly_smiling_face:

'use strict'

/*
 * adonis-middleware-sspi (Security Support Provider Interface)
 * (https://docs.microsoft.com/en-us/windows/desktop/SecAuthN/sspi)
 *
 * (c) 2019 René Bartholomay <rene.bartholomay@gmx.de>
 *
 * Module SSPI - Copyright (c) 2014-present, @abbr (MIT)
 * https://github.com/abbr/nodesspi
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
*/


/** @typedef {import('@adonisjs/framework/src/Request')} Request */
/** @typedef {import('@adonisjs/framework/src/Response')} Response */
/** @typedef {import('@adonisjs/framework/src/View')} View */


const Config  = use('Config')

const debug   = require('debug')('adonis:sspi')
const GE      = require('@adonisjs/generic-exceptions')

/**
 *
 */
const nodeSSPI  = require('node-sspi')



class Sspi {

  /**
   *
   */
  constructor () {
    this._nodeSSPIObj = new nodeSSPI({

      offerSSPI: Config.get('sspi.offerSSPI', true),

      offerBasic: Config.get('sspi.offerBasic', true),

      authoritative: Config.get('sspi.authoritative', true),

      perRequestAuth: Config.get('sspi.perRequestAuth', false),

      retrieveGroups: Config.get('sspi.retrieveGroups', false),

      maxLoginAttemptsPerConnection: Config.get('sspi.maxLoginAttemptsPerConnection', 3),

      sspiPackagesUsed: Config.get('sspi.sspiPackagesUsed', ['NTLM']),

      domain: Config.get('sspi.domain', undefined)
    })
  }

  /**
   * @param {object} ctx
   * @param {Function} next
   * @param {object} properties
   */
  async handle (ctx, next, properties) {
    const me = this;

    debug('attempting to request sspi header(s)')

    /**
     * map the nodejs native request, response object
     *
     * https://adonisjs.com/docs/4.1/request
     * The Node.js raw req object can be accessed via request.request.
     *
     * https://adonisjs.com/docs/4.1/response
     * The Node.js raw res object can be accessed as response.response.
     *
     */
    const req = ctx.request.request
    const res = ctx.response.response


    return await new Promise( (resolve, reject) => {
      me._nodeSSPIObj.authenticate(req, res, function(err) {
        if (err) {
          reject(err)
        }

        if (ctx.sspi) {
          throw new GE.HttpException(`there is already an sspi object`, 500, 'E_SSPI_CONFIG')
        }

        ctx.sspi = {
          user    : req.connection.user,
          groups  : req.connection.userGroups || null,
          sid     : req.connection.userSid
        }

        /**
         * Sharing user with the auth
         */
        if (ctx.auth && typeof (ctx.auth.share) === 'function') {
          ctx.auth.share({
            sspi: ctx.sspi
          })
        }

        resolve( res.finished || next() )
      })
    })
  }
}

module.exports = Sspi

1 Like

This is cool, thanks!