Yōten: A social tracker for your language learning journey built on the atproto.

feat(oauth): add permission sets #35

merged opened by brookjeynes.dev targeting master from push-sroumxtlyxxl
Labels

None yet.

Participants 1
AT URI
at://did:plc:4mj54vc4ha3lh32ksxwunnbh/sh.tangled.repo.pull/3md2sflgv3r22
+109 -208
Diff #0
assets/yoten_banner.png

This is a binary file and will not be displayed.

assets/yoten_logo.png

This is a binary file and will not be displayed.

+10
assets/yoten_logo_transparent.svg
··· 1 + <svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M160 107.39C160 141.824 145.837 161.277 122.403 161.277C98.9686 161.277 71.9149 140.006 71.9149 105.573C71.9149 71.1399 77.4844 46.3196 100.919 46.3196C124.214 38.116 160 72.9573 160 107.39Z" fill="#F9FBF9"/> 3 + <circle cx="98.3957" cy="110.264" r="49.3079" fill="#A8DE9C"/> 4 + <rect x="81.3088" y="58.0269" width="17.5751" height="104.474" fill="#F9FBF9"/> 5 + <path d="M96.3814 99.0276L147.255 149.39L110.606 172.558L90.3659 167.161L60.7262 135.045L96.3814 99.0276Z" fill="#F9FBF9"/> 6 + <path d="M97.4468 113.215C97.4468 149.759 100.729 172.128 85.3191 172.128C69.9089 172.128 40 149.759 40 113.215C40 76.6708 54.6809 56.3327 70.0912 56.3327C90.8815 41.2416 97.4468 76.6708 97.4468 113.215Z" fill="#F9FBF9"/> 7 + <circle cx="98.8839" cy="109.776" r="62.6073" stroke="black" stroke-width="10"/> 8 + <rect x="73.1915" y="13.1915" width="51.0638" height="12.766" rx="2" fill="black"/> 9 + <rect x="98.6467" y="104.894" width="32.4789" height="6.60207" rx="3.30104" transform="rotate(44.7106 98.6467 104.894)" fill="black"/> 10 + </svg>
+54
cmd/cborgen.go
··· 1 + package main 2 + 3 + import ( 4 + "maps" 5 + "reflect" 6 + "strings" 7 + 8 + "github.com/bluesky-social/indigo/mst" 9 + cbg "github.com/whyrusleeping/cbor-gen" 10 + 11 + "yoten.app/api/yoten" 12 + ) 13 + 14 + func main() { 15 + var typVals []any 16 + for _, typ := range mst.CBORTypes() { 17 + typVals = append(typVals, reflect.New(typ).Elem().Interface()) 18 + } 19 + 20 + genCfg := cbg.Gen{ 21 + MaxStringLength: 1_000_000, 22 + } 23 + 24 + yotenTypes := []any{ 25 + yoten.ActorProfile{}, 26 + yoten.FeedSession{}, 27 + yoten.FeedResource{}, 28 + yoten.ActivityDef{}, 29 + yoten.GraphFollow{}, 30 + yoten.FeedReaction{}, 31 + yoten.FeedComment{}, 32 + yoten.FeedComment_Reply{}, 33 + } 34 + 35 + for name, rt := range AllLexTypes() { 36 + if strings.HasPrefix(name, "app.yoten.") { 37 + yotenTypes = append(yotenTypes, reflect.New(rt).Interface()) 38 + } 39 + } 40 + yotenGenCfg := genCfg 41 + yotenGenCfg.SortTypeNames = true 42 + 43 + if err := yotenGenCfg.WriteMapEncodersToFile("api/yoten/cbor_gen.go", "yoten", yotenTypes...); err != nil { 44 + panic(err) 45 + } 46 + } 47 + 48 + var lexTypesMap map[string]reflect.Type 49 + 50 + func AllLexTypes() map[string]reflect.Type { 51 + out := make(map[string]reflect.Type, len(lexTypesMap)) 52 + maps.Copy(out, lexTypesMap) 53 + return out 54 + }
-54
cmd/gen.go
··· 1 - package main 2 - 3 - import ( 4 - "maps" 5 - "reflect" 6 - "strings" 7 - 8 - "github.com/bluesky-social/indigo/mst" 9 - cbg "github.com/whyrusleeping/cbor-gen" 10 - 11 - "yoten.app/api/yoten" 12 - ) 13 - 14 - func main() { 15 - var typVals []any 16 - for _, typ := range mst.CBORTypes() { 17 - typVals = append(typVals, reflect.New(typ).Elem().Interface()) 18 - } 19 - 20 - genCfg := cbg.Gen{ 21 - MaxStringLength: 1_000_000, 22 - } 23 - 24 - yotenTypes := []any{ 25 - yoten.ActorProfile{}, 26 - yoten.FeedSession{}, 27 - yoten.FeedResource{}, 28 - yoten.ActivityDef{}, 29 - yoten.GraphFollow{}, 30 - yoten.FeedReaction{}, 31 - yoten.FeedComment{}, 32 - yoten.FeedComment_Reply{}, 33 - } 34 - 35 - for name, rt := range AllLexTypes() { 36 - if strings.HasPrefix(name, "app.yoten.") { 37 - yotenTypes = append(yotenTypes, reflect.New(rt).Interface()) 38 - } 39 - } 40 - yotenGenCfg := genCfg 41 - yotenGenCfg.SortTypeNames = true 42 - 43 - if err := yotenGenCfg.WriteMapEncodersToFile("api/yoten/cbor_gen.go", "yoten", yotenTypes...); err != nil { 44 - panic(err) 45 - } 46 - } 47 - 48 - var lexTypesMap map[string]reflect.Type 49 - 50 - func AllLexTypes() map[string]reflect.Type { 51 - out := make(map[string]reflect.Type, len(lexTypesMap)) 52 - maps.Copy(out, lexTypesMap) 53 - return out 54 - }
-64
cmd/genjwks/main.go
··· 1 - // MIT License 2 - // 3 - // Copyright (c) 2025 Anirudh Oppiliappan, Akshay Oppiliappan and 4 - // contributors. 5 - // 6 - // Permission is hereby granted, free of charge, to any person obtaining a copy 7 - // of this software and associated documentation files (the "Software"), to deal 8 - // in the Software without restriction, including without limitation the rights 9 - // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 - // copies of the Software, and to permit persons to whom the Software is 11 - // furnished to do so, subject to the following conditions: 12 - // 13 - // The above copyright notice and this permission notice shall be included in all 14 - // copies or substantial portions of the Software. 15 - // 16 - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 - // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 - // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 - // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 - // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 - // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 - // SOFTWARE. 23 - 24 - package main 25 - 26 - import ( 27 - "crypto/ecdsa" 28 - "crypto/elliptic" 29 - "crypto/rand" 30 - "encoding/json" 31 - "fmt" 32 - "time" 33 - 34 - "github.com/lestrrat-go/jwx/v2/jwk" 35 - ) 36 - 37 - func main() { 38 - privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 39 - if err != nil { 40 - panic(err) 41 - } 42 - 43 - key, err := jwk.FromRaw(privKey) 44 - if err != nil { 45 - panic(err) 46 - } 47 - 48 - kid := fmt.Sprintf("%d", time.Now().Unix()) 49 - 50 - if err := key.Set(jwk.KeyIDKey, kid); err != nil { 51 - panic(err) 52 - } 53 - 54 - if err := key.Set("use", "sig"); err != nil { 55 - panic(err) 56 - } 57 - 58 - b, err := json.Marshal(key) 59 - if err != nil { 60 - panic(err) 61 - } 62 - 63 - fmt.Println(string(b)) 64 - }
+15 -16
cmd/server/main.go
··· 3 3 import ( 4 4 "context" 5 5 "encoding/gob" 6 - "errors" 7 6 "fmt" 8 7 "log" 9 8 "net/http" 9 + "os" 10 10 11 11 "yoten.app/internal/server" 12 12 "yoten.app/internal/server/config" ··· 16 16 func main() { 17 17 ctx := context.Background() 18 18 19 - c, err := config.LoadConfig(ctx) 19 + config, err := config.LoadConfig(ctx) 20 20 if err != nil { 21 21 log.Fatalf("failed to load config: %v", err) 22 + os.Exit(-1) 22 23 } 23 24 24 - serverState, err := server.Make(ctx, c) 25 + state, err := server.Make(ctx, config) 26 + defer func() { 27 + if err := state.Close(); err != nil { 28 + log.Fatalf("failed to create state: %v", err) 29 + } 30 + }() 25 31 if err != nil { 26 - log.Fatalf("failed to create state: %v", err) 32 + log.Fatalf("failed to start server: %v", err) 33 + os.Exit(-1) 27 34 } 28 35 29 - handler := handlers.NewHandler(serverState) 36 + handler := handlers.NewHandler(state) 30 37 31 38 gob.Register(map[string][]uint8{}) 32 39 33 - server := &http.Server{ 34 - Addr: fmt.Sprintf(":%s", c.Core.Port), 35 - Handler: handler.Router(), 36 - } 37 - 38 - log.Printf("Starting server on :%s\n", c.Core.Port) 39 - if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { 40 + log.Printf("Starting server on :%s\n", config.Core.Port) 41 + err = http.ListenAndServe(fmt.Sprintf(":%s", config.Core.Port), handler.Router()) 42 + if err != nil { 40 43 log.Fatalf("failed to start server: %v", err) 41 - } 42 - 43 - if err := serverState.Close(); err != nil { 44 - log.Printf("Application state cleanup error: %v", err) 45 44 } 46 45 47 46 log.Println("Shutdown complete.")
+2 -2
docs/hacking.md
··· 10 10 11 11 To authenticate, you will need OAUTH JWKs to be setup: 12 12 ```bash 13 - go build -o genjwks.out ./cmd/genjwks 14 - export YOTEN_OAUTH_JWKS="$(./genjwks.out)" 13 + export SHELF_OAUTH_CLIENT_KID="$(date +%s)" 14 + export SHELF_OAUTH_CLIENT_SECRET="$(goat key generate -t P-256 | grep -A1 "Secret Key" | tail -n1 | awk '{print $1}')" 15 15 ``` 16 16 17 17 You will need to fetch a series of static assets yōten depends on:
+3 -3
generate-lexicons.sh
··· 6 6 --build-file lexicon-build-config.json \ 7 7 lexicons/ 8 8 9 - find ./api/yoten -type f -exec sed -i.bak 's/\tutil/\/\/\tutil/' {} + 10 - find ./api/yoten -type f -exec sed -i.bak -E 's/^(.+)github(.+)//' {} + 11 - go run ./cmd/gen.go 9 + find ./api/shelf -type f -exec sed -i.bak 's/\lexutil/\/\/\lexutil/' {} + 10 + find ./api/shelf -type f -exec sed -i.bak -E 's/^(.+)github(.+)//' {} + 11 + go run ./cmd/cborgen.go 12 12 13 13 go run github.com/bluesky-social/indigo/cmd/lexgen \ 14 14 --package yoten \
+2 -5
go.mod
··· 1 1 module yoten.app 2 2 3 - go 1.24.0 4 - 5 - toolchain go1.24.4 3 + go 1.25 6 4 7 5 require ( 8 6 github.com/a-h/templ v0.3.898 9 7 github.com/bluesky-social/indigo v0.0.0-20251003000214-3259b215110e 10 - github.com/bluesky-social/jetstream v0.0.0-20250414024304-d17bd81a945e 8 + github.com/bluesky-social/jetstream v0.0.0-20241210005130-ea96859b93d1 11 9 github.com/carlmjohnson/versioninfo v0.22.5 12 10 github.com/charmbracelet/log v0.4.2 13 11 github.com/go-chi/chi/v5 v5.2.1 ··· 23 21 golang.org/x/sync v0.16.0 24 22 golang.org/x/text v0.28.0 25 23 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 26 - tangled.sh/icyphox.sh/atproto-oauth v0.0.0-20250724194903-28e660378cb1 27 24 ) 28 25 29 26 require (
+6 -12
go.sum
··· 12 12 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 13 13 github.com/bluesky-social/indigo v0.0.0-20251003000214-3259b215110e h1:IutKPwmbU0LrYqw03EuwJtMdAe67rDTrL1U8S8dicRU= 14 14 github.com/bluesky-social/indigo v0.0.0-20251003000214-3259b215110e/go.mod h1:n6QE1NDPFoi7PRbMUZmc2y7FibCqiVU4ePpsvhHUBR8= 15 - github.com/bluesky-social/jetstream v0.0.0-20250414024304-d17bd81a945e h1:P/O6TDHs53gwgV845uDHI+Nri889ixksRrh4bCkCdxo= 16 - github.com/bluesky-social/jetstream v0.0.0-20250414024304-d17bd81a945e/go.mod h1:WiYEeyJSdUwqoaZ71KJSpTblemUCpwJfh5oVXplK6T4= 15 + github.com/bluesky-social/jetstream v0.0.0-20241210005130-ea96859b93d1 h1:CFvRtYNSnWRAi/98M3O466t9dYuwtesNbu6FVPymRrA= 16 + github.com/bluesky-social/jetstream v0.0.0-20241210005130-ea96859b93d1/go.mod h1:WiYEeyJSdUwqoaZ71KJSpTblemUCpwJfh5oVXplK6T4= 17 17 github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= 18 18 github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= 19 19 github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= ··· 40 40 github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk= 41 41 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 42 42 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 43 + github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 43 44 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 44 - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 45 - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 46 45 github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= 47 46 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= 48 47 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= ··· 133 132 github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= 134 133 github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= 135 134 github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 136 - github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 137 - github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 138 135 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 139 136 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 140 137 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= ··· 201 198 github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= 202 199 github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= 203 200 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 201 + github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 204 202 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 205 - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 206 - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 207 203 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0= 208 204 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= 209 205 github.com/posthog/posthog-go v1.5.12 h1:nxK/z5QLCFxwzxV8GNvVd4Y1wJ++zJSWMGEtzU+/HLM= ··· 222 218 github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 223 219 github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 224 220 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 225 - github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= 226 - github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 221 + github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= 222 + github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 227 223 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 228 224 github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= 229 225 github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= ··· 398 394 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 399 395 lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= 400 396 lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= 401 - tangled.sh/icyphox.sh/atproto-oauth v0.0.0-20250724194903-28e660378cb1 h1:z1os1aRIqeo5e8d0Tx7hk+LH8OdZZeIOY0zw9VB/ZoU= 402 - tangled.sh/icyphox.sh/atproto-oauth v0.0.0-20250724194903-28e660378cb1/go.mod h1:+oQi9S6IIDll0nxLZVhuzOPX8WKLCYEnE6M5kUKupDg=
+2 -1
input.css
··· 172 172 @utility btn-muted { 173 173 border-radius: theme(borderRadius.md); 174 174 border-color: theme(--color-bg-dark); 175 - background-color: theme(colors.white); 175 + background-color: theme(--color-bg); 176 176 border-width: 1px; 177 + color: theme(--color-text-muted); 177 178 178 179 @variant hover { 179 180 opacity: 75%;
+3 -2
internal/server/config/config.go
··· 17 17 } 18 18 19 19 type OAuthConfig struct { 20 - Jwks string `env:"JWKS"` 20 + ClientSecret string `env:"CLIENT_SECRET"` 21 + ClientKid string `env:"CLIENT_KID"` 21 22 } 22 23 23 24 type JetstreamConfig struct { ··· 55 56 56 57 type Config struct { 57 58 Core CoreConfig `env:",prefix=YOTEN_"` 58 - Jetstream JetstreamConfig `env:",prefix=TANGLED_JETSTREAM_"` 59 + Jetstream JetstreamConfig `env:",prefix=YOTEN_JETSTREAM_"` 59 60 OAuth OAuthConfig `env:",prefix=YOTEN_OAUTH_"` 60 61 Posthog PosthogConfig `env:",prefix=YOTEN_POSTHOG_"` 61 62 Google GoogleConfig `env:",prefix=YOTEN_GOOGLE_"`
-24
internal/server/oauth/client/client.go
··· 1 - package client 2 - 3 - import ( 4 - oauth "tangled.sh/icyphox.sh/atproto-oauth" 5 - "tangled.sh/icyphox.sh/atproto-oauth/helpers" 6 - ) 7 - 8 - type OAuthClient struct { 9 - *oauth.Client 10 - } 11 - 12 - func NewClient(clientId, clientJwk, redirectUri string) (*OAuthClient, error) { 13 - k, err := helpers.ParseJWKFromBytes([]byte(clientJwk)) 14 - if err != nil { 15 - return nil, err 16 - } 17 - 18 - cli, err := oauth.NewClient(oauth.ClientArgs{ 19 - ClientId: clientId, 20 - ClientJwk: k, 21 - RedirectUri: redirectUri, 22 - }) 23 - return &OAuthClient{cli}, err 24 - }
+3 -25
internal/server/oauth/handler.go
··· 12 12 "github.com/bluesky-social/indigo/atproto/auth/oauth" 13 13 lexutil "github.com/bluesky-social/indigo/lex/util" 14 14 "github.com/go-chi/chi/v5" 15 - "github.com/lestrrat-go/jwx/v2/jwk" 16 15 "github.com/posthog/posthog-go" 17 16 18 17 "yoten.app/api/yoten" ··· 46 45 } 47 46 } 48 47 49 - func pubKeyFromJwk(jwks string) (jwk.Key, error) { 50 - k, err := jwk.ParseKey([]byte(jwks)) 51 - if err != nil { 52 - return nil, err 53 - } 54 - pubKey, err := k.PublicKey() 55 - if err != nil { 56 - return nil, err 57 - } 58 - return pubKey, nil 59 - } 60 - 61 48 func (o *OAuth) jwks(w http.ResponseWriter, r *http.Request) { 62 - jwks := o.Config.OAuth.Jwks 63 - pubKey, err := pubKeyFromJwk(jwks) 64 - if err != nil { 65 - o.Logger.Error("failed to parse public key", "err", err) 49 + w.Header().Set("Content-Type", "application/json") 50 + body := o.ClientApp.Config.PublicJWKS() 51 + if err := json.NewEncoder(w).Encode(body); err != nil { 66 52 http.Error(w, err.Error(), http.StatusInternalServerError) 67 53 return 68 54 } 69 - 70 - response := map[string]any{ 71 - "keys": []jwk.Key{pubKey}, 72 - } 73 - 74 - w.Header().Set("Content-Type", "application/json") 75 - w.WriteHeader(http.StatusOK) 76 - json.NewEncoder(w).Encode(response) 77 55 } 78 56 79 57 func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) {
+9
internal/server/oauth/oauth.go
··· 10 10 comatproto "github.com/bluesky-social/indigo/api/atproto" 11 11 "github.com/bluesky-social/indigo/atproto/auth/oauth" 12 12 atpclient "github.com/bluesky-social/indigo/atproto/client" 13 + atcrypto "github.com/bluesky-social/indigo/atproto/crypto" 13 14 "github.com/bluesky-social/indigo/atproto/syntax" 14 15 xrpc "github.com/bluesky-social/indigo/xrpc" 15 16 "github.com/gorilla/sessions" ··· 43 44 clientId := fmt.Sprintf("%s/oauth/client-metadata.json", clientUri) 44 45 callbackUri := clientUri + "/oauth/callback" 45 46 oauthConfig = oauth.NewPublicConfig(clientId, callbackUri, []string{"atproto", "transition:generic"}) 47 + } 48 + 49 + priv, err := atcrypto.ParsePrivateMultibase(config.OAuth.ClientSecret) 50 + if err != nil { 51 + return nil, err 52 + } 53 + if err := oauthConfig.SetClientSecret(priv, config.OAuth.ClientKid); err != nil { 54 + return nil, err 46 55 } 47 56 48 57 jwksUri := clientUri + "/oauth/jwks.json"

History

1 round 0 comments
sign up or login to add to the discussion
brookjeynes.dev submitted #0
3 commits
expand
fix: typos and style issues
feat: remove need for genjwks
chore: add assets
expand 0 comments
pull request successfully merged