-
Notifications
You must be signed in to change notification settings - Fork 154
feat: Add SPNEGO Authentication Middleware #1368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 6 commits
db1c1b7
8a1aa70
b795161
4f314bd
5197bf6
952aaf6
ef3cd2d
ba84250
45ce4a3
e04e024
d428340
000d40e
c798b96
c32cc18
80fa4dc
eb40e2c
12bd868
e0a550c
40c9876
b773b0b
b3b33d1
4d1c990
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,198 @@ | ||||||||||||||
| --- | ||||||||||||||
| id: spnego | ||||||||||||||
| --- | ||||||||||||||
|
|
||||||||||||||
| # SPNEGO Kerberos Authentication Middleware for Fiber | ||||||||||||||
|
|
||||||||||||||
|  | ||||||||||||||
| [](https://gofiber.io/discord) | ||||||||||||||
|  | ||||||||||||||
|
|
||||||||||||||
| This middleware provides SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) authentication for [Fiber](https://github.com/gofiber/fiber) applications, enabling Kerberos authentication for HTTP requests and inspired by [gokrb5](https://github.com/jcmturner/gokrb5) | ||||||||||||||
|
|
||||||||||||||
| [中文版本](README.zh-CN.md) | ||||||||||||||
|
|
||||||||||||||
| ## Features | ||||||||||||||
|
|
||||||||||||||
| - Kerberos authentication via SPNEGO mechanism | ||||||||||||||
| - Flexible keytab lookup system | ||||||||||||||
| - Support for dynamic keytab retrieval from various sources | ||||||||||||||
| - Integration with Fiber context for authenticated identity storage | ||||||||||||||
| - Configurable logging | ||||||||||||||
|
|
||||||||||||||
| ## Version Compatibility | ||||||||||||||
|
|
||||||||||||||
| This middleware is available in two versions to support different Fiber releases: | ||||||||||||||
|
|
||||||||||||||
| - **v2**: Compatible with Fiber v2 | ||||||||||||||
| - **v3**: Compatible with Fiber v3 | ||||||||||||||
|
|
||||||||||||||
| ## Installation | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| # For Fiber v3 | ||||||||||||||
| go get github.com/gofiber/contrib/spnego/v3 | ||||||||||||||
gaby marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||
|
|
||||||||||||||
| # For Fiber v2 | ||||||||||||||
| go get github.com/gofiber/contrib/spnego/v2 | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ## Usage | ||||||||||||||
|
|
||||||||||||||
| ### For Fiber v3 | ||||||||||||||
|
|
||||||||||||||
| ```go | ||||||||||||||
| package main | ||||||||||||||
|
|
||||||||||||||
| import ( | ||||||||||||||
| "fmt" | ||||||||||||||
| "time" | ||||||||||||||
|
|
||||||||||||||
| "github.com/gofiber/contrib/spnego" | ||||||||||||||
| "github.com/gofiber/contrib/spnego/utils" | ||||||||||||||
| v3 "github.com/gofiber/contrib/spnego/v3" | ||||||||||||||
| "github.com/gofiber/fiber/v3" | ||||||||||||||
| "github.com/gofiber/fiber/v3/log" | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| func main() { | ||||||||||||||
| app := fiber.New() | ||||||||||||||
|
|
||||||||||||||
| // Create a configuration with a keytab lookup function | ||||||||||||||
| // For testing, you can create a mock keytab file using utils.NewMockKeytab | ||||||||||||||
| // In production, use a real keytab file | ||||||||||||||
| keytabLookup, err := spnego.NewKeytabFileLookupFunc("/path/to/keytab/file.keytab") | ||||||||||||||
| if err != nil { | ||||||||||||||
| log.Fatalf("Failed to create keytab lookup function: %v", err) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Create the middleware | ||||||||||||||
| authMiddleware, err := v3.NewSpnegoKrb5AuthenticateMiddleware(spnego.Config{ | ||||||||||||||
| KeytabLookup: keytabLookup, | ||||||||||||||
| }) | ||||||||||||||
| if err != nil { | ||||||||||||||
| log.Fatalf("Failed to create middleware: %v", err) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Apply the middleware to protected routes | ||||||||||||||
| app.Use("/protected", authMiddleware) | ||||||||||||||
|
|
||||||||||||||
| // Access authenticated identity | ||||||||||||||
| app.Get("/protected/resource", func(c fiber.Ctx) error { | ||||||||||||||
| identity, ok := spnego.GetAuthenticatedIdentityFromContext(c) | ||||||||||||||
| if !ok { | ||||||||||||||
| return c.Status(fiber.StatusUnauthorized).SendString("Unauthorized") | ||||||||||||||
| } | ||||||||||||||
| return c.SendString(fmt.Sprintf("Hello, %s!", identity.UserName())) | ||||||||||||||
| }) | ||||||||||||||
|
|
||||||||||||||
| app.Listen(":3000") | ||||||||||||||
| } | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### For Fiber v2 | ||||||||||||||
|
|
||||||||||||||
| ```go | ||||||||||||||
| package main | ||||||||||||||
|
|
||||||||||||||
| import ( | ||||||||||||||
| "fmt" | ||||||||||||||
| "log" | ||||||||||||||
| "os" | ||||||||||||||
|
|
||||||||||||||
| "github.com/gofiber/contrib/spnego" | ||||||||||||||
| "github.com/gofiber/contrib/spnego/utils" | ||||||||||||||
| v2 "github.com/gofiber/contrib/spnego/v2" | ||||||||||||||
| "github.com/gofiber/fiber/v2" | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| func main() { | ||||||||||||||
| app := fiber.New() | ||||||||||||||
|
|
||||||||||||||
| // Create a configuration with a keytab lookup function | ||||||||||||||
| // For testing, you can create a mock keytab file using utils.NewMockKeytab | ||||||||||||||
| // In production, use a real keytab file | ||||||||||||||
| keytabLookup, err := spnego.NewKeytabFileLookupFunc("/path/to/keytab/file.keytab") | ||||||||||||||
| if err != nil { | ||||||||||||||
| log.Fatalf("Failed to create keytab lookup function: %v", err) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Create the middleware | ||||||||||||||
| authMiddleware, err := v2.NewSpnegoKrb5AuthenticateMiddleware(spnego.Config{ | ||||||||||||||
| KeytabLookup: keytabLookup, | ||||||||||||||
| // Optional: Set a custom logger | ||||||||||||||
| Log: log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds), | ||||||||||||||
| }) | ||||||||||||||
| if err != nil { | ||||||||||||||
| log.Fatalf("Failed to create middleware: %v", err) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Apply the middleware to protected routes | ||||||||||||||
| app.Use("/protected", authMiddleware) | ||||||||||||||
|
|
||||||||||||||
| // Access authenticated identity | ||||||||||||||
| app.Get("/protected/resource", func(c *fiber.Ctx) error { | ||||||||||||||
| identity, ok := spnego.GetAuthenticatedIdentityFromContext(c) | ||||||||||||||
| if !ok { | ||||||||||||||
| return c.Status(fiber.StatusUnauthorized).SendString("Unauthorized") | ||||||||||||||
| } | ||||||||||||||
| return c.SendString(fmt.Sprintf("Hello, %s!", identity.UserName())) | ||||||||||||||
| }) | ||||||||||||||
|
|
||||||||||||||
| app.Listen(":3000") | ||||||||||||||
| } | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ## Dynamic Keytab Lookup | ||||||||||||||
|
|
||||||||||||||
| The middleware is designed with extensibility in mind, allowing keytab retrieval from various sources beyond static files: | ||||||||||||||
|
|
||||||||||||||
| ```go | ||||||||||||||
| // Example: Retrieve keytab from a database | ||||||||||||||
| func dbKeytabLookup() (*keytab.Keytab, error) { | ||||||||||||||
| // Your database lookup logic here | ||||||||||||||
| // ... | ||||||||||||||
| return keytabFromDatabase, nil | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Example: Retrieve keytab from a remote service | ||||||||||||||
| func remoteKeytabLookup() (*keytab.Keytab, error) { | ||||||||||||||
| // Your remote service call logic here | ||||||||||||||
| // ... | ||||||||||||||
| return keytabFromRemote, nil | ||||||||||||||
| } | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ## API Reference | ||||||||||||||
|
|
||||||||||||||
| ### `NewSpnegoKrb5AuthenticateMiddleware(cfg spnego.Config) (fiber.Handler, error)` | ||||||||||||||
|
|
||||||||||||||
| Creates a new SPNEGO authentication middleware. | ||||||||||||||
|
|
||||||||||||||
| ### `GetAuthenticatedIdentityFromContext(ctx fiber.Ctx) (goidentity.Identity, bool)` | ||||||||||||||
|
|
||||||||||||||
| Retrieves the authenticated identity from the Fiber context. | ||||||||||||||
|
|
||||||||||||||
| ### `NewKeytabFileLookupFunc(keytabFiles ...string) (KeytabLookupFunc, error)` | ||||||||||||||
|
|
||||||||||||||
| Creates a new KeytabLookupFunc that loads keytab files. | ||||||||||||||
|
||||||||||||||
| ### `NewKeytabFileLookupFunc(keytabFiles ...string) (KeytabLookupFunc, error)` | |
| Creates a new KeytabLookupFunc that loads keytab files. | |
| ### `config.NewKeytabFileLookupFunc(keytabFiles ...string) (config.KeytabLookupFunc, error)` | |
| Creates a new KeytabLookupFunc that loads and merges keytab files. |
🤖 Prompt for AI Agents
In spnego/README.md around lines 175 to 177, the API reference incorrectly
states that NewKeytabFileLookupFunc is part of the version packages, but it is
actually located in the config package. Update the documentation to correctly
indicate that NewKeytabFileLookupFunc belongs to the config package to ensure
accurate API referencing.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,190 @@ | ||||||||||||||||||||||||||||||||||||||||
| # SPNEGO Kerberos 认证中间件 for Fiber | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| [English Version](README.md) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| 该中间件为Fiber应用提供SPNEGO(简单受保护GSSAPI协商机制)认证,使HTTP请求能够使用Kerberos认证。 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 功能特点 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| - 通过SPNEGO机制实现Kerberos认证 | ||||||||||||||||||||||||||||||||||||||||
| - 灵活的keytab查找系统 | ||||||||||||||||||||||||||||||||||||||||
| - 支持从各种来源动态检索keytab | ||||||||||||||||||||||||||||||||||||||||
| - 与Fiber上下文集成用于存储认证身份 | ||||||||||||||||||||||||||||||||||||||||
| - 可配置日志 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 版本兼容性 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| 该中间件提供两个版本以支持不同的Fiber版本: | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| - **v2**:兼容Fiber v2 | ||||||||||||||||||||||||||||||||||||||||
| - **v3**:兼容Fiber v3 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 安装 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||
| # 对于Fiber v3 | ||||||||||||||||||||||||||||||||||||||||
| go get github.com/gofiber/contrib/spnego/v3 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| # 对于Fiber v2 | ||||||||||||||||||||||||||||||||||||||||
| go get github.com/gofiber/contrib/spnego/v2 | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 使用方法 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ### 对于Fiber v3 | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```go | ||||||||||||||||||||||||||||||||||||||||
| package main | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| "github.com/gofiber/contrib/spnego" | ||||||||||||||||||||||||||||||||||||||||
| "github.com/gofiber/contrib/spnego/utils" | ||||||||||||||||||||||||||||||||||||||||
| v3 "github.com/gofiber/contrib/spnego/v3" | ||||||||||||||||||||||||||||||||||||||||
| "github.com/gofiber/fiber/v3" | ||||||||||||||||||||||||||||||||||||||||
| "github.com/gofiber/fiber/v3/log" | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
| import ( | |
| "fmt" | |
| "time" | |
| "github.com/gofiber/contrib/spnego" | |
| "github.com/gofiber/contrib/spnego/utils" | |
| v3 "github.com/gofiber/contrib/spnego/v3" | |
| "github.com/gofiber/fiber/v3" | |
| "github.com/gofiber/fiber/v3/log" | |
| ) | |
| import ( | |
| "fmt" | |
| "time" | |
| "github.com/gofiber/contrib/spnego" | |
| v3 "github.com/gofiber/contrib/spnego/v3" | |
| "github.com/gofiber/fiber/v3" | |
| "github.com/gofiber/fiber/v3/log" | |
| ) |
🤖 Prompt for AI Agents
In spnego/README.zh-CN.md around lines 39 to 48, the v3 example imports
"github.com/gofiber/contrib/spnego/utils" but never uses it which causes compile
errors when copying the snippet; remove the unused utils import or alternatively
demonstrate its use (e.g., call utils.NewMockKeytab in the example) so the
import is actually referenced; update the import block to omit utils if you
choose to keep the snippet minimal, or add a short usage line showing how to
construct the mock keytab and pass it to the v3 config.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove unused import from the v2 example.
Same unused utils import in the v2 snippet.
import (
"fmt"
"log"
"os"
"github.com/gofiber/contrib/spnego"
- "github.com/gofiber/contrib/spnego/utils"
v2 "github.com/gofiber/contrib/spnego/v2"
"github.com/gofiber/fiber/v2"
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import ( | |
| "fmt" | |
| "log" | |
| "os" | |
| "github.com/gofiber/contrib/spnego" | |
| "github.com/gofiber/contrib/spnego/utils" | |
| v2 "github.com/gofiber/contrib/spnego/v2" | |
| "github.com/gofiber/fiber/v2" | |
| ) | |
| import ( | |
| "fmt" | |
| "log" | |
| "os" | |
| "github.com/gofiber/contrib/spnego" | |
| v2 "github.com/gofiber/contrib/spnego/v2" | |
| "github.com/gofiber/fiber/v2" | |
| ) |
🤖 Prompt for AI Agents
In spnego/README.zh-CN.md around lines 90 to 100, the v2 example imports an
unused "github.com/gofiber/contrib/spnego/utils" package; remove that unused
import from the import block so only required packages remain (fmt, log, os, v2
"github.com/gofiber/contrib/spnego/v2", and "github.com/gofiber/fiber/v2") to
eliminate the unused-import warning and keep examples accurate.
Uh oh!
There was an error while loading. Please reload this page.