potato4d / nuxt-basic-auth-module

Provide basic auth your Nuxt.js application
https://www.npmjs.com/package/nuxt-basic-auth-module
MIT License
311 stars 9 forks source link

Add possibility to change basic auth credentials based on hostname / route or any custom condition #183

Closed Scoottykun closed 3 years ago

Scoottykun commented 3 years ago

Hey !

Would be nice to allow function for name & pass option. That way we would be able to adapt credentials for each route or each domain/subdomain if wanted (like in my use case).

I tried to do it myself the hard way like below, and it seems to be working like a charm :

middleware.js

const createMiddleware = options => {
  return (req, res, next) => {
    try {
      let enabled = true
      let match = options.match
      let name = options.name
      let pass = options.pass

      if (typeof name === 'function') {
          options.name = name(req)
      }

      if (typeof pass === 'function') {
          options.pass = pass(req)
      }

      if (typeof match === 'function') {
        enabled = match(req)
      }
      else if (match instanceof RegExp) {
        enabled = match.test(req.url)
      }
      else if (typeof match === 'string') {
        enabled = match === req.url 
      }

      if (!enabled || auth(options, req)) {
        return next()
      }
    } catch (e) {
      //
    }
    res.statusCode = 401
    res.setHeader('WWW-Authenticate', createBasicMessage(options))
    return res.end()
  }
}

nuxt.config.js

basic: {
        name({headers}){
            const currentHostname = headers['x-forwarded-host'] ? headers['x-forwarded-host'] : headers.host;
            switch (currentHostname) {
                case 'myhost.com':
                    return 'my_login'
                default:
                    return 'my_default_login';
            }
        },
        pass({headers}){
            const currentHostname = headers['x-forwarded-host'] ? headers['x-forwarded-host'] : headers.host;
            switch (currentHostname) {
                case 'myhost.com':
                    return 'my_password'
                default:
                    return 'my_default_password';
            }
        },
        match({headers}) {
            const enabledAuthHostnames = [
                'myhost.com',
                // ...
            ]
            const currentHostname = headers['x-forwarded-host'] ? headers['x-forwarded-host'] : headers.host;
            return enabledAuthHostnames.includes(currentHostname)
        }
}

Maybe my case is quite specific with the hostname conditions i added (i need to enable the basic Auth only on a few hostnames that my multisites application can hold), but it would at least give the choice for the developer to set whatever he want as condition within the function (route / domain / ...). As well as the current match option, the classic string format would still be the default usage of the options for the simple use case.

What do you think to this possible improvement ?

potato4d commented 3 years ago

thank you for your suggestion.

Sound good to me! Woud you implement and send pull request to this feature ?

Scoottykun commented 3 years ago

Just did a PR #185 :)

Scoottykun commented 3 years ago

Will not have the time any soon to add tests for full coverage, could you do it maybe ?

potato4d commented 3 years ago

Merged ~

potato4d commented 3 years ago

@Scoottykun I just finished publish package. Please download v1.4.0

potato4d commented 3 years ago

thanks!