Skip to content

Comments

Replace fosite with native OAuth implementation and quality fixes#40

Merged
dgellow merged 1 commit intomainfrom
sam/native-oauth-and-quality
Feb 14, 2026
Merged

Replace fosite with native OAuth implementation and quality fixes#40
dgellow merged 1 commit intomainfrom
sam/native-oauth-and-quality

Conversation

@dgellow
Copy link
Member

@dgellow dgellow commented Feb 14, 2026

Replaces the fosite OAuth library with a native implementation that's simpler, has fewer dependencies, and gives us full control over the token flow. Also includes quality improvements found during review:

  • Fix SSE proxy content-type check to handle parameters (charset=utf-8)
  • Fix data race on package-level logger variable in log package
  • Deduplicate log level parsing and LogWithFields helpers
  • Change GenerateSecureToken to return error instead of empty string

Replaces the fosite OAuth library with a native implementation that's
simpler, has fewer dependencies, and gives us full control over the
token flow. Also includes quality improvements found during review:

- Fix SSE proxy content-type check to handle parameters (charset=utf-8)
- Fix data race on package-level logger variable in log package
- Deduplicate log level parsing and LogWithFields helpers
- Change GenerateSecureToken to return error instead of empty string
@dgellow dgellow enabled auto-merge (squash) February 14, 2026 19:49
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @dgellow, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request undertakes a significant architectural shift by replacing the existing 'fosite' OAuth library with a custom-built native OAuth 2.0 implementation. This change aims to simplify the codebase, reduce external dependencies, and offer greater flexibility and control over the OAuth token lifecycle, including authorization code, access token, and refresh token flows. Complementing this core refactoring, several quality improvements were integrated, addressing a data race in the logging system, refining log level parsing, enhancing secure token generation with explicit error handling, and fixing a content-type parsing issue in the SSE proxy.

