diff --git a/drivers/aliyundrive_open/util.go b/drivers/aliyundrive_open/util.go index 37895b8a..f23b6a1e 100644 --- a/drivers/aliyundrive_open/util.go +++ b/drivers/aliyundrive_open/util.go @@ -2,9 +2,11 @@ package aliyundrive_open import ( "context" + "encoding/base64" "errors" "fmt" "net/http" + "strings" "github.com/alist-org/alist/v3/drivers/base" "github.com/alist-org/alist/v3/internal/op" @@ -15,7 +17,7 @@ import ( // do others that not defined in Driver interface -func (d *AliyundriveOpen) refreshToken() error { +func (d *AliyundriveOpen) _refreshToken() (string, string, error) { url := d.base + "/oauth/access_token" if d.OauthTokenURL != "" && d.ClientID == "" { url = d.OauthTokenURL @@ -34,15 +36,54 @@ func (d *AliyundriveOpen) refreshToken() error { SetError(&e). Post(url) if err != nil { - return err + return "", "", err } log.Debugf("[ali_open] refresh token response: %s", res.String()) if e.Code != "" { - return fmt.Errorf("failed to refresh token: %s", e.Message) + return "", "", fmt.Errorf("failed to refresh token: %s", e.Message) } refresh, access := utils.Json.Get(res.Body(), "refresh_token").ToString(), utils.Json.Get(res.Body(), "access_token").ToString() if refresh == "" { - return errors.New("failed to refresh token: refresh token is empty") + return "", "", errors.New("failed to refresh token: refresh token is empty") + } + curSub, err := getSub(d.RefreshToken) + if err != nil { + return "", "", err + } + newSub, err := getSub(refresh) + if err != nil { + return "", "", err + } + if curSub != newSub { + return "", "", errors.New("failed to refresh token: sub not match") + } + return refresh, access, nil +} + +func getSub(token string) (string, error) { + segments := strings.Split(token, ".") + if len(segments) != 3 { + return "", errors.New("not a jwt token because of invalid segments") + } + bs, err := base64.StdEncoding.DecodeString(segments[1]) + if err != nil { + return "", errors.New("failed to decode jwt token") + } + return utils.Json.Get(bs, "sub").ToString(), nil +} + +func (d *AliyundriveOpen) refreshToken() error { + refresh, access, err := d._refreshToken() + for i := 0; i < 3; i++ { + if err == nil { + break + } else { + log.Errorf("[ali_open] failed to refresh token: %s", err) + } + refresh, access, err = d._refreshToken() + } + if err != nil { + return err } log.Infof("[ali_open] toekn exchange: %s -> %s", d.RefreshToken, refresh) d.RefreshToken, d.AccessToken = refresh, access