mirror of
https://git.sr.ht/~sircmpwn/core-go
synced 2024-09-09 11:42:36 +02:00
auth: s/OAuth2Token/BearerToken/g
This also makes some tweaks to the organization of the crypto module to make it easier for us to add more keys in the future, which will be necessary for the internal token redesign.
This commit is contained in:
parent
39cd24bd09
commit
1d24fef3e2
6 changed files with 68 additions and 68 deletions
|
@ -23,7 +23,7 @@ func ToTimestamp(t time.Time) Timestamp {
|
|||
return Timestamp(t.UTC().Unix())
|
||||
}
|
||||
|
||||
type OAuth2Token struct {
|
||||
type BearerToken struct {
|
||||
Version uint
|
||||
Expires Timestamp
|
||||
Grants string
|
||||
|
@ -31,16 +31,16 @@ type OAuth2Token struct {
|
|||
Username string
|
||||
}
|
||||
|
||||
func (ot *OAuth2Token) Encode() string {
|
||||
plain, err := bare.Marshal(ot)
|
||||
func (bt *BearerToken) Encode() string {
|
||||
plain, err := bare.Marshal(bt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
mac := crypto.HMAC(plain)
|
||||
mac := crypto.BearerHMAC(plain)
|
||||
return base64.RawStdEncoding.EncodeToString(append(plain, mac...))
|
||||
}
|
||||
|
||||
func DecodeToken(token string) *OAuth2Token {
|
||||
func DecodeBearerToken(token string) *BearerToken {
|
||||
payload, err := base64.RawStdEncoding.DecodeString(token)
|
||||
if err != nil {
|
||||
log.Printf("Invalid bearer token: invalid base64 %e", err)
|
||||
|
@ -53,25 +53,25 @@ func DecodeToken(token string) *OAuth2Token {
|
|||
|
||||
mac := payload[len(payload)-32:]
|
||||
payload = payload[:len(payload)-32]
|
||||
if crypto.HMACVerify(payload, mac) == false {
|
||||
if crypto.BearerVerify(payload, mac) == false {
|
||||
log.Printf("Invalid bearer token: HMAC verification failed (MAC: [%d]%s; payload: [%d]%s",
|
||||
len(mac), hex.EncodeToString(mac), len(payload), hex.EncodeToString(payload))
|
||||
return nil
|
||||
}
|
||||
|
||||
var ot OAuth2Token
|
||||
err = bare.Unmarshal(payload, &ot)
|
||||
var bt BearerToken
|
||||
err = bare.Unmarshal(payload, &bt)
|
||||
if err != nil {
|
||||
log.Printf("Invalid bearer token: BARE unmarshal failed: %e", err)
|
||||
return nil
|
||||
}
|
||||
if ot.Version != TokenVersion {
|
||||
if bt.Version != TokenVersion {
|
||||
log.Printf("Invalid bearer token: invalid token version")
|
||||
return nil
|
||||
}
|
||||
if time.Now().UTC().After(ot.Expires.Time()) {
|
||||
if time.Now().UTC().After(bt.Expires.Time()) {
|
||||
log.Printf("Invalid bearer token: token expired")
|
||||
return nil
|
||||
}
|
||||
return &ot
|
||||
return &bt
|
||||
}
|
|
@ -27,75 +27,75 @@ network-key=tbuG-7Vh44vrDq1L_HKWkHnWrDOtJhEkPKPiauaLeuk=`))
|
|||
}
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
ot := &OAuth2Token{
|
||||
bt := &BearerToken{
|
||||
Version: TokenVersion,
|
||||
Expires: ToTimestamp(time.Now().Add(30 * time.Minute)),
|
||||
Grants: "",
|
||||
ClientID: "",
|
||||
Username: "jdoe",
|
||||
}
|
||||
token := ot.Encode()
|
||||
token := bt.Encode()
|
||||
bytes, err := base64.RawStdEncoding.DecodeString(token)
|
||||
assert.Nil(t, err)
|
||||
|
||||
mac := bytes[len(bytes)-32:]
|
||||
payload := bytes[:len(bytes)-32]
|
||||
assert.True(t, crypto.HMACVerify(payload, mac))
|
||||
assert.True(t, crypto.BearerVerify(payload, mac))
|
||||
|
||||
var ot2 OAuth2Token
|
||||
err = bare.Unmarshal(payload, &ot2)
|
||||
var bt2 BearerToken
|
||||
err = bare.Unmarshal(payload, &bt2)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, ot.Version, ot2.Version)
|
||||
assert.Equal(t, ot.Expires, ot2.Expires)
|
||||
assert.Equal(t, ot.Grants, ot2.Grants)
|
||||
assert.Equal(t, ot.ClientID, ot2.ClientID)
|
||||
assert.Equal(t, ot.Username, ot2.Username)
|
||||
assert.Equal(t, bt.Version, bt2.Version)
|
||||
assert.Equal(t, bt.Expires, bt2.Expires)
|
||||
assert.Equal(t, bt.Grants, bt2.Grants)
|
||||
assert.Equal(t, bt.ClientID, bt2.ClientID)
|
||||
assert.Equal(t, bt.Username, bt2.Username)
|
||||
}
|
||||
|
||||
func TestDecode(t *testing.T) {
|
||||
ot := &OAuth2Token{
|
||||
bt := &BearerToken{
|
||||
Version: TokenVersion,
|
||||
Expires: ToTimestamp(time.Now().Add(30 * time.Minute)),
|
||||
Grants: "",
|
||||
ClientID: "",
|
||||
Username: "jdoe",
|
||||
}
|
||||
token := ot.Encode()
|
||||
ot2 := DecodeToken(token)
|
||||
assert.NotNil(t, ot2)
|
||||
assert.Equal(t, ot.Version, ot2.Version)
|
||||
assert.Equal(t, ot.Expires, ot2.Expires)
|
||||
assert.Equal(t, ot.Grants, ot2.Grants)
|
||||
assert.Equal(t, ot.ClientID, ot2.ClientID)
|
||||
assert.Equal(t, ot.Username, ot2.Username)
|
||||
token := bt.Encode()
|
||||
bt2 := DecodeBearerToken(token)
|
||||
assert.NotNil(t, bt2)
|
||||
assert.Equal(t, bt.Version, bt2.Version)
|
||||
assert.Equal(t, bt.Expires, bt2.Expires)
|
||||
assert.Equal(t, bt.Grants, bt2.Grants)
|
||||
assert.Equal(t, bt.ClientID, bt2.ClientID)
|
||||
assert.Equal(t, bt.Username, bt2.Username)
|
||||
|
||||
// Expired token:
|
||||
ot = &OAuth2Token{
|
||||
bt = &BearerToken{
|
||||
Version: TokenVersion,
|
||||
Expires: ToTimestamp(time.Now().Add(-30 * time.Minute)),
|
||||
Grants: "",
|
||||
ClientID: "",
|
||||
Username: "jdoe",
|
||||
}
|
||||
token = ot.Encode()
|
||||
ot2 = DecodeToken(token)
|
||||
assert.Nil(t, ot2)
|
||||
token = bt.Encode()
|
||||
bt2 = DecodeBearerToken(token)
|
||||
assert.Nil(t, bt2)
|
||||
|
||||
// Invalid MAC:
|
||||
ot = &OAuth2Token{
|
||||
bt = &BearerToken{
|
||||
Version: TokenVersion,
|
||||
Expires: ToTimestamp(time.Now().Add(30 * time.Minute)),
|
||||
Grants: "",
|
||||
ClientID: "",
|
||||
Username: "jdoe",
|
||||
}
|
||||
plain, err := bare.Marshal(ot)
|
||||
plain, err := bare.Marshal(bt)
|
||||
assert.Nil(t, err)
|
||||
mac := crypto.HMAC(plain)
|
||||
ot.Username = "rdoe"
|
||||
plain, err = bare.Marshal(ot)
|
||||
mac := crypto.BearerHMAC(plain)
|
||||
bt.Username = "rdoe"
|
||||
plain, err = bare.Marshal(bt)
|
||||
assert.Nil(t, err)
|
||||
token = base64.RawStdEncoding.EncodeToString(append(plain, mac...))
|
||||
ot2 = DecodeToken(token)
|
||||
assert.Nil(t, ot2)
|
||||
bt2 = DecodeBearerToken(token)
|
||||
assert.Nil(t, bt2)
|
||||
}
|
|
@ -75,7 +75,7 @@ type AuthContext struct {
|
|||
InternalAuth InternalAuth
|
||||
|
||||
// Only filled out if AuthMethod == AUTH_OAUTH2
|
||||
OAuth2Token *OAuth2Token
|
||||
BearerToken *BearerToken
|
||||
Access map[string]string
|
||||
}
|
||||
|
||||
|
@ -503,15 +503,15 @@ func OAuth2(token string, hash [64]byte, w http.ResponseWriter,
|
|||
)
|
||||
wg.Add(2)
|
||||
|
||||
ot := DecodeToken(token)
|
||||
if ot == nil {
|
||||
bt := DecodeBearerToken(token)
|
||||
if bt == nil {
|
||||
authError(w, `Invalid or expired OAuth 2.0 bearer token`, http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err = LookupUser(r.Context(), ot.Username, &auth)
|
||||
err = LookupUser(r.Context(), bt.Username, &auth)
|
||||
if err != nil {
|
||||
log.Printf("LookupUser: %e", err)
|
||||
atomic.AddInt32(&tempErr, 1)
|
||||
|
@ -523,7 +523,7 @@ func OAuth2(token string, hash [64]byte, w http.ResponseWriter,
|
|||
go func() {
|
||||
defer wg.Done()
|
||||
isRevoked, err := LookupTokenRevocation(r.Context(),
|
||||
ot.Username, hash, ot.ClientID)
|
||||
bt.Username, hash, bt.ClientID)
|
||||
if err != nil {
|
||||
log.Printf("LookupTokenRevocation: %e", err)
|
||||
atomic.AddInt32(&tempErr, 1)
|
||||
|
@ -550,11 +550,11 @@ func OAuth2(token string, hash [64]byte, w http.ResponseWriter,
|
|||
}
|
||||
|
||||
auth.AuthMethod = AUTH_OAUTH2
|
||||
auth.OAuth2Token = ot
|
||||
auth.BearerToken = bt
|
||||
|
||||
if ot.Grants != "" {
|
||||
if bt.Grants != "" {
|
||||
auth.Access = make(map[string]string)
|
||||
for _, grant := range strings.Split(ot.Grants, " ") {
|
||||
for _, grant := range strings.Split(bt.Grants, " ") {
|
||||
var (
|
||||
service string
|
||||
scope string
|
||||
|
|
|
@ -12,6 +12,6 @@ import (
|
|||
func main() {
|
||||
conf := config.LoadConfig(":1111")
|
||||
crypto.InitCrypto(conf)
|
||||
tok := auth.DecodeToken(os.Args[1])
|
||||
tok := auth.DecodeBearerToken(os.Args[1])
|
||||
fmt.Printf("%+v\n", tok)
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
privateKey ed25519.PrivateKey
|
||||
publicKey ed25519.PublicKey
|
||||
macKey []byte
|
||||
fernetKey *fernet.Key
|
||||
webhookSk ed25519.PrivateKey
|
||||
webhookPk ed25519.PublicKey
|
||||
bearerKey []byte
|
||||
fernetKey *fernet.Key
|
||||
)
|
||||
|
||||
func InitCrypto(config ini.File) {
|
||||
|
@ -31,8 +31,8 @@ func InitCrypto(config ini.File) {
|
|||
if err != nil {
|
||||
log.Fatalf("base64 decode webhooks private key: %v", err)
|
||||
}
|
||||
privateKey = ed25519.NewKeyFromSeed(seed)
|
||||
publicKey, _ = privateKey.Public().(ed25519.PublicKey)
|
||||
webhookSk = ed25519.NewKeyFromSeed(seed)
|
||||
webhookPk, _ = webhookSk.Public().(ed25519.PublicKey)
|
||||
|
||||
b64fernet, ok := config.Get("sr.ht", "network-key")
|
||||
if !ok {
|
||||
|
@ -42,17 +42,17 @@ func InitCrypto(config ini.File) {
|
|||
if err != nil {
|
||||
log.Fatalf("Load Fernet network encryption key: %v", err)
|
||||
}
|
||||
mac := hmac.New(sha256.New, privateKey)
|
||||
mac := hmac.New(sha256.New, webhookSk)
|
||||
mac.Write([]byte("sr.ht HMAC key"))
|
||||
macKey = mac.Sum(nil)
|
||||
bearerKey = mac.Sum(nil)
|
||||
}
|
||||
|
||||
func Sign(payload []byte) []byte {
|
||||
return ed25519.Sign(privateKey, payload)
|
||||
return ed25519.Sign(webhookSk, payload)
|
||||
}
|
||||
|
||||
func Verify(payload, signature []byte) bool {
|
||||
return ed25519.Verify(publicKey, payload, signature)
|
||||
return ed25519.Verify(webhookPk, payload, signature)
|
||||
}
|
||||
|
||||
func Encrypt(payload []byte) []byte {
|
||||
|
@ -75,14 +75,14 @@ func DecryptWithExpiration(payload []byte, expiry time.Duration) []byte {
|
|||
return fernet.VerifyAndDecrypt(payload, expiry, []*fernet.Key{fernetKey})
|
||||
}
|
||||
|
||||
func HMAC(payload []byte) []byte {
|
||||
mac := hmac.New(sha256.New, macKey)
|
||||
func BearerHMAC(payload []byte) []byte {
|
||||
mac := hmac.New(sha256.New, bearerKey)
|
||||
mac.Write(payload)
|
||||
return mac.Sum(nil)
|
||||
}
|
||||
|
||||
func HMACVerify(payload []byte, signature []byte) bool {
|
||||
mac := hmac.New(sha256.New, macKey)
|
||||
func BearerVerify(payload []byte, signature []byte) bool {
|
||||
mac := hmac.New(sha256.New, bearerKey)
|
||||
mac.Write(payload)
|
||||
expected := mac.Sum(nil)
|
||||
return hmac.Equal(expected, signature)
|
||||
|
|
|
@ -79,13 +79,13 @@ func TestEncryptWithExpire(t *testing.T) {
|
|||
assert.Nil(t, dec)
|
||||
}
|
||||
|
||||
func TestHMAC(t *testing.T) {
|
||||
func TestBearerHMAC(t *testing.T) {
|
||||
payload := []byte("Hello, world!")
|
||||
mac := HMAC(payload)
|
||||
mac := BearerHMAC(payload)
|
||||
|
||||
valid := HMACVerify(payload, mac)
|
||||
valid := BearerVerify(payload, mac)
|
||||
assert.True(t, valid)
|
||||
|
||||
valid = HMACVerify([]byte("Something else"), mac)
|
||||
valid = BearerVerify([]byte("Something else"), mac)
|
||||
assert.False(t, valid)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue