Skip to content

feat(auth): add post-auth hook mechanism#1527

Open
HEUDavid wants to merge 9 commits intorouter-for-me:devfrom
HEUDavid:feat/auth-hook
Open

feat(auth): add post-auth hook mechanism#1527
HEUDavid wants to merge 9 commits intorouter-for-me:devfrom
HEUDavid:feat/auth-hook

Conversation

@HEUDavid
Copy link

Summary

This PR introduces a PostAuthHook mechanism that allows developers to intercept and modify authentication records before they are saved to disk. This is particularly useful for injecting metadata derived from the HTTP request (such as headers or query parameters) into the auth record, which can then be used for routing or policy enforcement.

Changes

  • SDK: Added PostAuthHook function type and RequestInfo struct to sdk/cliproxy/auth.
  • Server: Added WithPostAuthHook option to ServerOption to allow registering a hook at startup.
  • Management API: Updated Handler and auth_files.go to execute the registered hook when creating or updating auth files, passing RequestInfo extracted from the Gin context.
  • Providers: Updated token generation logic in all providers (Claude, Codex, Gemini, iFlow, Kimi, Qwen) to support the new flow and ensure context is propagated.

Use Case

This feature enables scenarios where auth credentials need to be tagged with specific attributes (e.g., user ID, Client, origin, usage plan) present in the registration request headers or query parameters.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @HEUDavid, 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 introduces a flexible post-authentication hook system, allowing for dynamic modification of authentication records based on incoming HTTP request details. This enhancement facilitates advanced scenarios such as tagging credentials with specific attributes like user IDs or usage plans, which can then be leveraged for routing or policy enforcement within the system.

Highlights

  • Post-Authentication Hook Mechanism: Introduced a PostAuthHook mechanism that allows developers to intercept and modify authentication records before they are saved to disk, enabling injection of metadata derived from HTTP requests.
  • Request Information Struct: Added a RequestInfo struct to sdk/cliproxy/auth to capture query parameters and headers from HTTP requests, which can be passed to the post-auth hook.
  • Server Option for Hook Registration: Implemented a WithPostAuthHook option for ServerOption to allow registering the post-auth hook during server startup.
  • Management API Integration: Updated the Management API's Handler and auth_files.go to execute the registered PostAuthHook when creating or updating authentication files, passing the extracted RequestInfo.
  • Provider Token Generation Updates: Modified token generation logic across all authentication providers (Claude, Codex, Gemini, iFlow, Kimi, Qwen) to support the new metadata injection flow and ensure context propagation.

🧠 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
  • internal/api/handlers/management/auth_files.go
    • Added logic to execute the postAuthHook before saving token records, handling potential errors from the hook.
    • Introduced PopulateAuthContext function to extract query parameters and headers from gin.Context and add them to the Go context.
    • Integrated PopulateAuthContext into all token request handlers (Anthropic, Gemini, Codex, Antigravity, Qwen, Kimi, iFlow) to ensure request information is available in the context.
  • internal/api/handlers/management/handler.go
    • Added a postAuthHook field of type coreauth.PostAuthHook to the Handler struct.
    • Implemented SetPostAuthHook method to register the post-authentication hook on the handler.
  • internal/api/server.go
    • Added postAuthHook field to serverOptionConfig struct.
    • Created WithPostAuthHook function to provide a ServerOption for configuring the post-authentication hook.
    • Modified NewServer to set the postAuthHook on the management handler if provided in the server options.
  • internal/auth/claude/token.go
    • Added a Metadata field (unexported to JSON) to ClaudeTokenStorage to hold arbitrary key-value pairs.
    • Implemented SetMetadata method to allow external callers to inject metadata.
    • Updated SaveTokenToFile to use misc.MergeMetadata for flattening the Metadata into the JSON output.
  • internal/auth/codex/token.go
    • Added a Metadata field (unexported to JSON) to CodexTokenStorage.
    • Implemented SetMetadata method.
    • Updated SaveTokenToFile to use misc.MergeMetadata for flattening the Metadata into the JSON output.
  • internal/auth/gemini/gemini_token.go
    • Added a Metadata field (unexported to JSON) to GeminiTokenStorage.
    • Implemented SetMetadata method.
    • Updated SaveTokenToFile to use misc.MergeMetadata for flattening the Metadata into the JSON output and added JSON indentation.
  • internal/auth/iflow/iflow_token.go
    • Added a Metadata field (unexported to JSON) to IFlowTokenStorage.
    • Implemented SetMetadata method.
    • Updated SaveTokenToFile to use misc.MergeMetadata for flattening the Metadata into the JSON output.
  • internal/auth/kimi/token.go
    • Added a Metadata field (unexported to JSON) to KimiTokenStorage.
    • Implemented SetMetadata method.
    • Updated SaveTokenToFile to use misc.MergeMetadata for flattening the Metadata into the JSON output.
  • internal/auth/qwen/qwen_token.go
    • Added a Metadata field (unexported to JSON) to QwenTokenStorage.
    • Implemented SetMetadata method.
    • Updated SaveTokenToFile to use misc.MergeMetadata for flattening the Metadata into the JSON output.
  • internal/misc/credentials.go
    • Imported the encoding/json package.
    • Added MergeMetadata function to serialize a source struct and merge additional metadata into a map, respecting JSON tags.
  • sdk/auth/filestore.go
    • Defined a private metadataSetter interface.
    • Modified the Save method to check if the auth.Storage implements metadataSetter and, if so, call SetMetadata with the auth.Metadata.
  • sdk/cliproxy/auth/types.go
    • Imported the context package.
    • Defined PostAuthHook function type for intercepting and modifying Auth records.
    • Defined RequestInfo struct to hold HTTP request query parameters and headers.
  • sdk/cliproxy/builder.go
    • Added WithPostAuthHook method to the Builder to allow configuring the post-authentication hook via the SDK builder.
