package main import ( "context" "errors" "fmt" "net/http" "slices" "time" "github.com/Luzifer/twitch-bot/v3/internal/service/authcache" "github.com/Luzifer/twitch-bot/v3/pkg/twitch" ) const internalTokenAuthCacheExpiry = 5 * time.Minute func authBackendInternalToken(token string) (modules []string, expiresAt time.Time, err error) { for _, auth := range config.AuthTokens { if auth.validate(token) != nil { continue } // We found a matching token return auth.Modules, time.Now().Add(internalTokenAuthCacheExpiry), nil } return nil, time.Time{}, authcache.ErrUnauthorized } func authBackendTwitchToken(token string) (modules []string, expiresAt time.Time, err error) { tc := twitch.New(cfg.TwitchClient, cfg.TwitchClientSecret, token, "") var httpError twitch.HTTPError id, user, err := tc.GetAuthorizedUser(context.Background()) switch { case err == nil: // We got a valid user, continue check below if !slices.Contains(config.BotEditors, user) && !slices.Contains(config.BotEditors, id) { // That user is none of our editors: Deny access return nil, time.Time{}, authcache.ErrUnauthorized } _, _, expiresAt, err = tc.GetTokenInfo(context.Background()) if err != nil { return nil, time.Time{}, fmt.Errorf("getting token expiry: %w", err) } // Editors have full access: Return module "*" return []string{"*"}, expiresAt, nil case errors.As(err, &httpError): // We either got "forbidden" or we got another error if httpError.Code == http.StatusUnauthorized { // That token wasn't valid or not a Twitch token: Unauthorized return nil, time.Time{}, authcache.ErrUnauthorized } return nil, time.Time{}, fmt.Errorf("validating Twitch token: %w", err) default: // Something else went wrong return nil, time.Time{}, fmt.Errorf("validating Twitch token: %w", err) } }