// Copyright (C) 2024 veypi // 2025-03-04 16:08:06 // Distributed under terms of the MIT license. package oauth import ( "github.com/veypi/vbase/cfg" "github.com/veypi/vbase/libs/cache" "github.com/veypi/vbase/libs/crypto" "github.com/veypi/vbase/models" "github.com/veypi/vigo" ) type AuthorizeRequest struct { ResponseType string `json:"response_type" src:"query" desc:"授权类型"` ClientID string `json:"client_id" src:"query" desc:"客户端ID"` RedirectURI string `json:"redirect_uri" src:"query" desc:"重定向URI"` Scope string `json:"scope" src:"query" desc:"授权范围"` State string `json:"state" src:"query" desc:"状态值"` } type AuthorizeResponse struct { Code string `json:"code"` State string `json:"state"` } func authorize(x *vigo.X, req *AuthorizeRequest) (*AuthorizeResponse, error) { // 验证客户端 var client models.OAuthClient if err := cfg.DB().First(&client, "client_id = ?", req.ClientID).Error; err != nil { return nil, vigo.ErrUnauthorized.WithString("invalid client") } if client.Status != models.OAuthClientStatusActive { return nil, vigo.ErrForbidden.WithString("client is disabled") } // 获取当前用户 userID := getCurrentUserID(x) if userID == "" { return nil, vigo.ErrUnauthorized } // 生成授权码 code := crypto.GenerateSecret(32) // 缓存授权码 authData := map[string]any{ "client_id": req.ClientID, "user_id": userID, "redirect_uri": req.RedirectURI, "scope": req.Scope, } if err := cache.SetObject(cache.OAuthCodeKey(code), authData, cfg.Config.OAuth.AuthorizationExpiry); err != nil { return nil, vigo.ErrInternalServer.WithError(err) } return &AuthorizeResponse{ Code: code, State: req.State, }, nil } func getCurrentUserID(x *vigo.X) string { if uid, ok := x.Get("user_id").(string); ok { return uid } return "" }