Highlights

  • Native OAuth Implementation: The external 'fosite' library has been replaced with a custom, native OAuth 2.0 authorization server, significantly reducing external dependencies and providing granular control over the authentication and token issuance processes.
  • Improved Logging Infrastructure: The internal logging package was refactored to resolve a data race condition, deduplicate log level parsing logic, and streamline the use of structured logging helpers, enhancing the reliability and maintainability of logging.
  • Enhanced Secure Token Generation: The 'GenerateSecureToken' function now returns an error in addition to the generated token, allowing for more robust error handling when cryptographic randomness generation fails.
  • SSE Proxy Content-Type Fix: A bug in the SSE proxy's content-type check was resolved, enabling it to correctly parse media types that include parameters, such as 'text/event-stream; charset=utf-8'.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • go.mod
    • Removed the 'github.com/ory/fosite' dependency.
    • Removed numerous indirect dependencies previously required by 'fosite'.
  • go.sum
    • Updated dependency hashes to reflect the removal of 'fosite' and its transitive dependencies.
  • internal/config/unmarshal.go
    • Updated comments for 'RefreshTokenScopes' to clarify its behavior within the new native OAuth implementation.
  • internal/crypto/csrf.go
    • Updated the call to 'GenerateSecureToken' to correctly handle its new error return value.
  • internal/crypto/random.go
    • Modified 'GenerateSecureToken' to return an error upon failure to generate random bytes.
    • Removed internal logging calls, propagating errors instead.
    • Removed the import of the internal log package.
  • internal/inline/handler.go
    • Updated the call to 'crypto.GenerateSecureToken()' to handle its new error return value.
  • internal/log/log.go
    • Removed the package-level 'logger' variable to prevent data races and ensure direct use of 'slog.Default()'.
    • Extracted log level parsing logic into a new 'parseLevel' function for deduplication.
    • Updated 'SetLogLevel' to utilize the new 'parseLevel' function.
    • Refactored all 'Log*' and 'Log*WithFields' functions to use 'slog.Default()' and a new 'buildArgs' helper, reducing redundant code.
  • internal/mcpfront.go
    • Removed the 'fosite' import.
    • Updated the 'setupAuthentication' function signature to return the new native 'oauth.AuthorizationServer'.
    • Updated the 'buildHTTPHandler' function signature to accept the new native 'oauth.AuthorizationServer'.
    • Removed various redundant comments and references to 'fosite'.
    • Configured 'minStateEntropy' for the new 'AuthorizationServer' based on development mode.
    • Updated 'oauth.NewValidateTokenMiddleware' to integrate with the new native 'AuthorizationServer'.
  • internal/oauth/authz.go
    • Added a new file implementing the native OAuth Authorization Server, including core logic for authorization, token issuance, and validation.
  • internal/oauth/authz_test.go
    • Added comprehensive unit tests for the new native OAuth Authorization Server, covering various flows and error conditions.
  • internal/oauth/client_val.go
    • Added a new file defining the 'Client' interface and helper functions for validating client-related parameters like redirect URIs and secrets.
  • internal/oauth/errors.go
    • Added a new file defining custom OAuth error codes, a structured 'OAuthError' type, and utility functions for writing standardized error responses.
  • internal/oauth/grant.go
    • Added a new file defining data structures for OAuth authorization grants and parameters.
  • internal/oauth/pkce.go
    • Added a new file implementing PKCE (Proof Key for Code Exchange) verification logic.
  • internal/oauth/pkce_test.go
    • Added unit tests for the PKCE verification implementation.
  • internal/oauth/provider.go
    • Removed 'fosite' imports and related code.
    • Removed the 'NewOAuthProvider' function, replaced by the new native 'AuthorizationServer' constructor.
    • Updated 'NewValidateTokenMiddleware' to integrate with the new native 'AuthorizationServer' type.
  • internal/oauth/provider_test.go
    • Updated tests to reflect the removal of 'NewOAuthProvider' and the introduction of 'NewAuthorizationServer'.
  • internal/oauth/token.go
    • Added a new file defining structures for access token claims, refresh token claims, and the standard OAuth token response format.
  • internal/server/auth_handlers.go
    • Updated the 'AuthHandlers' struct and its constructor to use the new native 'oauth.AuthorizationServer'.
    • Modified 'ClientMetadataHandler' to use 'storage.GetClient' and handle 'storage.ErrClientNotFound'.
    • Refactored 'AuthorizeHandler' to leverage the new native OAuth logic for request validation and code issuance.
    • Refactored 'IDPCallbackHandler' to use 'oauth.AuthorizeParams' and the new OAuth error handling utilities.
    • Refactored 'handleOAuthClientCallback' to integrate with the new native OAuth logic.
    • Rewrote 'TokenHandler' to implement OAuth token exchange and refresh token flows using the native authorization server and storage mechanisms.
    • Updated 'signUpstreamOAuthState' to accept 'oauth.AuthorizeParams'.
    • Refactored 'CompleteOAuthHandler' to use the new native OAuth logic for issuing codes and storing grants.
  • internal/server/auth_handlers_test.go
    • Updated tests for OAuth authentication handlers to align with the new native OAuth implementation.
  • internal/server/http_test.go
    • Updated HTTP server tests to reflect the integration of new OAuth components.
  • internal/server/middleware.go
    • Adjusted 'generateBrowserState' to correctly handle potential errors returned by 'crypto.GenerateSecureToken'.
  • internal/server/sse_proxy.go
    • Corrected the 'Content-Type' header parsing logic in the SSE proxy to properly handle media type parameters.
  • internal/session/session.go
    • Removed 'fosite'-specific session structures, simplifying the session management.
  • internal/storage/client.go
    • Removed 'fosite.Client' conversion methods.
    • Implemented the new native OAuth 'Client' interface methods.
    • Added a 'clone()' method to ensure client data isolation in memory storage.
  • internal/storage/firestore.go
    • Removed 'fosite' imports and its storage interface implementation.
    • Added a new 'grantsCollection' constant for storing authorization codes.
    • Removed embedding of 'storage.MemoryStore'.
    • Removed the in-memory 'stateCache' as authorize requests are now stored in Firestore.
    • Updated 'GetClient' to return a native 'Client' type and handle 'ErrClientNotFound'.
    • Removed 'GetClientWithMetadata'.
    • Added 'StoreGrant' and 'ConsumeGrant' methods for managing authorization codes in Firestore.
    • Updated error handling to use 'ErrClientNotFound' and 'ErrGrantNotFound'.
    • Added 'encodeJSON' and 'decodeJSON' helper functions for serializing 'idp.Identity'.
  • internal/storage/memory.go
    • Removed 'fosite' imports and its storage interface implementation.
    • Removed embedding of 'storage.MemoryStore'.
    • Removed the in-memory 'stateCache'.
    • Added a 'grants' map and 'grantsMutex' for in-memory storage of 'oauth.Grant' objects.
    • Updated 'GetClient' to return a native 'Client' type and return a cloned copy for data isolation.
    • Removed 'GetClientWithMetadata'.
    • Added 'StoreGrant' and 'ConsumeGrant' methods for managing authorization codes in memory.
  • internal/storage/memory_test.go
    • Updated memory storage tests to reflect the removal of 'MemoryStore' embedding.
  • internal/storage/storage.go
    • Removed 'fosite' import.
    • Added new error types: 'ErrClientNotFound' and 'ErrGrantNotFound'.
    • Removed the 'fosite.Storage' interface from the main 'Storage' interface.
    • Removed 'StoreAuthorizeRequest' and 'GetAuthorizeRequest' methods.
    • Updated the 'GetClient' method signature.
    • Removed 'GetClientWithMetadata'.
    • Added 'StoreGrant' and 'ConsumeGrant' methods to the 'Storage' interface for native OAuth grant management.
    • Removed comments related to 'fosite' specific storage requirements.
  • internal/storage/storage_test.go
    • Added new tests for native OAuth grant management and client data isolation in storage.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request is a major and impressive refactoring that replaces the fosite OAuth library with a simpler, native implementation. This gives the project more control and reduces dependencies significantly. The new implementation is well-structured, with clear separation of concerns and a comprehensive test suite that provides confidence in its correctness.
