Live video on the AT Protocol
1package oproxy
2
3import (
4 "context"
5 "fmt"
6 "net/http"
7
8 "github.com/bluesky-social/indigo/xrpc"
9 oauth "github.com/haileyok/atproto-oauth-golang"
10 "github.com/labstack/echo/v4"
11 "github.com/lestrrat-go/jwx/v2/jwk"
12)
13
14var xrpcClient *oauth.XrpcClient
15
16type XrpcClient struct {
17 client *oauth.XrpcClient
18 authArgs *oauth.XrpcAuthedRequestArgs
19}
20
21func (o *OProxy) GetXrpcClient(session *OAuthSession) (*XrpcClient, error) {
22 key, err := jwk.ParseKey([]byte(session.UpstreamDPoPPrivateJWK))
23 if err != nil {
24 return nil, fmt.Errorf("failed to parse DPoP private JWK: %w", err)
25 }
26 authArgs := &oauth.XrpcAuthedRequestArgs{
27 Did: session.DID,
28 AccessToken: session.UpstreamAccessToken,
29 PdsUrl: session.PDSUrl,
30 Issuer: session.UpstreamAuthServerIssuer,
31 DpopPdsNonce: session.UpstreamDPoPNonce,
32 DpopPrivateJwk: key,
33 }
34
35 xrpcClient := &oauth.XrpcClient{
36 OnDpopPdsNonceChanged: func(did, newNonce string) {
37 sess, err := o.loadOAuthSession(session.DownstreamDPoPJKT)
38 if err != nil {
39 o.slog.Error("failed to get OAuth session in OnDpopPdsNonceChanged", "error", err)
40 return
41 }
42 sess.UpstreamDPoPNonce = newNonce
43 err = o.updateOAuthSession(session.DownstreamDPoPJKT, sess)
44 if err != nil {
45 o.slog.Error("failed to update OAuth session in OnDpopPdsNonceChanged", "error", err)
46 }
47 },
48 }
49 return &XrpcClient{client: xrpcClient, authArgs: authArgs}, nil
50}
51
52func (c *XrpcClient) Do(ctx context.Context, kind xrpc.XRPCRequestType, inpenc, method string, params map[string]any, bodyobj any, out any) error {
53 err := c.client.Do(ctx, c.authArgs, kind, inpenc, method, params, bodyobj, out)
54 if err == nil {
55 return nil
56 }
57 xErr, ok := err.(*xrpc.Error)
58 if !ok {
59 return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
60 }
61 return echo.NewHTTPError(xErr.StatusCode, xErr.Error())
62}