Golang实现OIDC资源服务器的完整教程

我正在学习Golang实现OIDC资源服务器,但遇到了一些问题:

  1. 如何配置Golang服务来验证OIDC token?
  2. 资源服务器需要实现哪些必要的OIDC端点?
  3. 如何处理JWT签名验证和issuer校验?
  4. 有没有完整的代码示例可以参考?
  5. 在生产环境中需要注意哪些安全事项?
    希望能得到详细的指导,谢谢!
2 回复

要使用Golang实现OIDC资源服务器,可按以下步骤操作:

  1. 安装依赖 使用go mod初始化项目,安装核心包:
go mod init oidc-server
go get github.com/coreos/go-oidc/v3/oidc
  1. 配置OIDC提供者 从Issuer URL初始化Provider:
provider, err := oidc.NewProvider(ctx, "https://your-oidc-provider.com")
  1. 验证JWT令牌 创建验证器并校验访问令牌:
verifier := provider.Verifier(&oidc.Config{ClientID: "your-client-id"})
token, err := verifier.Verify(ctx, accessToken)
  1. 保护API路由 在HTTP中间件中验证请求:
func AuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token := r.Header.Get("Authorization")
        // 验证令牌逻辑
        if valid {
            next.ServeHTTP(w, r)
        }
    })
}
  1. 提取用户声明 从验证后的令牌获取用户信息:
var claims struct {
    Email string `json:"email"`
}
token.Claims(&claims)

关键点:

  • 使用标准库net/http构建服务器
  • 通过go-oidc库处理OIDC协议
  • 验证令牌签名和有效期
  • 根据scope检查权限

完整示例代码建议参考GitHub上的oauth2-proxy或dex项目实现。

更多关于Golang实现OIDC资源服务器的完整教程的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang实现OIDC资源服务器完整教程

概述

OIDC(OpenID Connect)资源服务器负责保护API资源,验证访问令牌并授权客户端访问。

核心组件

1. 依赖包

import (
    "context"
    "fmt"
    "net/http"
    "github.com/coreos/go-oidc/v3/oidc"
    "golang.org/x/oauth2"
)

2. 配置OIDC提供者

func setupOIDCProvider(issuerURL string) (*oidc.Provider, error) {
    ctx := context.Background()
    provider, err := oidc.NewProvider(ctx, issuerURL)
    if err != nil {
        return nil, fmt.Errorf("failed to create provider: %v", err)
    }
    return provider, nil
}

3. 中间件验证令牌

func authMiddleware(verifier *oidc.IDTokenVerifier) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            authHeader := r.Header.Get("Authorization")
            if authHeader == "" {
                http.Error(w, "Authorization header required", http.StatusUnauthorized)
                return
            }

            // 提取Bearer令牌
            token := strings.TrimPrefix(authHeader, "Bearer ")
            if token == authHeader {
                http.Error(w, "Bearer token required", http.StatusUnauthorized)
                return
            }

            // 验证令牌
            idToken, err := verifier.Verify(r.Context(), token)
            if err != nil {
                http.Error(w, "Invalid token", http.StatusUnauthorized)
                return
            }

            // 将令牌信息存入上下文
            ctx := context.WithValue(r.Context(), "idToken", idToken)
            next.ServeHTTP(w, r.WithContext(ctx))
        })
    }
}

4. 资源服务器主程序

func main() {
    // 配置OIDC提供者
    provider, err := setupOIDCProvider("https://your-oidc-provider.com")
    if err != nil {
        panic(err)
    }

    // 创建令牌验证器
    verifier := provider.Verifier(&oidc.Config{
        ClientID: "your-client-id",
    })

    // 创建路由
    mux := http.NewServeMux()
    
    // 受保护的路由
    mux.Handle("/api/protected", authMiddleware(verifier)(
        http.HandlerFunc(protectedHandler),
    ))

    // 启动服务器
    fmt.Println("Server starting on :8080")
    http.ListenAndServe(":8080", mux)
}

func protectedHandler(w http.ResponseWriter, r *http.Request) {
    // 从上下文中获取令牌信息
    idToken := r.Context().Value("idToken").(*oidc.IDToken)
    
    var claims struct {
        Email string `json:"email"`
        Name  string `json:"name"`
    }
    
    if err := idToken.Claims(&claims); err != nil {
        http.Error(w, "Failed to parse claims", http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    fmt.Fprintf(w, `{"message": "Hello %s!", "email": "%s"}`, claims.Name, claims.Email)
}

5. 完整配置示例

// config.go
type Config struct {
    OIDCIssuer   string
    ClientID     string
    ClientSecret string
    RedirectURL  string
}

func LoadConfig() *Config {
    return &Config{
        OIDCIssuer:   "https://your-oidc-provider.com",
        ClientID:     "your-client-id",
        ClientSecret: "your-client-secret",
        RedirectURL:  "http://localhost:8080/callback",
    }
}

部署步骤

  1. 安装依赖
go mod init oidc-resource-server
go get github.com/coreos/go-oidc/v3/oidc
go get golang.org/x/oauth2
  1. 配置OIDC提供者信息
  2. 运行服务器go run main.go

测试

使用有效的访问令牌访问受保护端点:

curl -H "Authorization: Bearer <your-access-token>" http://localhost:8080/api/protected

这个实现提供了基本的OIDC资源服务器功能,包括令牌验证和声明提取。根据具体需求,可以扩展添加角色验证、范围检查等高级功能。

回到顶部