You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OneAuth/oauth/revoke.go

66 lines
1.8 KiB
Go

//
// Copyright (C) 2024 veypi <i@veypi.com>
// 2025-07-24 15:27:31
// Distributed under terms of the MIT license.
//
package oauth
import (
"github.com/veypi/OneAuth/cfg"
"github.com/vyes/vigo"
)
// RevokeRequest 撤销令牌请求参数
type RevokeRequest struct {
Token string `form:"token" binding:"required"`
TokenTypeHint string `form:"token_type_hint"` // access_token 或 refresh_token
ClientID string `form:"client_id"`
ClientSecret string `form:"client_secret"`
}
// RevokeResponse 撤销令牌响应
type RevokeResponse struct {
Message string `json:"message"`
Success bool `json:"success"`
}
// handleRevoke 处理OAuth撤销请求
func handleRevoke(x *vigo.X) error {
args := &RevokeRequest{}
if err := x.Parse(args); err != nil {
return vigo.NewError("参数解析失败").WithError(err).WithCode(400)
}
if args.Token == "" {
return vigo.NewError("令牌不能为空").WithCode(400)
}
db := cfg.DB()
// 根据OAuth 2.0规范,撤销令牌应该是幂等操作
// 即使令牌不存在也应该返回成功,这是为了防止信息泄露
var revoked = false
// 尝试撤销访问令牌
result := db.Model(&OAuthAccessToken{}).Where("token = ?", args.Token).Update("revoked", true)
if result.Error == nil && result.RowsAffected > 0 {
revoked = true
}
// 如果没有找到访问令牌,尝试撤销刷新令牌
if !revoked {
result = db.Model(&OAuthRefreshToken{}).Where("token = ?", args.Token).Update("revoked", true)
if result.Error == nil && result.RowsAffected > 0 {
revoked = true
}
}
// 根据OAuth 2.0规范,即使令牌不存在也返回成功
// 这样可以防止攻击者通过响应差异推断令牌是否存在
return x.JSON(&RevokeResponse{
Message: "令牌撤销成功",
Success: true,
})
}