golang支持OAuth2和OpenID Connect的身份认证与授权插件库goiabada的使用

Golang支持OAuth2和OpenID Connect的身份认证与授权插件库Goiabada的使用

Goiabada是一个开源的身份认证授权服务器,专为应用开发者设计,简化用户管理流程。

Goiabada主要特性

  • 使用Go语言构建,具有高性能和低资源消耗的特点
  • 提供简单易用的用户界面
  • 支持单点登录(SSO)
  • 提供基于一次性密码(OTP)的双因素认证(2FA)
  • 细粒度的资源和权限控制
  • 用户自助服务页面,允许用户更新个人信息
  • 支持OAuth2,包括授权码流程和客户端凭证流程
  • 支持OpenID Connect
  • 支持多种数据库:MySQL、PostgreSQL、Microsoft SQL Server、SQLite

Goiabada使用示例

以下是一个使用Goiabada进行OAuth2认证的完整示例:

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"

	"golang.org/x/oauth2"
)

// 配置OAuth2客户端
var oauth2Config = &oauth2.Config{
	ClientID:     "your-client-id",          // 在Goiabada中注册的客户端ID
	ClientSecret: "your-client-secret",      // 在Goiabada中注册的客户端密钥
	RedirectURL:  "http://localhost:8080/callback", // 回调URL
	Scopes:       []string{"openid", "profile", "email"}, // 请求的权限范围
	Endpoint: oauth2.Endpoint{
		AuthURL:  "http://localhost:8080/auth",  // Goiabada认证端点
		TokenURL: "http://localhost:8080/token", // Goiabada令牌端点
	},
}

func main() {
	http.HandleFunc("/", handleHome)
	http.HandleFunc("/login", handleLogin)
	http.HandleFunc("/callback", handleCallback)

	fmt.Println("Client is running at http://localhost:8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

// 首页处理器
func handleHome(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, `<h1>Goiabada OAuth2 Demo</h1>
		<a href="/login">Login with Goiabada</a>`)
}

// 登录处理器 - 重定向到Goiabada认证端点
func handleLogin(w http.ResponseWriter, r *http.Request) {
	url := oauth2Config.AuthCodeURL("state", oauth2.AccessTypeOffline)
	http.Redirect(w, r, url, http.StatusFound)
}

// 回调处理器 - 处理Goiabada返回的授权码
func handleCallback(w http.ResponseWriter, r *http.Request) {
	// 验证state参数
	state := r.FormValue("state")
	if state != "state" {
		http.Error(w, "Invalid state", http.StatusBadRequest)
		return
	}

	// 获取授权码
	code := r.FormValue("code")
	if code == "" {
		http.Error(w, "Authorization code not found", http.StatusBadRequest)
		return
	}

	// 交换令牌
	token, err := oauth2Config.Exchange(context.Background(), code)
	if err != nil {
		http.Error(w, fmt.Sprintf("Token exchange failed: %v", err), http.StatusInternalServerError)
		return
	}

	// 使用令牌获取用户信息
	client := oauth2Config.Client(context.Background(), token)
	resp, err := client.Get("http://localhost:8080/userinfo")
	if err != nil {
		http.Error(w, fmt.Sprintf("Failed to get user info: %v", err), http.StatusInternalServerError)
		return
	}
	defer resp.Body.Close()

	// 显示用户信息
	fmt.Fprintf(w, "<h1>Login Successful</h1>")
	fmt.Fprintf(w, "<pre>Access Token: %s</pre>", token.AccessToken)
	fmt.Fprintf(w, "<pre>Refresh Token: %s</pre>", token.RefreshToken)
	fmt.Fprintf(w, "<pre>User Info: %v</pre>", resp.Body)
}

Goiabada部署示例

使用Docker快速部署Goiabada服务:

docker run -d \
  -p 8080:8080 \
  -e GOIABADA_DATABASE_TYPE=sqlite \
  -e GOIABADA_DATABASE_NAME=goiabada.db \
  -v ./data:/data \
  leodip/goiabada:latest

配置说明

  1. 首先需要在Goiabada管理界面中创建客户端应用
  2. 配置客户端ID、客户端密钥和回调URL
  3. 根据需求设置权限范围(scope)
  4. 在应用中集成上述示例代码

Goiabada为Golang开发者提供了一个完整的OAuth2和OpenID Connect解决方案,可以轻松集成到现有应用中,实现安全的身份认证和授权功能。


更多关于golang支持OAuth2和OpenID Connect的身份认证与授权插件库goiabada的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang支持OAuth2和OpenID Connect的身份认证与授权插件库goiabada的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 中的 OAuth2 和 OpenID Connect 认证授权:goiabada 库使用指南

概述

OAuth2 和 OpenID Connect (OIDC) 是现代身份认证和授权的标准协议。在 Golang 生态中,goiabada 是一个实现这些协议的库,它可以帮助开发者快速构建安全的认证授权系统。

goiabada 简介

goiabada 是一个 Golang 实现的 OAuth2 和 OpenID Connect 服务器,它提供了:

  • OAuth2 授权码、隐式、密码和客户端凭证流程
  • OpenID Connect 认证
  • JWT 令牌签发与验证
  • 用户管理功能

安装

go get github.com/goiabada/goiabada

基本使用示例

1. 初始化 goiabada 服务器

package main

import (
	"log"
	"net/http"
	
	"github.com/goiabada/goiabada"
	"github.com/goiabada/goiabada/entities"
)

func main() {
	// 配置 goiabada
	config := &goiabada.Config{
		Issuer:        "http://localhost:8080",
		SigningKey:    []byte("your-256-bit-secret"), // 生产环境请使用更强的密钥
		SessionSecret: []byte("session-secret"),
		Database: goiabada.DatabaseConfig{
			Type: "sqlite3",
			URL:  "file:goiabada.db?cache=shared&mode=rwc",
		},
	}
	
	// 初始化服务器
	server, err := goiabada.NewServer(config)
	if err != nil {
		log.Fatal(err)
	}
	
	// 添加示例客户端
	client := &entities.Client{
		ClientID:     "example-client",
		ClientSecret: "client-secret",
		RedirectURIs: []string{"http://localhost:3000/callback"},
		Scopes:      []string{"openid", "profile", "email"},
	}
	
	if err := server.Store.SaveClient(client); err != nil {
		log.Fatal(err)
	}
	
	// 添加示例用户
	user := &entities.User{
		Email:    "user@example.com",
		Password: "password123", // 生产环境应使用哈希密码
	}
	
	if err := server.Store.SaveUser(user); err != nil {
		log.Fatal(err)
	}
	
	// 启动服务器
	log.Println("Starting goiabada server on http://localhost:8080")
	log.Fatal(http.ListenAndServe(":8080", server.Handler()))
}

2. 客户端应用集成

以下是一个使用 goiabada 进行 OAuth2 授权码流程的客户端示例:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	
	"golang.org/x/oauth2"
)

