-
-
Notifications
You must be signed in to change notification settings - Fork 113
Enhance authentication strategies with improved type safety and additional options #387
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
base: main
Are you sure you want to change the base?
Conversation
…support to extra authenticate options
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR enhances authentication strategies with improved type safety and additional options, making the authentication system more flexible and secure. The changes introduce a more strongly-typed approach to strategy configuration and callback handling.
- Refactored Strategy class to use
CallbackFunctioninstead ofVerifyFunctionwith better parameter naming - Redesigned Authenticator to accept a record of strategies at construction time with improved type inference
- Added support for strategies that accept additional authenticate method parameters
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/strategy.ts | Updated Strategy class with improved generics, callback function terminology, and support for extra authenticate parameters |
| src/strategy.test.ts | Removed existing test file (complete deletion) |
| src/index.ts | Completely refactored Authenticator class with constructor-based strategy registration and enhanced type safety |
| src/index.test.ts | Added new comprehensive tests demonstrating the enhanced API with form and login strategies |
| README.md | Updated documentation to reflect the new API design and improved examples |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated 10 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| set(state: string, verifier?: string) { | ||
| this.state = state; | ||
| this.codeVerifier = verifier; | ||
|
|
||
| this.states.add(state); | ||
| if (verifier) this.codeVerifiers.set(state, verifier); | ||
| } |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential race condition: The StateStore class uses instance properties state and codeVerifier that are set in the set() method and read in the toString() method. If multiple calls to set() happen before toString() is called, only the last set values will be serialized. This could be problematic in concurrent scenarios where multiple authentication flows are happening simultaneously.
However, looking at the usage in OAuth2Strategy, this appears to be intentional - each OAuth2 flow creates its own StateStore instance, and the instance properties track the "current" state being set. The class also maintains Sets and Maps for all states/verifiers. Consider adding documentation to clarify this design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
| toSetCookie( | ||
| cookieName = "oauth2", | ||
| options: Omit<SetCookieInit, "value"> = {}, | ||
| ) { | ||
| let id = crypto.randomUUID(); | ||
| return new SetCookie({ | ||
| value: this.toString(), | ||
| httpOnly: true, // Prevents JavaScript from accessing the cookie | ||
| maxAge: 60 * 5, // 5 minutes | ||
| path: "/", // Allow the cookie to be sent to any path | ||
| sameSite: "Lax", // Prevents it from being sent in cross-site requests | ||
| ...options, | ||
| name: `${cookieName}:${id}`, | ||
| }); |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The toSetCookie method generates a random UUID but never uses it for anything meaningful. The variable id is generated on line 84 but only used to construct the cookie name. However, this creates a unique cookie name every time toSetCookie is called, which means:
- Every call creates a new cookie with a different name
- Old cookies are never cleaned up
- The cookie name pattern
${cookieName}:${id}is used for retrieval infromRequest, but since a new UUID is generated each time, there's potential for cookie accumulation
Consider documenting this behavior or revising the approach to cookie naming.
| codeVerifier: string | undefined; | ||
|
|
||
| constructor(params = new URLSearchParams()) { | ||
| for (let [state, verifier] of params) { |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for skipping the "state" parameter in the constructor is unclear and potentially buggy. The code iterates over URLSearchParams entries and skips when state === "state", but this compares the key (first element of the tuple) with the string "state". This means if there's a parameter with key "state", it will be skipped. However, looking at the toString() method, it adds both params.set("state", this.state) and params.set(this.state, this.codeVerifier), so the "state" key is used as metadata. The skip logic should be documented or clarified with a comment explaining why "state" key entries are skipped.
| for (let [state, verifier] of params) { | |
| for (let [state, verifier] of params) { | |
| // The "state" key is used to store the current state value as metadata. | |
| // We skip it here to avoid treating it as a state-codeVerifier pair. |
|
@sergiodxa I've opened a new pull request, #401, to work on those changes. Once the pull request is ready, I'll request review from you. |
Improve type safety in authentication strategies, allowing for more flexible and secure user verification.
Also adds support for extra authenticate options defined by strategies.
This PR refactors the authentication system to provide better type safety and a more intuitive API:
Usertype with a more accurateSessionDatatypeAuthenticator.infer<typeof authenticator>verifytocallbackfor clarity and consistency