storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.04k stars 9.24k forks source link

Secure the main view #5193

Closed chulanovskyi closed 5 years ago

chulanovskyi commented 5 years ago

Is it possible to have any sort of authorization to the Storybook, for example to create initial login page (simple name&pass component) and wrap the main Storybook app with it to ensure that user have an access to the view.

I've been searching for any examples or at least a described approach how it could be achieved, but found none. I thought that it might be at the addons - still no luck.

sensone commented 5 years ago

Me also interested this question

chulanovskyi commented 5 years ago

The question remains opened

chulanovskyi commented 5 years ago

Don't close

ndelangen commented 5 years ago

@chulanovskyi If you're creating a static build the security should be provided on a hosted level.

If you're running a dev server, we could add some login, but that's a little out of scope for what it is: a dev setup.

Having said that, We have made improvements to make the dev-server more composable "under the hood" and so if we up the documentation you'll likely be able to wrap storybook's dev server with another express server which has auth fairly easily.

Improving docs is high on my priority list. So it's coming.

stale[bot] commented 5 years ago

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

stale[bot] commented 5 years ago

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

evankellogg commented 4 years ago

Hello, was the documentation ever updated to show to how wrap the dev server in a separate express server?

chulanovskyi-bs commented 4 years ago

@evankellogg I've just looked through their new fancy guides, and guess what - not a single word about security, neither at main docs...

ndelangen commented 4 years ago

We assume the dev server is used development on someone's local machine and that will never be made public.

We assume the static build could be hosted anywhere, and pretty much all hosting platforms have some way to add a basic auth to a folder or something.

Here's our start-dev script: https://github.com/storybookjs/storybook/blob/next/lib/core/src/server/build-dev.js

This is where it's used in a framework app: https://github.com/storybookjs/storybook/blob/next/app/react/src/server/index.ts

Vadorequest commented 3 years ago

I'm wondering how to do that with Vercel, is there any example?

My Next.js app isn't behind a basic-auth, but I'd like our Storybook static site to be protected.

dvago commented 3 years ago

Same here, it would really appreciated to add some either documentation or support to authentication within the static build via 3rd party services (e.g. AWS Cognito/Appsync) without relying on node servers (or any other servers)

Vadorequest commented 3 years ago

Maybe this could be implemented as a plugin?

Maybe it could be some passwordless auth, like allowing a list of domains in Storybook config and being prompted about our email and that'd send an email if it belongs to the allowed domains.

chulanovskyi-bs commented 3 years ago

@ndelangen Hi! Could you please re-open this issue, 'cause it seems like there are still some gaps in the documentation regarding this topic? Thanks!

randak commented 3 years ago

I think most of the people commenting in this thread here have missed the point that @ndelangen is making above.

A Storybook build is a static site. It has no backend. Therefore, you cannot add auth directly in the storybook code itself—you've already sent all the assets to the client so any authentication you put in place could be trivially circumvented. This is no different than if you wanted to protect your application's JS bundle from unauthenticated access.

If you want to add authentication it needs to be in whatever layer serves your Storybook (such as a reverse proxy like nginx or some sort of API service). You can add basic auth or IP-based access restrictions to a reverse proxy layer as a simple access control mechanism. Anything else you would need to build yourself, but it seems out of scope for Storybook to support.

dvago commented 3 years ago

@randak what are you saying? static web apps (like storybook) can get auth mechanisms to prevent accessing certain content/route without need of reverse proxy :/

Since the Webpack bundle provides a compressed and obfuscated version of your source it is quite tricky to say "could be trivially circumvented". Not sure but it seems last few years of the frenzy around "static sites coupled and re-hydrated with data via API, JAM stack" didn't reach your attention.

What people, here, are asking is the possibility to inject an initial default route which provides the possibility to authenticate and an hook in each requested route to check if your client has the rights to access it.

randak commented 3 years ago

Sorry if I'm misunderstanding you. Your storybook assets are still on a public route in this scenario, right? I guess it depends on what level of protection you are looking for. I don't mean to imply that Storybook couldn't offer some protection here, but if the goal is to prevent access to your documentation, obfuscation alone wouldn't really help you with that since the text has to be preserved in the output.

dvago commented 3 years ago

Your storybook asset by definition is what you get out from the build:storybook script which generates storybook-static a folder which you can serve in whatever directory you like (e.g. public/dist).

If you look at the content of storybook-static is not a simple bunch of html files but a fully JS driven application with a couple of HTML placeholders, there is no way you can just affirm "I can easily reach a page and download the text/html" as all the pages are virtually generated by the output of this SPA, said so the above comment and the requests made by all the developers in this thread are totally legit.

randak commented 3 years ago

I know it's not just a bunch of HTML files 😓

Admittedly, I've never tried to put authentication on a truly static site, so I may be unaware of some technique here, but how is your initial route supposed to load the other JS files without having their paths to those files contained somewhere within the JS code? Setting aside obfuscation, how are you protecting the discovery of those paths? Or is it just obfuscation?

If you're suggesting that the JS files are themselves on authentication-protected paths, well, I don't see how that's any different than what I'm suggesting. Something in your server is protecting those assets, and I don't see why it would matter in that case if the auth check was built into the storybook or part of a completely separate login page.

(By the way, the reason I'm on this thread in the first place is because I also want to protect my Storybook from the public internet, so by all means, please prove me wrong! I just don't quite see it yet.)