var (
	oauth2Config = &oauth2.Config{
		ClientID:     "example-client",
		ClientSecret: "client-secret",
		RedirectURL:  "http://localhost:3000/callback",
		Scopes:       []string{"openid", "profile", "email"},
		Endpoint: oauth2.Endpoint{
			AuthURL:  "http://localhost:8080/authorize",
			TokenURL: "http://localhost:8080/token",
		},
	}
)

func main() {
	http.HandleFunc("/", handleHome)
	http.HandleFunc("/login", handleLogin)
	http.HandleFunc("/callback", handleCallback)
	
	log.Println("Client running on http://localhost:3000")
	log.Fatal(http.ListenAndServe(":3000", nil))
}

func handleHome(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, `<a href="/login">Login with goiabada</a>`)
}

func handleLogin(w http.ResponseWriter, r *http.Request) {
	url := oauth2Config.AuthCodeURL("state", oauth2.AccessTypeOffline)
	http.Redirect(w, r, url, http.StatusFound)
}

func handleCallback(w http.ResponseWriter, r *http.Request) {
	ctx := context.Background()
	
	// 交换授权码获取令牌
	code := r.URL.Query().Get("code")
	token, err := oauth2Config.Exchange(ctx, code)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	
	// 使用令牌获取用户信息
	client := oauth2Config.Client(ctx, token)
	resp, err := client.Get("http://localhost:8080/userinfo")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer resp.Body.Close()
	
	var userInfo map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&userInfo); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	
	// 显示用户信息
	json.NewEncoder(w).Encode(userInfo)
}

高级配置

自定义用户存储

type CustomUserStore struct {
	// 实现 goiabada.UserStore 接口
}

func (s *CustomUserStore) GetUserByEmail(email string) (*entities.User, error) {
	// 自定义实现
}

// 在配置中使用自定义存储
config := &goiabada.Config{
	// ... 其他配置
	UserStore: &CustomUserStore{},
}

自定义令牌签名

config := &goiabada.Config{
	// ... 其他配置
	SigningMethod: jwt.SigningMethodRS256,
	PrivateKey:    privateKey, // *rsa.PrivateKey
	PublicKey:     publicKey,  // *rsa.PublicKey
}

安全最佳实践

  1. 生产环境配置

    • 使用 HTTPS
    • 使用强密钥 (至少 32 字节)
    • 密码应使用 bcrypt 等算法哈希存储
  2. 令牌安全

    • 使用短期访问令牌
    • 实现令牌撤销机制
    • 考虑使用 PKCE (Proof Key for Code Exchange)
  3. 会话管理

    • 设置安全的 Cookie 属性 (HttpOnly, Secure, SameSite)
    • 实现会话过期

总结

goiabada 为 Golang 开发者提供了一个实现 OAuth2 和 OpenID Connect 的便捷解决方案。通过上述示例,您可以快速搭建一个认证授权服务器,并在客户端应用中集成认证流程。对于生产环境,请确保遵循安全最佳实践,并根据需要扩展和定制功能。

更多高级功能和详细配置请参考 goiabada 的官方文档和源代码。

回到顶部