this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 93 lines 2.6 kB view raw
1package main 2 3import ( 4 "fmt" 5 "net/http" 6 "strings" 7 8 "github.com/bluesky-social/indigo/atproto/crypto" 9 "github.com/bluesky-social/indigo/atproto/identity" 10 "github.com/bluesky-social/indigo/atproto/syntax" 11 "github.com/golang-jwt/jwt/v5" 12) 13 14// The contents of this file have been borrowed from here: https://github.com/orthanc/bluesky-go-feeds/blob/f719f113f1afc9080e50b4b1f5ca239aa3073c79/web/auth.go#L20-L46 15// It essentially allows the signing method that atproto uses for JWT to be used when verifying the JWT that they send in requests 16 17const ( 18 ES256K = "ES256K" 19 ES256 = "ES256" 20) 21 22type AtProtoSigningMethod struct { 23 alg string 24} 25 26func (m *AtProtoSigningMethod) Alg() string { 27 return m.alg 28} 29 30func (m *AtProtoSigningMethod) Verify(signingString string, signature []byte, key interface{}) error { 31 err := key.(crypto.PublicKey).HashAndVerifyLenient([]byte(signingString), signature) 32 return err 33} 34 35func (m *AtProtoSigningMethod) Sign(signingString string, key interface{}) ([]byte, error) { 36 return nil, fmt.Errorf("unimplemented") 37} 38 39func init() { 40 ES256K := AtProtoSigningMethod{alg: "ES256K"} 41 jwt.RegisterSigningMethod(ES256K.Alg(), func() jwt.SigningMethod { 42 return &ES256K 43 }) 44 45 ES256 := AtProtoSigningMethod{alg: "ES256"} 46 jwt.RegisterSigningMethod(ES256.Alg(), func() jwt.SigningMethod { 47 return &ES256 48 }) 49 50} 51 52var directory = identity.DefaultDirectory() 53 54func getRequestUserDID(r *http.Request) (string, error) { 55 headerValues := r.Header["Authorization"] 56 57 if len(headerValues) != 1 { 58 return "", fmt.Errorf("missing authorization header") 59 } 60 token := strings.TrimSpace(strings.Replace(headerValues[0], "Bearer ", "", 1)) 61 62 keyfunc := func(token *jwt.Token) (interface{}, error) { 63 did := syntax.DID(token.Claims.(jwt.MapClaims)["iss"].(string)) 64 identity, err := directory.LookupDID(r.Context(), did) 65 if err != nil { 66 return nil, fmt.Errorf("unable to resolve did %s: %s", did, err) 67 } 68 key, err := identity.PublicKey() 69 if err != nil { 70 return nil, fmt.Errorf("signing key not found for did %s: %s", did, err) 71 } 72 return key, nil 73 } 74 75 validMethods := jwt.WithValidMethods([]string{ES256, ES256K}) 76 77 parsedToken, err := jwt.ParseWithClaims(token, jwt.MapClaims{}, keyfunc, validMethods) 78 if err != nil { 79 return "", fmt.Errorf("invalid token: %s", err) 80 } 81 82 claims, ok := parsedToken.Claims.(jwt.MapClaims) 83 if !ok { 84 return "", fmt.Errorf("token contained no claims") 85 } 86 87 issVal, ok := claims["iss"].(string) 88 if !ok { 89 return "", fmt.Errorf("iss claim missing") 90 } 91 92 return string(syntax.DID(issVal)), nil 93}