-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Intro
Hello, I'm not sure if this is an issue but I spend way more time than I thought I was going to spend trying to make authentication work for my project that uses a custom login flow. I managed to make it work but it took me adding several steps that were not in your documentation. I might missed or misunderstood how to implement it so that's why I'm creating this issue, so you can tell me if I got something wrong or if there's really a good opportunity to improve the codebase and documentation.
First steps
First let me start saying I read your Playwright global setup doc to implement authentication in my project. I really liked the performOAuthSetup function, even though you use a lot of configuration options I think all of them are necessary; sadly this didn't work for me because, like I said, I had a custom login flow where the password was not showing alongside the username text input, I first show the username input, then a button to continue and it loads another page to show the username and password input.
I moved on with the Custom Login Flow which seemed like the ideal solution for me case but I quickly noticed that it differs a lot from what performOAuthSetup does to authenticate because you don't use the PlaywrightOAuthClientProvider there. Anyways, I followed the steps from the Custom Login Flow section and it was not working for me. You have a comment saying: "The provider handles PKCE, state management, token exchange, and storage." in your code example but it wasn't doing any of that.
Questions I had when trying to make it work using your way
It was not a surprise for me because I didn't know how you do the connection between the provider and the custom browser flow
- How do I generate the authorization URL so I can start the login flow in the Playwright browser?
- How do you generate the tokens from the authorization code that I got from the browser flow?
- How can I feed the tokens to the provider so they can be saved in the storage path?
- Also, for the browser flow (and this might be out of scope but it's worth mention it I think) how can I grab the authorization code if I don't have a server running for the redirect URI? do I need to run a separate server so the browser loads something and Playwright doesn't close the browser context when redirecting to it?
My solution
I had these issues and questions that were not clear how to solve them using your documentation so what I did to solve everything was like a combination of performOAuthSetup code combined with PlaywrightOAuthClientProvider.
You can see how the code looks like here
A brief explanation of the code
I first created a new instance for PlaywrightOAuthClientProvider with the required configurations, then I pretty much copy and paste a lot of the code used in performOAuthSetup to generate the authorization URL (Discover OAuth authorization server metadata, generates PKCE, builds auth URL using functions from the @modelcontextprotocol/sdk).
I did my custom login flow using the Playwright browser; since I didn't want it to run a server for the redirect URI what I did was intercept the request before it was loaded and grab the URL with the authorization code.
With the authorization code I exchanged it for tokens and feed the tokens to the provider using await provider.saveTokens(tokens).
Final thoughts
I know this was a long read and I appreciate if you made it to here. My final thoughts are:
- Do you think I overly complicated something that was way simpler?
- If I did, Where did I go wrong and how did I misunderstood your documentation?
- Do you think there's room for improvement? I think you nailed it with performOAuthSetup so I think it would be cool to add a new configuration option that accepts a function that handles to custom login flow instead of using PlaywrightOAuthClientProvider for that case because that's what pretty much broke the deal with performOAuthSetup for me.
- What about the redirection URI thing? do I really need a server running to make the redirection work? how do you guys do it?
Anyways I'm open to your thoughts and also open to contribute to the project if you guys need help.