In addition to the OAuth replacement, this PR includes several valuable quality improvements:

  • A fix for a data race in the logging package by removing a global logger variable.
  • Deduplication of logging logic, improving maintainability.
  • A more robust SSE content-type check.
  • Improved error handling in GenerateSecureToken by returning an error instead of an empty string.

The overall quality of the changes is very high. I have one suggestion for improvement in internal/storage/memory.go regarding session cleanup when a user is deleted.

Comment on lines 227 to 242
func (s *MemoryStorage) DeleteUser(ctx context.Context, email string) error {
s.usersMutex.Lock()
defer s.usersMutex.Unlock()

delete(s.users, email)

// Also delete all user tokens
s.userTokensMutex.Lock()
defer s.userTokensMutex.Unlock()

prefix := email + ":"
for key := range s.userTokens {
if strings.HasPrefix(key, prefix) {
delete(s.userTokens, key)
}
}
s.userTokensMutex.Unlock()

s.usersMutex.Lock()
delete(s.users, email)
s.usersMutex.Unlock()

return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The DeleteUser function successfully removes the user and their associated tokens, but it overlooks revoking the user's active sessions. This could leave orphaned sessions that remain active until they expire, which might be a security concern. It would be more robust to also iterate through active sessions and remove any belonging to the deleted user.

func (s *MemoryStorage) DeleteUser(ctx context.Context, email string) error {
	s.userTokensMutex.Lock()
	prefix := email + ":"
	for key := range s.userTokens {
		if strings.HasPrefix(key, prefix) {
			delete(s.userTokens, key)
		}
	}
	s.userTokensMutex.Unlock()

	s.sessionsMutex.Lock()
	for id, session := range s.sessions {
		if session.UserEmail == email {
			delete(s.sessions, id)
		}
	}
	s.sessionsMutex.Unlock()

	s.usersMutex.Lock()
	delete(s.users, email)
	s.usersMutex.Unlock()

	return nil
}

@dgellow dgellow merged commit dfb5bbd into main Feb 14, 2026
2 checks passed
@dgellow dgellow deleted the sam/native-oauth-and-quality branch February 14, 2026 19:53
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.

1 participant