66 lines
1.3 KiB
Go
66 lines
1.3 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/sha256"
|
||
|
|
"encoding/json"
|
||
|
|
"fmt"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
// CachedToken is the on-disk cache format.
|
||
|
|
type CachedToken struct {
|
||
|
|
AccessToken string `json:"accessToken"`
|
||
|
|
ExpiresAtEpoch int64 `json:"expiresAtEpoch"`
|
||
|
|
CreatedAtEpoch int64 `json:"createdAtEpoch"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func cacheFile(authBase, clientKey, cacheDir string) string {
|
||
|
|
h := sha256.Sum256([]byte(authBase + "|" + clientKey))
|
||
|
|
key := fmt.Sprintf("%x", h)
|
||
|
|
os.MkdirAll(cacheDir, 0o755)
|
||
|
|
return filepath.Join(cacheDir, "session_"+key+".json")
|
||
|
|
}
|
||
|
|
|
||
|
|
func readCachedToken(path string, minTTLSec int) string {
|
||
|
|
data, err := os.ReadFile(path)
|
||
|
|
if err != nil {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
var ct CachedToken
|
||
|
|
if err := json.Unmarshal(data, &ct); err != nil {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
if ct.AccessToken == "" || ct.ExpiresAtEpoch <= 0 {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
now := time.Now().Unix()
|
||
|
|
if now+int64(minTTLSec) >= ct.ExpiresAtEpoch {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
return ct.AccessToken
|
||
|
|
}
|
||
|
|
|
||
|
|
func writeCache(path string, token string, expiresIn int) {
|
||
|
|
if expiresIn <= 0 {
|
||
|
|
expiresIn = 900
|
||
|
|
}
|
||
|
|
now := time.Now().Unix()
|
||
|
|
ct := CachedToken{
|
||
|
|
AccessToken: token,
|
||
|
|
ExpiresAtEpoch: now + int64(expiresIn),
|
||
|
|
CreatedAtEpoch: now,
|
||
|
|
}
|
||
|
|
data, _ := json.MarshalIndent(ct, "", " ")
|
||
|
|
os.WriteFile(path, data, 0o644)
|
||
|
|
}
|
||
|
|
|
||
|
|
func deleteCache(path string) {
|
||
|
|
os.Remove(path)
|
||
|
|
}
|