مقدمة في OAuth 2.0 و JWT على Go
تتطلب تطبيقات الويب الحديثة وواجهات برمجة التطبيقات (API) نظامًا موثوقًا وآمنًا للمصادقة والتفويض. المعياران الأكثر شيوعًا في هذا المجال هما OAuth 2.0 و JWT (JSON Web Tokens). في لغة Go (Golang)، يصبح تنفيذ هذه الآليات فعالاً بشكل خاص بفضل الدعم المدمج للتوازي (concurrency)، والأداء العالي، والنظام البيئي الغني للمكتبات.
في هذه المقالة، سنشرح بالتفصيل كيفية تنفيذ تفويض OAuth 2.0 و JWT على Go. ستتعلم كيفية إعداد الخادم، وإنشاء الرموز (tokens) والتحقق منها، بالإضافة إلى حماية نقاط النهاية (endpoints) الخاصة بك. ستكون المادة مفيدة لكل من المطورين المبتدئين وذوي الخبرة في Go.
أساسيات OAuth 2.0 و JWT
ما هو OAuth 2.0؟
OAuth 2.0 هو بروتوكول تفويض يسمح للتطبيقات بالحصول على وصول محدود إلى موارد المستخدم دون نقل كلمة المرور. بدلاً من ذلك، يتم استخدام رموز الوصول (access tokens). المشاركون الرئيسيون في العملية هم:
- Resource Owner — المستخدم، مالك البيانات
- Client — التطبيق الذي يطلب الوصول
- Authorization Server — الخادم الذي يصدر الرموز
- Resource Server — الخادم الذي يوفر الموارد المحمية
ما هو JWT؟
JWT (JSON Web Token) هو تنسيق مضغوط ومكتفٍ ذاتيًا لنقل البيانات بين الأطراف على شكل كائن JSON. يتكون الرمز من ثلاثة أجزاء مفصولة بنقاط:
header.payload.signatureمزايا JWT:
- لا يتطلب تخزين الجلسات على الخادم (stateless)
- يحتوي على جميع المعلومات الضرورية (claims)
- موقع للتحقق من سلامته
تنفيذ تفويض JWT على Go
للعمل مع JWT في Go، سنستخدم المكتبة الشائعة golang-jwt/jwt/v5. قم بتثبيتها باستخدام الأمر:
go get github.com/golang-jwt/jwt/v5إنشاء رمز JWT
لنقم بإنشاء دالة لإنشاء رموز الوصول (access) والتحديث (refresh):
package auth
import ( "time" "github.com/golang-jwt/jwt/v5")
var jwtSecret = []byte("your-secret-key")
type Claims struct { UserID uint `json:"user_id"` Email string `json:"email"` jwt.RegisteredClaims}
func GenerateAccessToken(userID uint, email string) (string, error) { claims := &Claims{ UserID: userID, Email: email, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)), IssuedAt: jwt.NewNumericDate(time.Now()), Issuer: "myapp", }, }
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(jwtSecret)}
func GenerateRefreshToken(userID uint) (string, error) { claims := &Claims{ UserID: userID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), }, }
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(jwtSecret)}التحقق من رمز JWT
Middleware للتحقق من الرمز في طلبات HTTP:
package middleware
import ( "net/http" "strings" "github.com/gin-gonic/gin" "myapp/auth")
func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "missing authorization header"}) c.Abort() return }
tokenString := strings.TrimPrefix(authHeader, "Bearer ") if tokenString == authHeader {