feat: 添加 password 模式
This commit is contained in:
@ -15,49 +15,34 @@ import (
|
||||
"uauth/model"
|
||||
)
|
||||
|
||||
func HandleToken(c *nf.Ctx) error {
|
||||
type Req struct {
|
||||
Code string `form:"code"`
|
||||
GrantType string `form:"grant_type"`
|
||||
RedirectURI string `form:"redirect_uri"`
|
||||
}
|
||||
|
||||
func verifyClient(c *nf.Ctx) (*model.Client, error) {
|
||||
var (
|
||||
err error
|
||||
req = new(Req)
|
||||
opId uint64
|
||||
op = new(model.User)
|
||||
token string
|
||||
basic string
|
||||
bs []byte
|
||||
strs []string
|
||||
client = new(model.Client)
|
||||
)
|
||||
|
||||
if err = c.BodyParser(req); err != nil {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: invalid form")
|
||||
}
|
||||
|
||||
// client_secret
|
||||
if basic = c.Get("Authorization"); basic == "" {
|
||||
return c.Status(http.StatusUnauthorized).SendString("Authorization header missing")
|
||||
return nil, errors.New("authorization header missing")
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(basic, "Basic "):
|
||||
basic = strings.TrimPrefix(basic, "Basic ")
|
||||
default:
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: authorization scheme not supported")
|
||||
return nil, errors.New("authorization scheme not supported")
|
||||
}
|
||||
|
||||
if bs, err = base64.StdEncoding.DecodeString(basic); err != nil {
|
||||
log.Warn("[Token] base64 decode failed, raw = %s, err = %s", basic, err.Error())
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: invalid basic authorization")
|
||||
return nil, errors.New("invalid basic authorization")
|
||||
}
|
||||
|
||||
if strs = strings.SplitN(string(bs), ":", 2); len(strs) != 2 {
|
||||
log.Warn("[Token] basic split err, decode = %s", string(bs))
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: invalid basic authorization")
|
||||
return nil, errors.New("invalid basic authorization")
|
||||
}
|
||||
|
||||
clientId, clientSecret := strs[0], strs[1]
|
||||
@ -66,31 +51,79 @@ func HandleToken(c *nf.Ctx) error {
|
||||
Take(client).
|
||||
Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: client invalid")
|
||||
return nil, errors.New("client invalid")
|
||||
}
|
||||
|
||||
log.Error("[Token] db take client by id = %s, err = %s", clientId, err.Error())
|
||||
return c.Status(http.StatusInternalServerError).SendString("Internal Server Error")
|
||||
return nil, errors.New("unknown server error")
|
||||
}
|
||||
|
||||
if client.ClientSecret != clientSecret {
|
||||
log.Warn("[Token] client_secret invalid, want = %s, got = %s", client.ClientSecret, clientSecret)
|
||||
return c.Status(http.StatusUnauthorized).SendString("Unauthorized: client secret invalid")
|
||||
return nil, errors.New("client secret invalid")
|
||||
}
|
||||
|
||||
if err = cache.Client.GetScan(tool.Timeout(2), cache.Prefix+"auth_code:"+req.Code).Scan(&opId); err != nil {
|
||||
if errors.Is(err, cache.ErrorKeyNotFound) {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: invalid code")
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func HandleToken(c *nf.Ctx) error {
|
||||
var (
|
||||
err error
|
||||
opId uint64
|
||||
op = new(model.User)
|
||||
token string
|
||||
client *model.Client
|
||||
grantType = c.Form("grant_type")
|
||||
)
|
||||
|
||||
switch grantType {
|
||||
case "password":
|
||||
if client, err = verifyClient(c); err != nil {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: " + err.Error())
|
||||
}
|
||||
|
||||
log.Error("[S] handleToken: get code from cache err = %s", err.Error())
|
||||
return c.Status(http.StatusInternalServerError).SendString("Internal Server Error")
|
||||
}
|
||||
username := c.Form("username")
|
||||
password := c.Form("password")
|
||||
if err = db.Default.Session().Model(&model.User{}).
|
||||
Where("username = ?", username).
|
||||
Take(op).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: invalid username or password")
|
||||
}
|
||||
|
||||
op.Id = opId
|
||||
if err = db.Default.Session().Take(op).Error; err != nil {
|
||||
log.Error("[S] handleToken: get op by id err, id = %d, err = %s", opId, err.Error())
|
||||
return c.Status(http.StatusInternalServerError).SendString("Internal Server Error")
|
||||
log.Error("[Token] db take user by username = %s, err = %s", username, err.Error())
|
||||
return c.Status(http.StatusInternalServerError).SendString("Internal Server Error")
|
||||
}
|
||||
|
||||
if !tool.ComparePassword(password, op.Password) {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: invalid username or password")
|
||||
}
|
||||
case "authorization_code":
|
||||
if client, err = verifyClient(c); err != nil {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: " + err.Error())
|
||||
}
|
||||
|
||||
code := c.Form("code")
|
||||
if code == "" {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: no code provided")
|
||||
}
|
||||
|
||||
if err = cache.Client.GetScan(tool.Timeout(2), cache.Prefix+"auth_code:"+code).Scan(&opId); err != nil {
|
||||
if errors.Is(err, cache.ErrorKeyNotFound) {
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: invalid code")
|
||||
}
|
||||
|
||||
log.Error("[S] handleToken: get code from cache err = %s", err.Error())
|
||||
return c.Status(http.StatusInternalServerError).SendString("Internal Server Error")
|
||||
}
|
||||
|
||||
op.Id = opId
|
||||
if err = db.Default.Session().Take(op).Error; err != nil {
|
||||
log.Error("[S] handleToken: get op by id err, id = %d, err = %s", opId, err.Error())
|
||||
return c.Status(http.StatusInternalServerError).SendString("Internal Server Error")
|
||||
}
|
||||
default:
|
||||
return c.Status(http.StatusBadRequest).SendString("Bad Request: invalid grant type")
|
||||
}
|
||||
|
||||
if token, err = op.JwtEncode(); err != nil {
|
||||
@ -100,6 +133,8 @@ func HandleToken(c *nf.Ctx) error {
|
||||
|
||||
refreshToken := uuid.New().String()
|
||||
|
||||
_ = client
|
||||
|
||||
return c.JSON(map[string]any{
|
||||
"access_token": token,
|
||||
"refresh_token": refreshToken,
|
||||
|
Reference in New Issue
Block a user