dvago commented 3 years ago

So, as mentioned above the world SPA should give an idea on how you prevent to get fully functional Storybook to download and use in your local environment/elsewhere. Your components "reacts" and render to certain conditions, if you don't have such requirements (e.g. a valid token) you can't actually render data nor download content from a mock service (e.g. chart components that fetch mock data in order to render). Storybook pages are virtual routes driven by JS logic, as per any JS modern framework you might have a router which talks to an API using tokens and then decides to generate the code to display a specific route or send you to a fallback.

Removing all these checks it's quite tricky if your bundle is compressed and obfuscated, you really need to be extremely motivated and an extreme amount of time to get the needle out of the haystack.

I think we are not going anywhere with this thread as the task is Closed and it's now more than 2 years since @chulanovskyi raised it.

randak commented 3 years ago

Ah, it seems we're talking past each other.

In my case, my concern is not about someone decompiling and rendering my JS components; it is about the descriptive content surrounding the components—the text that explains what the components are for, how to use them, and potentially business-sensitive information that shouldn't be on the open internet. That kind of content can usually be more easily extracted from a bundle since it won't be mangled and compressed to the same extent, which is why I said that it depends on what level of protection you're looking for. For me, I'd rather not ever serve that documentation publicly to begin with, and so my recommendation is based on that.

I'm not affiliated with Storybook, so I can't speak to their openness for adopting a solution here. But it seems like you may be able to do something with custom Webpack config that would satisfy your basic requirements.

dvago commented 3 years ago

Indeed, having an authentication system within Storybook could permit you to serve these business-sensitive info via API.

Serving these descriptions via API could give you an extra scope of such as"permit non-dev people to edit/review/publish via a 3rd dashboard/CMS" (that's just me expanding your needs).

In general, as bare minimum usage of Storybook as "list of live components within a UI where devs can browse and copy paste snippets" it can have totally sense requesting a "plugin" or some support to the Storybook team to provide a login route and a check within each route for valid authenticated user.

randak commented 3 years ago

Personally, serving descriptions via API that I would normally write in MDX files sounds far more onerous than just having auth from my server. That destroys all the convenience of Storybook's documentation approach.

If you really want an official authentication solution from Storybook, I imagine the real answer is "use Chromatic". The basic tier is free, and it supports access control according to the docs. I've never used it before, but that does seem to be the Storybook team's answer to this ticket.

I have no further stake in this conversation, so I'm checking out. I hope you find what you're looking for.

dvago commented 3 years ago

What probably the author and I were looking for is the comment above, no sensitive description involved, just the possibility to serve components across multiple devs having a login system so not everyone can render and control them via Storybook UI.

Chromatic is not the answer as it involves your code to be deployed into a 3rd party service/hosting (Chroma Software, Inc).

I think the discussion did last quite too much and as mentioned above I don't think Storybook contributors will ever take in consideration anything related to "auth plugin" as this issue has been closed and no one gave actual support since 2019.

shilman commented 3 years ago

As @randak explained above, it's just not secure. And there are secure methods available on the server. Chromatic is one example, but you can easily set it up yourself. Those solutions are actually secure, so why would we want to put in extra work to create and maintain something that's worse than the existing solution that doesn't require any change to Storybook?

Vadorequest commented 3 years ago

How would you implement an authentication system when your Storybook static site is hosted on Vercel?

Maybe there are better alternatives to strong authentication than building something in Storybook itself, but if that's the case, then maybe there is a lack of example/documentation about those.

At this time, I'd like to protect my storybook static site hosted on Vercel and I don't know how to do that. Could a tutorial be made? It should probably work similarly for any static site host provider. (Vercel, ...)

ndelangen commented 3 years ago

This seems like an answer from vercel, on how to do that: https://vercel.com/support/articles/how-do-i-add-password-protection-to-my-vercel-deployment?query=password It does require a paid tier it seems.

Netlify has a similar feature here: https://docs.netlify.com/visitor-access/password-protection/

Vadorequest commented 3 years ago

Yeah, it costs $150/month min (on top of the cost of the Pro plan itself). https://vercel.com/docs/platform/projects#password-protection

shijujckl commented 12 months ago

We are hosting the storybook as a static site in Azure blob storage. Is it possible to add Octa login to access the storybook for Organization users?

AJ-7885 commented 11 months ago

I am hosting static version of my storybook on Github page, but I like to protected with Organization SSO as it is required for my company, I did implement the MASL , https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/4282 But still only protected only preview section and menu and reset of section is visible. and I am looking for a way to protect whole section.

GAAOPS commented 8 months ago

Yeah, it costs $150/month min (on top of the cost of the Pro plan itself). https://vercel.com/docs/platform/projects#password-protection

If you are interested, I have secured the storybook with basic auth on the hobby account of vercel using a simple node express middleware. With this approach, you can secure the storybook on any kind of hosting:

https://www.ashournia.com/basic-authentication-for-storybook/ https://github.com/GAAOPS/storybook-basic-auth

TomIshiyama commented 1 week ago

In my case, I installed the staticrypt dependency and built a static site for Storybook with a password lock. I run the scripts after building Storybook.

I added staticrypt to the devDependencies in package.json and included a command in the scripts section. The command looks like this:

"build:storybook-crypt": "yarn staticrypt ./dist-storybook/index.html --directory ./dist-storybook",

Then, I ran the following command:

yarn build-storybook && yarn build:storybook-crypt