An atproto PDS written in Go
103
fork

Configure Feed

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

at 8c7f03f9c80e688fc25a64ab838c78d4e0ef56d2 91 lines 2.8 kB view raw
1package server 2 3import ( 4 "context" 5 "fmt" 6 "strings" 7 8 "github.com/bluesky-social/indigo/atproto/atcrypto" 9 "github.com/bluesky-social/indigo/atproto/identity" 10 atproto_identity "github.com/bluesky-social/indigo/atproto/identity" 11 "github.com/bluesky-social/indigo/atproto/syntax" 12 "github.com/golang-jwt/jwt/v4" 13) 14 15type ES256KSigningMethod struct { 16 alg string 17} 18 19func (m *ES256KSigningMethod) Alg() string { 20 return m.alg 21} 22 23func (m *ES256KSigningMethod) Verify(signingString string, signature string, key interface{}) error { 24 signatureBytes, err := jwt.DecodeSegment(signature) 25 if err != nil { 26 return err 27 } 28 return key.(atcrypto.PublicKey).HashAndVerifyLenient([]byte(signingString), signatureBytes) 29} 30 31func (m *ES256KSigningMethod) Sign(signingString string, key interface{}) (string, error) { 32 return "", fmt.Errorf("unimplemented") 33} 34 35func init() { 36 ES256K := ES256KSigningMethod{alg: "ES256K"} 37 jwt.RegisterSigningMethod(ES256K.Alg(), func() jwt.SigningMethod { 38 return &ES256K 39 }) 40} 41 42func (s *Server) validateServiceAuth(ctx context.Context, rawToken string, nsid string) (string, error) { 43 token := strings.TrimSpace(rawToken) 44 45 parsedToken, err := jwt.ParseWithClaims(token, jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) { 46 did := syntax.DID(token.Claims.(jwt.MapClaims)["iss"].(string)) 47 didDoc, err := s.passport.FetchDoc(ctx, did.String()); 48 if err != nil { 49 return nil, fmt.Errorf("unable to resolve did %s: %s", did, err) 50 } 51 52 verificationMethods := make([]atproto_identity.DocVerificationMethod, len(didDoc.VerificationMethods)) 53 for i, verificationMethod := range didDoc.VerificationMethods { 54 verificationMethods[i] = atproto_identity.DocVerificationMethod{ 55 ID: verificationMethod.Id, 56 Type: verificationMethod.Type, 57 PublicKeyMultibase: verificationMethod.PublicKeyMultibase, 58 Controller: verificationMethod.Controller, 59 } 60 } 61 services := make([]atproto_identity.DocService, len(didDoc.Service)) 62 for i, service := range didDoc.Service { 63 services[i] = atproto_identity.DocService{ 64 ID: service.Id, 65 Type: service.Type, 66 ServiceEndpoint: service.ServiceEndpoint, 67 } 68 } 69 parsedIdentity := atproto_identity.ParseIdentity(&identity.DIDDocument{ 70 DID: did, 71 AlsoKnownAs: didDoc.AlsoKnownAs, 72 VerificationMethod: verificationMethods, 73 Service: services, 74 }) 75 76 key, err := parsedIdentity.PublicKey() 77 if err != nil { 78 return nil, fmt.Errorf("signing key not found for did %s: %s", did, err) 79 } 80 return key, nil 81 }) 82 if err != nil { 83 return "", fmt.Errorf("invalid token: %s", err) 84 } 85 86 claims := parsedToken.Claims.(jwt.MapClaims) 87 if claims["lxm"] != nsid { 88 return "", fmt.Errorf("bad jwt lexicon method (\"lxm\"). must match: %s", nsid) 89 } 90 return claims["iss"].(string), nil 91}