mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-01 15:56:58 +00:00
75 lines
2.7 KiB
Go
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)
|
|
}
|