From 515cf93fc4ff354b4dbac95ee34b0280096f3dcb Mon Sep 17 00:00:00 2001 From: Johnny Date: Thu, 18 Dec 2025 15:33:56 +0800 Subject: [PATCH] fix(auth): enable RefreshToken endpoint for token renewal Two critical authentication fixes: 1. **MetadataInterceptor**: Forward Cookie header to gRPC metadata - RefreshToken extracts refresh token from cookie via metadata - Previously only User-Agent, X-Forwarded-For, X-Real-Ip were forwarded - Added cookie forwarding to enable token refresh flow 2. **ACL Configuration**: Add RefreshToken to PublicMethods - RefreshToken must be accessible when access token has expired - Without this, clients cannot refresh expired access tokens - Now properly listed as public endpoint alongside CreateSession These fixes enable the token refresh flow where clients can obtain new access tokens using their refresh token cookie without re-authenticating. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- server/router/api/v1/acl_config.go | 1 + server/router/api/v1/connect_interceptors.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/server/router/api/v1/acl_config.go b/server/router/api/v1/acl_config.go index 4569e82b9..e29af35ae 100644 --- a/server/router/api/v1/acl_config.go +++ b/server/router/api/v1/acl_config.go @@ -12,6 +12,7 @@ var PublicMethods = map[string]struct{}{ // Auth Service - login flow must be accessible without auth "/memos.api.v1.AuthService/CreateSession": {}, "/memos.api.v1.AuthService/GetCurrentSession": {}, + "/memos.api.v1.AuthService/RefreshToken": {}, // Token refresh must be accessible when access token expired // Instance Service - needed before login to show instance info "/memos.api.v1.InstanceService/GetInstanceProfile": {}, diff --git a/server/router/api/v1/connect_interceptors.go b/server/router/api/v1/connect_interceptors.go index d4781e37c..5af3d7b2b 100644 --- a/server/router/api/v1/connect_interceptors.go +++ b/server/router/api/v1/connect_interceptors.go @@ -43,6 +43,10 @@ func (*MetadataInterceptor) WrapUnary(next connect.UnaryFunc) connect.UnaryFunc if xri := header.Get("X-Real-Ip"); xri != "" { md.Set("x-real-ip", xri) } + // Forward Cookie header for authentication methods that need it (e.g., RefreshToken) + if cookie := header.Get("Cookie"); cookie != "" { + md.Set("cookie", cookie) + } // Set metadata in context so services can use metadata.FromIncomingContext() ctx = metadata.NewIncomingContext(ctx, md)