|
package middleware |
|
|
|
import ( |
|
"encoding/base64" |
|
"encoding/json" |
|
"fmt" |
|
"net/http" |
|
"os" |
|
"strings" |
|
"time" |
|
|
|
"github.com/gin-gonic/gin" |
|
|
|
"github.com/linweiyuan/go-chatgpt-api/api" |
|
) |
|
|
|
const ( |
|
emptyAccessTokenErrorMessage = "please provide a valid access token or api key in 'Authorization' header" |
|
accessTokenHasExpiredErrorMessage = "the accessToken for account %s has expired" |
|
) |
|
|
|
type AccessToken struct { |
|
HTTPSAPIOpenaiComProfile struct { |
|
Email string `json:"email"` |
|
EmailVerified bool `json:"email_verified"` |
|
} `json:"https://api.openai.com/profile"` |
|
HTTPSAPIOpenaiComAuth struct { |
|
UserID string `json:"user_id"` |
|
} `json:"https://api.openai.com/auth"` |
|
Iss string `json:"iss"` |
|
Sub string `json:"sub"` |
|
Aud []string `json:"aud"` |
|
Iat int `json:"iat"` |
|
Exp int `json:"exp"` |
|
Azp string `json:"azp"` |
|
Scope string `json:"scope"` |
|
} |
|
|
|
func Authorization() gin.HandlerFunc { |
|
return func(c *gin.Context) { |
|
authorization := c.GetHeader(api.AuthorizationHeader) |
|
if authorization == "" { |
|
authorization = c.GetHeader(api.XAuthorizationHeader) |
|
} |
|
|
|
if authorization == "" { |
|
if c.Request.URL.Path == "/" { |
|
c.Header("Content-Type", "text/plain") |
|
} else if strings.HasSuffix(c.Request.URL.Path, "/login") || |
|
strings.HasPrefix(c.Request.URL.Path, "/chatgpt/public-api") || |
|
(strings.HasPrefix(c.Request.URL.Path, "/imitate") && os.Getenv("IMITATE_ACCESS_TOKEN") != "") { |
|
c.Header("Content-Type", "application/json") |
|
} else if c.Request.URL.Path == "/favicon.ico" { |
|
c.Abort() |
|
return |
|
} else { |
|
c.AbortWithStatusJSON(http.StatusUnauthorized, api.ReturnMessage(emptyAccessTokenErrorMessage)) |
|
return |
|
} |
|
|
|
c.Next() |
|
} else { |
|
if expired := isExpired(c); expired { |
|
c.AbortWithStatusJSON(http.StatusUnauthorized, api.ReturnMessage(fmt.Sprintf(accessTokenHasExpiredErrorMessage, c.GetString(api.EmailKey)))) |
|
return |
|
} |
|
|
|
c.Set(api.AuthorizationHeader, authorization) |
|
} |
|
} |
|
} |
|
|
|
func isExpired(c *gin.Context) bool { |
|
accessToken := c.GetHeader(api.AuthorizationHeader) |
|
split := strings.Split(accessToken, ".") |
|
if len(split) == 3 { |
|
rawDecodedText, _ := base64.RawStdEncoding.DecodeString(split[1]) |
|
var accessToken AccessToken |
|
json.Unmarshal(rawDecodedText, &accessToken) |
|
|
|
c.Set(api.EmailKey, accessToken.HTTPSAPIOpenaiComProfile.Email) |
|
|
|
exp := int64(accessToken.Exp) |
|
expTime := time.Unix(exp, 0) |
|
now := time.Now() |
|
|
|
return now.After(expTime) |
|
} |
|
|
|
|
|
return false |
|
} |
|
|