Skip to content

Conversation

@sergiodxa
Copy link
Owner

@sergiodxa sergiodxa commented Oct 9, 2025

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:

  • Replaces the generic User type with a more accurate SessionData type
  • Introduces a new constructor pattern that accepts a record of strategies
  • Adds support for passing extra parameters to strategy authenticate methods
  • Provides type inference utilities via Authenticator.infer<typeof authenticator>
  • Renames verify to callback for clarity and consistency
  • Updates documentation with modern TypeScript patterns and examples
  • Removes the need to manually define session data types

@sergiodxa sergiodxa requested a review from Copilot October 9, 2025 22:24
@sergiodxa sergiodxa self-assigned this Oct 9, 2025
Copy link

Copilot AI left a 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 CallbackFunction instead of VerifyFunction with 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.

@sergiodxa sergiodxa requested a review from Copilot October 10, 2025 04:28
Copy link

Copilot AI left a 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.

@sergiodxa sergiodxa requested a review from Copilot November 12, 2025 06:46
Copilot finished reviewing on behalf of sergiodxa November 12, 2025 06:48
Copy link

Copilot AI left a 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.

@sergiodxa sergiodxa requested a review from Copilot November 12, 2025 06:54
Copilot finished reviewing on behalf of sergiodxa November 12, 2025 06:58
Copy link

Copilot AI left a 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.

Comment on lines +40 to +46
set(state: string, verifier?: string) {
this.state = state;
this.codeVerifier = verifier;

this.states.add(state);
if (verifier) this.codeVerifiers.set(state, verifier);
}
Copy link

Copilot AI Nov 12, 2025

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.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

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

Comment on lines +80 to +93
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}`,
});
Copy link

Copilot AI Nov 12, 2025

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:

  1. Every call creates a new cookie with a different name
  2. Old cookies are never cleaned up
  3. The cookie name pattern ${cookieName}:${id} is used for retrieval in fromRequest, 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.

Copilot uses AI. Check for mistakes.
codeVerifier: string | undefined;

constructor(params = new URLSearchParams()) {
for (let [state, verifier] of params) {
Copy link

Copilot AI Nov 12, 2025

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.

Suggested change
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.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI commented Nov 12, 2025

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants