-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question: How to test page behind authentication? #1418
Comments
Is this in the extension? Cookies should not be cleared, so you should stay logged in. If this is the CLI, you can run We do clear a lot of other things in storage, though, so more exotic forms of authentication may not work. |
Sorry, I should have specified that this is from the CLI. I'm trying to automate the process as much as possible so manual authentication will be a problem. Assuming nothing works out of the box, I'll try hacking at the gather source files. |
It shouldn't require hacking the gather files. How were you intending to authenticate in this workflow? If you were just going to manually authenticate in Chrome once and then reuse that browser repeatedly, that should still work. Lighthouse will talk to any Chrome launched with You'll probably want to launch Chrome with the other flags here as well to reduce noise due to extensions, prevent first run screen, etc. |
I don't intend on manually authenticating Chrome before the run. I'm leveraging Lighthouse for the performance monitoring so I want to do this at scale. |
I can see room for a "setCookie" command being added to the driver, probably very similar to the url blocking PR |
Can you explain how your workflow (current or intended) for authenticating in a CI or performance monitoring environment works? Happy to make this easier for folks doing this. |
I'll take a stab at that. For example: I want to perf test the loading of drive.google.com with a very active account, and watch this for regressions. Would need to set cookies on the run configuration because the browser is otherwise a clean slate. To me it seems to be similar to the scripting capabilities of WebPageTest, where things like custom cookies can be set: https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/scripting |
Right, sorry, I understood that part :) my question was about how authentication like this is normally handled (or intended to be handled) in this kind of monitoring situation. |
@paulirish SetCookie would be nice. Thinking about it a bit more, SetHeaders might be more generic providing a mechanism for basic auth as well. |
I poked around a bit. It looks like there isn't a mechanism for setting cookies in the Chromium API. But there is a mechanism for setting arbitrary headers. driver.js setExtraHTTPHeaders(jsonHeaders) {
let headers;
try {
headers = JSON.parse(jsonHeaders);
} catch(e) {
log.warn('Driver', 'Invalid extraHeaders JSON');
headers = {};
}
return this.sendCommand('Network.setExtraHTTPHeaders', {
headers
});
} gather-runner.js .then(_ => driver.clearDataForOrigin(options.url))
.then(_ => driver.setExtraHTTPHeaders(options.flags.extraHeaders || '{}'))
.then(_ => driver.blockUrlPatterns(options.flags.blockedUrlPatterns || [])); Invoking node node_modules/lighthouse/lighthouse-cli http://localhost:8080 --disable-device-emulation --disable-network-throttling --perf --extra-headers="{\"Authorization\":\"Basic YWRtaW46YWRtaW4=\"}" I was able to send a basic authorization header which allowed me authenticated access. The JSON configuration via the CLI is gross but it works. |
@fdn looks like devtools has https://chromedevtools.github.io/debugger-protocol-viewer/tot/Network/#method-setCookie |
@wardpeet That's much more convenient than constructing the cookie header manually. 👍 Is there anything I can do to help this functionality get implemented? |
Any update on this issue? is there a way to do it in the 2.0.0 version? I need to test an authenticated page from CLI. |
I never submitted a pull request since the API is quite gross. You might be able to cherry pick my commit into your local... or use the commit from above 2f54c0e https://github.com/fdn/lighthouse/commits/feature/new-flags |
Just a comment, if you're using basic authentication, you can run lighthouse this way:
|
#2599 uses a combination of localStorage and cookies for auth too Rather than trying to craft specific logic in Lighthouse it might make more sense to make the artifactless custom gatherer story a little easier and allow users to put their arbitrary setup code in the beforePass there. |
@patrickhulce sounds like a good idea, perhaps we should add an example in how it would work and just refer to that example, people will have to create a custom config but might be good enough. Most people can have the --cookie option which most people use for auth anyway |
Any updates on this? Or do you know of an external tool that'll help us do this? We really want to set up lighthouse reporting as part of our CI pipeline, but all our important pages are behind cookie authentication. |
@unindented, Hey! I'd seen this thread and didn't want to jump in promote my product, but seeing as you asked reasonably directly, it seems more ok to do so. Calibre runs lighthouse and allows you to create 'test profiles'. A test profile can: Alter the bandwidth, emulate a mobile device and set cookies for authentication. There's also an option to use form-based authentication too, if that's easier. |
Is another possible path to achieving testability of pages/sites/apps that require login to allow passing the name of a Chrome profile to Lighthouse or the Chrome Launcher? I have a test profile that is intended to maintain cookies, local storage, cache, etc. and has no extensions installed. If Lighthouse could be launched with a flag like This doesn't appear to be the same as #2291, which seems to create the same empty profile in a user-writable location so it can be later deleted. Of course, my idea would also require not deleting the profile afterward (which seems to be the default for Chrome Launcher). |
@runlevelsix thanks for the suggestion! That method is already mostly supported by virtue of the fact that you can launch chrome with the profile you need before running Lighthouse and then passing the port that your instance is running on to Lighthouse. |
I think it's just a question of how many chrome-launcher flags we want to also expose on lighthouse. If using lighthouse as a module you can just pass in |
@unindented yeah, I basically did the same thing when I was using Backstop. I feel like that's decent approach since it will x-module / testing framework. |
Similar approach to @unindented, but we were already using Nightmarejs, so I used that instead of puppeteer: import Nightmare from 'nightmare';
import lighthouse from 'lighthouse';
import chai from 'chai';
import { get } from 'lodash';
const performanceOnlyConfig = require('lighthouse/lighthouse-core/config/perf.json');
const lhConfig = { port: 5858, output: 'json' };
const nightmareConfig = {
switches: {
'--remote-debugging-port': 5858 // to match debut port passed to lighthouse
},
}
const nightmare = Nightmare(nightmareConfig);
let results
describe('Performance', () => {
before(async function () {
this.retries(3);
const pathToTest = 'some/path'
// Navigate to path using nightmare
await nightmare.goto(pathToTest);
// Call lighthouse performance audit tool
results = await lighthouse(pathToTest, lhConfig, performanceOnlyConfig);
});
after(async () => {
await nightmare.end();
});
it('First Meaningful Paint less than 10 seconds', () => {
chai.expect(get(results, 'audits.first-meaningful-paint.rawValue'))
.to.be.below(10000);
});
}); |
Here is a way on how to use puppeteer, which you could use to login first. https://github.com/GoogleChrome/lighthouse/blob/master/docs/puppeteer.md |
Is there a way to use the lighthouse extension to test a PWA which stores the auth credentials in localstorage? Or do I have to change it so that the credentials are stored in the cookies for it to work? |
@gdavalos unfortunately not able to use the extension if kept in localStorage, but you can use DevTools with clear storage off. |
@patrickhulce you mean the nodejs lib? do you have an example of that? |
Oh I was talking about the DevTools panel in Chrome actually, but the CLI works too. CLI /path/to/chrome --remote-debugging-port=9222 # login to your app
lighthouse --port=9222 --disable-storage-reset https://url-to-your-app.com Node lighthouse('https://my-url.com', {port: 9222, disableStorageReset: true}) |
At the very least we need documentation. DevTools users can use "preserve storage" and CLI users can workaround this awkwardly. |
In case it's useful for documenting a workaround for CLI users -- I have a use case where there are a couple auth-token kinda things in const Gatherer = require('lighthouse').Gatherer;
const puppeteer = require('puppeteer');
class Authenticate extends Gatherer {
async beforePass(options) {
const ws = await options.driver.wsEndpoint();
const browser = await puppeteer.connect({
browserWSEndpoint: ws,
});
const page = await browser.newPage();
await page.goto(process.env.TEST_URL);
await page.click('input[name=username]');
await page.keyboard.type(process.env.USER);
await page.click('input[name=password]');
await page.keyboard.type(process.env.PASSWORD);
// sign in button
await page.click('span[class^=Section__sectionFooterPrimaryContent] button');
// this means the login succeeded
await page.waitForSelector('.dashboard');
browser.disconnect();
return {};
}
}
module.exports = Authenticate; A couple things I came across that might be worth noting for this kind of setup:
|
Thanks for sharing @stuartsan! That is an interesting use of a gatherer. It begs for us to implement a "before" hook. So I understand better, could you describe the limitations you have that prevent a solution like the one described here? It seems that if writing a custom audit works for you, then writing a custom launcher for Lighthouse instead could also work for you. |
@hoten, sure thing! I think I definitely could write a custom launcher instead, but the context around why I preferred this setup in my project:
So doing a custom launcher instead wouldn't be a big deal, it's just more convenient and feels a little more standardized, or something, to me, to be able to stick with calling Also, if my observations around lighthouse(options.url, { port: options.debugPort, disableStorageReset: true }, null); But then it seems like I'd be back to the wrongly inflated perf score, because it wasn't considered a "perf run" and my authenticated page (which is the same url that shows the login form when not logged in) was cached. (If that's right, maybe this is avoidable through clearing the cache before puppeteer hands the page off, but IDK). Overall I think it's more convenient to be able to preserve the standard way of launching via CLI and also be able to hook in and do some general setup, but I get that it might not be LH's responsibility to support that use case :) A more general "before" hook would be super sweet IMO. |
@prescottprue I am trying to use lighthouse in nightmare , I got below error, Do you have any solution for this issue? need your help .thanks so much. |
We now have great documentation and a working example on how to handle these situations: https://github.com/GoogleChrome/lighthouse/blob/master/docs/authenticated-pages.md fixed by #9628 |
I found that authentication is cleared when requesting a page. It makes sense however when testing an app behind authentication it doesn't seem like there is a way to specify an authorization header or cookie to be used.
Reference issue: #592
Any tips on how I can test a page that is behind authentication?
UPDATE (LATEST METHOD): The best way to currently do this is to load your authenticated page in DevTools, uncheck the "Clear storage" checkbox, and run Lighthouse.
The text was updated successfully, but these errors were encountered: