+10
-1
cmd/main.go
+10
-1
cmd/main.go
···
18
18
"github.com/teal-fm/piper/service/musicbrainz"
19
19
"github.com/teal-fm/piper/service/spotify"
20
20
"github.com/teal-fm/piper/session"
21
+
"github.com/teal-fm/piper/util/jwtgen"
21
22
)
22
23
23
24
type application struct {
···
55
56
// --- Service Initializations ---
56
57
jwksBytes, err := os.ReadFile("./jwks.json")
57
58
if err != nil {
58
-
log.Fatalf("Error reading JWK file: %v", err)
59
+
// fuck Makefiles
60
+
if err := jwtgen.WriteJwksToDisk(""); err != nil {
61
+
log.Fatalf("Error reading JWK file: %v", err)
62
+
}
63
+
// works for now
64
+
jwksBytes, err = os.ReadFile("./jwks.json")
65
+
if err != nil {
66
+
log.Fatalf("Error reading JWK file: %v", err)
67
+
}
59
68
}
60
69
jwks, err := atproto.LoadJwks(jwksBytes)
61
70
if err != nil {
+120
util/jwtgen/jwtgen.go
+120
util/jwtgen/jwtgen.go
···
1
+
// bless up @haileyok
2
+
// https://github.com/haileyok/atproto-oauth-golang/blob/main/helpers/generic.go
3
+
4
+
package jwtgen
5
+
6
+
import (
7
+
"crypto/ecdsa"
8
+
"crypto/elliptic"
9
+
"crypto/rand"
10
+
"encoding/json"
11
+
"fmt"
12
+
"net/url"
13
+
"os"
14
+
"time"
15
+
16
+
"github.com/lestrrat-go/jwx/v2/jwk"
17
+
)
18
+
19
+
func WriteJwksToDisk(inputPrefix string) error {
20
+
var prefix *string
21
+
if inputPrefix != "" {
22
+
prefix = &inputPrefix
23
+
}
24
+
key, err := GenerateKey(prefix)
25
+
if err != nil {
26
+
return fmt.Errorf("error generating key: %v\n", err)
27
+
}
28
+
29
+
b, err := json.Marshal(key)
30
+
if err != nil {
31
+
return fmt.Errorf("error marshaling key: %v\n", err)
32
+
}
33
+
34
+
if err := os.WriteFile("./jwks.json", b, 0644); err != nil {
35
+
return fmt.Errorf("error writing jwk to disk: %v\n", err)
36
+
}
37
+
38
+
return nil
39
+
}
40
+
41
+
func GenerateKey(kidPrefix *string) (jwk.Key, error) {
42
+
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
43
+
if err != nil {
44
+
return nil, err
45
+
}
46
+
47
+
key, err := jwk.FromRaw(privKey)
48
+
if err != nil {
49
+
return nil, err
50
+
}
51
+
52
+
var kid string
53
+
if kidPrefix != nil {
54
+
kid = fmt.Sprintf("%s-%d", *kidPrefix, time.Now().Unix())
55
+
} else {
56
+
kid = fmt.Sprintf("%d", time.Now().Unix())
57
+
}
58
+
59
+
if err := key.Set(jwk.KeyIDKey, kid); err != nil {
60
+
return nil, err
61
+
}
62
+
return key, nil
63
+
}
64
+
65
+
func IsUrlSafeAndParsed(rawString string) (*url.URL, error) {
66
+
u, err := url.Parse(rawString)
67
+
if err != nil {
68
+
return nil, err
69
+
}
70
+
71
+
if u.Scheme != "https" {
72
+
return nil, fmt.Errorf("input url is not https")
73
+
}
74
+
75
+
if u.Hostname() == "" {
76
+
return nil, fmt.Errorf("url hostname was empty")
77
+
}
78
+
79
+
if u.User != nil {
80
+
return nil, fmt.Errorf("url user was not empty")
81
+
}
82
+
83
+
if u.Port() != "" {
84
+
return nil, fmt.Errorf("url port was not empty")
85
+
}
86
+
87
+
return u, nil
88
+
}
89
+
90
+
func GetPrivateKey(key jwk.Key) (*ecdsa.PrivateKey, error) {
91
+
var pkey ecdsa.PrivateKey
92
+
if err := key.Raw(&pkey); err != nil {
93
+
return nil, err
94
+
}
95
+
96
+
return &pkey, nil
97
+
}
98
+
99
+
func GetPublicKey(key jwk.Key) (*ecdsa.PublicKey, error) {
100
+
var pkey ecdsa.PublicKey
101
+
if err := key.Raw(&pkey); err != nil {
102
+
return nil, err
103
+
}
104
+
105
+
return &pkey, nil
106
+
}
107
+
108
+
type JwksResponseObject struct {
109
+
Keys []jwk.Key `json:"keys"`
110
+
}
111
+
112
+
func CreateJwksResponseObject(key jwk.Key) *JwksResponseObject {
113
+
return &JwksResponseObject{
114
+
Keys: []jwk.Key{key},
115
+
}
116
+
}
117
+
118
+
func ParseJWKFromBytes(bytes []byte) (jwk.Key, error) {
119
+
return jwk.ParseKey(bytes)
120
+
}