Activity
  • No specific activity (comments, reviews, or progress updates) has been recorded for this pull request yet.
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 introduces a post-authentication hook mechanism, which is a great feature for extensibility. The implementation is mostly solid, but I've found a couple of areas for improvement.

My main concern is the use of context.Background() in the token request handlers, which detaches the asynchronous operations from the request's lifecycle. I've suggested using c.Request.Context() to ensure proper cancellation propagation.

Additionally, I've provided suggestions to improve the PopulateAuthContext function to handle multi-value headers/parameters correctly and to use a typed context key, which is a Go best practice.

@HEUDavid
Copy link
Author

@luispater 你好,已经对 AI 的建议都做出回应,请 CR 代码。

@luispater
Copy link
Collaborator

@luispater 你好,已经对 AI 的建议都做出回应,请 CR 代码。

能否给我详细解释一下这个PR的应用场景是什么?我理解不了它的应用场景。

@HEUDavid
Copy link
Author

HEUDavid commented Feb 10, 2026

@luispater 你好,已经对 AI 的建议都做出回应,请 CR 代码。

能否给我详细解释一下这个PR的应用场景是什么?我理解不了它的应用场景。

@luispater

我用代码来说明:

  1. 注册对 auth-flie 操作的 Hook 方法
		WithPostAuthHook(func(ctx context.Context, auth *coreauth.Auth) error {
			// Extract RequestInfo from context
			if info := coreauth.GetRequestInfo(ctx); info != nil {
				log.Printf("PostAuthHook: Injected Metadata for %s", auth.ID)
				log.Printf("Request Headers: %+v", info.Headers)
				log.Printf("Request Query: %+v", info.Query)
				auth.Metadata["AAA"] = "AAA"
				auth.Metadata["BBB"] = "BBB"
				if key := info.Headers["X-Management-Key"]; key != "" {
					if auth.Metadata == nil {
						auth.Metadata = make(map[string]any)
					}
					auth.Metadata["X-Management-Key"] = key
				}
			}
			return nil
		}).
		Build()
  1. 调用 oauth 认证流程,用户认证成功之后:
2026/02/10 23:11:49 PostAuthHook: Injected Metadata for qwen-1770736309056.json
2026/02/10 23:11:49 Request Headers: map[Accept-Encoding:gzip User-Agent:Go-http-client/1.1 X-Management-Key:CCC]
2026/02/10 23:11:49 Request Query: map[is_webui:true]
time="2026-02-10T23:11:49+08:00" level=info msg="auth file changed (CREATE): qwen-1770736309056.json, processing incrementally"

auth-file 中会额外记录Metadata, 当前代码在各类型的 provider 中是 hardcode 操作 email 等那些信息,没有拓展能力。没有充分利用您定义的Metadata字段

	// Attributes stores provider specific metadata needed by executors (immutable configuration).
	Attributes map[string]string `json:"attributes,omitempty"`
	// Metadata stores runtime mutable provider state (e.g. tokens, cookies).
	Metadata map[string]any `json:"metadata,omitempty"`
{
  "AAA": "AAA",
  "BBB": "BBB",
  "X-Management-Key": "CCC",
  "access_token": "",
  "email": "1770736309056",
  "expired": "2026-02-11T05:11:49+08:00",
  "last_refresh": "2026-02-10T23:11:49+08:00",
  "refresh_token": "",
  "resource_url": "portal.qwen.ai",
  "type": "qwen"
}

本 PR 提供一个接口来操作 auth-file, 可以灵活拓展 auth-file 属性,甚至操作 auth-file 文件名等。可以更容易地把启动 oauth 流程的用户属性与其 auth-file 直接绑定起来,类似 SAAS 服务中单实例多租户场景。

@luispater luispater changed the base branch from main to dev February 11, 2026 10:57
@HEUDavid
Copy link
Author

@luispater 你好,还有其他问题吗?或者还需要我做其他调整吗?

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