Files
at-container-registry/pkg/labeler/identity.go
T
2026-05-03 20:49:56 -05:00

75 lines
2.7 KiB
Go

package labeler
import (
"context"
"encoding/json"
"fmt"
"net/http"
"atcr.io/pkg/atproto/did"
"atcr.io/pkg/auth/oauth"
"github.com/bluesky-social/indigo/atproto/atcrypto"
)
// labelerServices returns the service entries the labeler publishes in its DID document
// and PLC operations: a single AtprotoLabeler endpoint at #atproto_labeler.
func labelerServices(publicURL string) map[string]did.Service {
return map[string]did.Service{
"atproto_labeler": {Type: "AtprotoLabeler", Endpoint: publicURL},
}
}
// LoadIdentity resolves the labeler's DID and loads its k256 signing key.
// For did:plc this calls into the shared PLC package (loading or creating); for did:web
// the DID is derived from PublicURL and the signing key is generated on disk if missing.
func LoadIdentity(ctx context.Context, cfg *Config) (string, *atcrypto.PrivateKeyK256, error) {
labelerDID, err := did.LoadOrCreate(ctx, did.Config{
Method: cfg.Labeler.DIDMethod,
PublicURL: cfg.PublicURL(),
DBPath: cfg.Labeler.DataDir,
SigningKeyPath: cfg.SigningKeyPath(),
RotationKey: cfg.Labeler.RotationKey,
PLCDirectoryURL: cfg.PLCDirectoryURL(),
DID: cfg.Labeler.DID,
VerificationKeyName: "atproto_label",
Services: labelerServices(cfg.PublicURL()),
})
if err != nil {
return "", nil, fmt.Errorf("labeler: failed to resolve DID: %w", err)
}
signingKey, err := oauth.GenerateOrLoadPDSKey(cfg.SigningKeyPath())
if err != nil {
return "", nil, fmt.Errorf("labeler: failed to load signing key: %w", err)
}
return labelerDID, signingKey, nil
}
func (s *Server) handleDIDDocument(w http.ResponseWriter, r *http.Request) {
doc, err := did.BuildDIDDocument(s.did, s.config.PublicURL(), s.signingKey, "atproto_label", labelerServices(s.config.PublicURL()))
if err != nil {
http.Error(w, "failed to build DID document", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(doc)
}
func (s *Server) handleClientMetadata(w http.ResponseWriter, r *http.Request) {
publicURL := s.config.PublicURL()
metadata := map[string]any{
"client_id": publicURL + "/oauth-client-metadata.json",
"client_name": s.config.Labeler.ClientName,
"client_uri": publicURL,
"redirect_uris": []string{publicURL + "/auth/oauth/callback"},
"scope": "atproto",
"grant_types": []string{"authorization_code"},
"response_types": []string{"code"},
"token_endpoint_auth_method": "none",
"application_type": "web",
"dpop_bound_access_tokens": true,
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(metadata)
}