node-radius-server icon indicating copy to clipboard operation
node-radius-server copied to clipboard

Google IMAP App specific Password

Open BWilky opened this issue 1 year ago • 8 comments

[IMAPAuth] imap auth failed Error: Application-specific password required: https://support.google.com/accounts/answer/185833 (Failure)

Has anyone come up with a work around for this? I'd like to whitelist this radius server

BWilky avatar May 22 '23 19:05 BWilky

Yeah,just create an App specific password.https://support.google.com/mail/answer/185833?hl=en-GB

simllll avatar May 22 '23 20:05 simllll

@simllll How do I get this to work for all the users without them all creating app specific passwords? We're on nonprofit G suite so LDAP isn't an option

BWilky avatar May 22 '23 20:05 BWilky

I guess there is no way around an app specific password, if you don't want to use ldap ... Maybe you can apply for some program at Google if your are eligible for non profit things?

simllll avatar May 22 '23 20:05 simllll

Damn, that's too bad. I've tried looking into asking google for LDAP access, no luck. Thanks!

BWilky avatar May 22 '23 20:05 BWilky

So I managed to actually get this to work. I created a express server that uses node.js puppeteer to login with a headless chrome instance. It actually works really really well with the Http auth function

BWilky avatar May 23 '23 05:05 BWilky

Haha creative solution ;-) do you want to share the headless login code?

simllll avatar May 23 '23 06:05 simllll

Outside of this, I've used a endswith checker to make sure it's from the correct domain.

Known issues would be 2FA accounts, no work-around for that.


class GoogleAuth {
  async login(email, password) {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    let navigationPromise = page.waitForNavigation();

    const timer = setTimeout(() => {
      console.log('Login attempt timed out');
      browser.close();
      return false;
    }, 10000); // Set timeout to 10 seconds

    await page.goto('https://accounts.google.com/');
    await navigationPromise;

    await page.waitForSelector('input[type="email"]');
    await page.type('input[type="email"]', email);

    await page.waitForSelector('#identifierNext');
    await page.click('#identifierNext');

    await page.waitForSelector('input[type="password"]', { visible: true });
    await page.type('input[type="password"]', password);

    await page.waitForSelector('#passwordNext', { visible: true });
    await page.click('#passwordNext');

    try {
      await Promise.race([
        page.waitForNavigation(), // Wait for navigation
        page.waitForFunction('document.body.innerText.includes("Wrong password")'), // Wait for "Wrong password" text
        new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 10000)) // Set timeout
      ]);
    } catch (error) {
      console.log('An error occurred while waiting for navigation or "Wrong password" text');
      await browser.close();
      return false;
    }

    const url = await page.url();
    const loginFailed = url.includes('signin');

    clearTimeout(timer);

    await browser.close();

    return !loginFailed;
  }
}

BWilky avatar May 23 '23 16:05 BWilky

@simllll

Right now I got it to work with two node apps, the radius, and then an express app. I noticed at the bottom of the readme there's a how to include radius server in another app. I can't seem to get that sample code going. Is it possible to run radius server in a custom node file with custom function for auth?

BWilky avatar May 23 '23 16:05 BWilky