Jay
Jay

Reputation: 9477

NodeJS RADIUS OTP authentication

I am trying to implement RADIUS OTP authentication in NodeJS. I could not find much information and if it's at all possible. NodeJS: https://www.npmjs.com/package/radius Any directions would be very helpful.

I have implemented the same on Java platform using CAS RADIUS and that work fine. CAS: https://apereo.github.io/cas/6.0.x/mfa/RADIUS-Authentication.html#

Upvotes: 1

Views: 2897

Answers (2)

Simon Tretter
Simon Tretter

Reputation: 21

Maybe a little late, but you can easily extend node-radius-server to cope with OTP.

Upvotes: 0

Michael Hobbs
Michael Hobbs

Reputation: 1693

Here is some information and guidance.

Is it possible? Yes.

Nodejs Radius Package: https://www.npmjs.com/package/radius Nodejs OTP Package: https://www.npmjs.com/package/otplib

Example of using the radius package for OTP: https://github.com/mcguinness/simple-radius-server

You should be able to fork the example and modify it to use the OTP package to generate the OTP tokens.

Another possibility would be to deploy FreeIPA in a docker container and then use ldapjs to auth against the FreeIPA container from node. See code below for an example of how to do auth against FreeIPA using ldapjs.

const LDAP = require('ldapjs');

class LDAPAuth {
    constructor({url, base, uid}) {
        this.errorCount = 0
        setInterval(()=>this.errorCount = 0, 10000)
        let self = this
        function createLdap() {
            self.ldap = LDAP.createClient({url})
                .on('error', (error)=> {
                    console.error('Error in ldap',error)
                    self.errorCount++
                    if (self.errorCount > 20) {
                        console.error('Too many errors! Giving up...')
                        process.exit()
                    } else {
                        createLdap()
                    }
                })
        }
        createLdap()
        this.base = base
        this.uid = uid
    }

    authenicate({username, password, count = 0}) {
        let dn = `${this.uid}=${username},${this.base}`
        if (count > 5) {
            return Promise.reject('Failed to authenticate with LDAP!')
        }
        return new Promise((resolve, reject)=> {
            this.ldap.bind(dn, password, (err, res) => {
                if (err) {
                    if (err && err.stack && err.stack.indexOf(`${this.url} closed`) > -1) {
                        count++
                        // wait 1 second to give the ldap error handler time to reconnect
                        return setTimeout(()=>resolve(this.authenicate({username, password})), 2000)
                    }
                    console.error('ldap error', err)
                    reject(err)
                }
                if (res) resolve()
                else reject()
            })
        })

    }
}

module.exports = LDAPAuth

note: The code example has issues and I would not write it this way now but has been functioning well for a few years now so not going to touch it unless a need arises.

Upvotes: 2

Related Questions