Skip to content

Enhance authentication strategies with improved type safety and additional options - #387

Open
sergiodxa wants to merge 28 commits into
mainfrom
type-safety
Open

Enhance authentication strategies with improved type safety and additional options#387
sergiodxa wants to merge 28 commits into
mainfrom
type-safety

Conversation

@sergiodxa

@sergiodxa sergiodxa commented Oct 9, 2025

Copy link
Copy Markdown
Owner

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

Copilot AI left a comment

Copy link
Copy Markdown

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.

Comment thread src/index.ts Outdated
@sergiodxa
sergiodxa requested a review from Copilot October 10, 2025 04:28

Copilot AI left a comment

Copy link
Copy Markdown

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.

Copilot AI left a comment

Copy link
Copy Markdown

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.

Comment thread src/strategies/oauth2.ts Outdated
Comment thread src/strategies/oauth2.ts
Comment thread src/strategies/oauth2.ts Outdated
Comment thread src/strategies/oauth2.test.ts Outdated
sergiodxa and others added 2 commits November 12, 2025 01:51
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

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 thread src/lib/state-store.ts Outdated
Comment thread src/lib/state-store.ts
Comment thread src/strategies/oauth2.ts Outdated
Comment thread src/index.ts Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread src/strategies/oauth2.ts Outdated
Comment thread src/lib/state-store.ts Outdated
Comment thread src/strategies/oauth2.ts
Comment thread README.md

This comment was marked as resolved.

Copilot AI left a comment

Copy link
Copy Markdown

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 13 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/index.ts
get strategies(): Readonly<{
[K in keyof StrategyRecord]: Omit<StrategyRecord[K], "authenticate">;
}> {
return this.#strategies;

Copilot AI Dec 10, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The strategies getter returns a type that omits the authenticate method from each strategy, but the actual implementation returns this.#strategies which still contains the authenticate method. This creates a type mismatch where the runtime object has more methods than the type indicates. Either the return type should not omit authenticate, or the getter should return a mapped object that actually omits it.

Suggested change
return this.#strategies;
// Return a mapped object omitting 'authenticate' from each strategy
return Object.freeze(
Object.fromEntries(
Object.entries(this.#strategies).map(([key, strategy]) => {
// Omit 'authenticate' using destructuring
const { authenticate, ...rest } = strategy as any;
return [key, rest];
}),
),
) as Readonly<{
[K in keyof StrategyRecord]: Omit<StrategyRecord[K], "authenticate">;
}>;

Copilot uses AI. Check for mistakes.
Comment thread src/strategies/oauth2.ts
}

/**
* Options that can be defined at athentication time to override the default

Copilot AI Dec 10, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word "athentication" is misspelled. It should be "authentication".

Suggested change
* Options that can be defined at athentication time to override the default
* Options that can be defined at authentication time to override the default

Copilot uses AI. Check for mistakes.
Comment thread src/strategies/oauth2.ts

private get cookieName() {
if (typeof this.options.cookie === "string") {
return this.options.cookie || "oauth2";

Copilot AI Dec 10, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in this getter has a bug. When this.options.cookie is an empty string "", the expression this.options.cookie || "oauth2" will return "oauth2" instead of using the empty string. If you intend to allow empty strings as cookie names, use nullish coalescing instead. If empty strings should fall back to the default, this is correct but potentially confusing. Consider using this.options.cookie || "oauth2" only when the value is explicitly falsy (not just empty string), or document this behavior clearly.

Suggested change
return this.options.cookie || "oauth2";
return this.options.cookie ?? "oauth2";

Copilot uses AI. Check for mistakes.
Comment thread src/strategies/oauth2.ts
}

private get cookieOptions() {
if (typeof this.options.cookie !== "object") return {};

Copilot AI Dec 10, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition typeof this.options.cookie !== "object" will be true when this.options.cookie is null, since typeof null === "object" in JavaScript. This means when cookie is null, you'll return an empty object instead of checking the nullish case properly. Consider using if (typeof this.options.cookie !== "object" || this.options.cookie === null) or restructure the logic to handle null explicitly.

Suggested change
if (typeof this.options.cookie !== "object") return {};
if (typeof this.options.cookie !== "object" || this.options.cookie === null) return {};

Copilot uses AI. Check for mistakes.
Comment thread src/lib/state-store.ts Outdated
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.

3 participants