[WIP] music platform user data scraper
teal-fm atproto

add haileys jwt helper package

Changed files
+21 -132
cmd
util
jwtgen
+6 -2
Makefile
··· 13 13 && go run golang.org/x/tools/cmd/goimports@latest -w $$(find ./api/teal -type f) \ 14 14 && go run ./util/gencbor/gencbor.go \ 15 15 && $(MAKE) lexgen \ 16 - && find . | grep bak$$ | xargs rm 16 + && find . | grep bak$$ | xargs rm 17 17 18 18 .PHONY: lexgen 19 19 lexgen: ··· 24 24 go run github.com/bluesky-social/indigo/cmd/lexgen \ 25 25 --build-file ./lexcfg.json \ 26 26 ../atproto/lexicons \ 27 - ./lexicons/teal \ 27 + ./lexicons/teal 28 + 29 + .PHONY: jwtgen 30 + jwtgen: 31 + go run github.com/haileyok/atproto-oauth-golang/cmd/helper generate-jwks
+2 -10
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" 22 21 ) 23 22 24 23 type application struct { ··· 56 55 // --- Service Initializations --- 57 56 jwksBytes, err := os.ReadFile("./jwks.json") 58 57 if err != nil { 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 - } 58 + // run `make jwtgen` 59 + log.Fatalf("Error reading JWK file: %v", err) 68 60 } 69 61 jwks, err := atproto.LoadJwks(jwksBytes) 70 62 if err != nil {
+4
go.mod
··· 26 26 github.com/bep/golibsass v1.2.0 // indirect 27 27 github.com/carlmjohnson/versioninfo v0.22.5 // indirect 28 28 github.com/cli/safeexec v1.0.1 // indirect 29 + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect 29 30 github.com/creack/pty v1.1.23 // indirect 30 31 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect 31 32 github.com/fatih/color v1.17.0 // indirect ··· 74 75 github.com/pelletier/go-toml v1.9.5 // indirect 75 76 github.com/pelletier/go-toml/v2 v2.2.3 // indirect 76 77 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect 78 + github.com/russross/blackfriday/v2 v2.1.0 // indirect 77 79 github.com/sagikazarmark/locafero v0.7.0 // indirect 78 80 github.com/segmentio/asm v1.2.0 // indirect 79 81 github.com/sourcegraph/conc v0.3.0 // indirect ··· 83 85 github.com/spf13/pflag v1.0.6 // indirect 84 86 github.com/subosito/gotenv v1.6.0 // indirect 85 87 github.com/tdewolff/parse/v2 v2.7.15 // indirect 88 + github.com/urfave/cli/v2 v2.27.5 // indirect 89 + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect 86 90 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect 87 91 go.opentelemetry.io/otel v1.29.0 // indirect 88 92 go.opentelemetry.io/otel/metric v1.29.0 // indirect
+9
go.sum
··· 51 51 github.com/cli/safeexec v1.0.1/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q= 52 52 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 53 53 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 54 + github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= 55 + github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 54 56 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 55 57 github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= 56 58 github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= ··· 303 305 github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= 304 306 github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 305 307 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 308 + github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 309 + github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 306 310 github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= 307 311 github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= 308 312 github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= ··· 348 352 github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= 349 353 github.com/tetratelabs/wazero v1.8.0 h1:iEKu0d4c2Pd+QSRieYbnQC9yiFlMS9D+Jr0LsRmcF4g= 350 354 github.com/tetratelabs/wazero v1.8.0/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= 355 + github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk= 351 356 github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 357 + github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= 358 + github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= 352 359 github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= 353 360 github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= 354 361 github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= 355 362 github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= 356 363 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e h1:28X54ciEwwUxyHn9yrZfl5ojgF4CBNLWX7LR0rvBkf4= 357 364 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= 365 + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= 366 + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= 358 367 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 359 368 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 360 369 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-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 - }