this repo has no description
1package main
2
3import (
4 "context"
5 "fmt"
6 "log/slog"
7 "net/http"
8 "os"
9
10 oauth "github.com/haileyok/atproto-oauth-golang"
11 _ "github.com/joho/godotenv/autoload"
12 "github.com/labstack/echo/v4"
13 "github.com/lestrrat-go/jwx/v2/jwk"
14 slogecho "github.com/samber/slog-echo"
15 "github.com/urfave/cli/v2"
16)
17
18var (
19 ctx = context.Background()
20 serverAddr = os.Getenv("OAUTH_TEST_SERVER_ADDR")
21 serverUrlRoot = os.Getenv("OAUTH_TEST_SERVER_URL_ROOT")
22 serverMetadataUrl = fmt.Sprintf("%s/oauth/client-metadata.json", serverUrlRoot)
23 serverCallbackUrl = fmt.Sprintf("%s/callback", serverUrlRoot)
24 pdsUrl = os.Getenv("OAUTH_TEST_PDS_URL")
25)
26
27func main() {
28 app := &cli.App{
29 Name: "atproto-oauth-golang-tester",
30 Action: run,
31 }
32
33 if serverUrlRoot == "" {
34 panic(fmt.Errorf("no server url root set in env file"))
35 }
36
37 app.RunAndExitOnError()
38}
39
40type TestServer struct {
41 httpd *http.Server
42 e *echo.Echo
43 jwksResponse *oauth.JwksResponseObject
44}
45
46func run(cmd *cli.Context) error {
47 s, err := NewServer()
48 if err != nil {
49 panic(err)
50 }
51
52 s.run()
53
54 return nil
55}
56
57func NewServer() (*TestServer, error) {
58 e := echo.New()
59
60 e.Use(slogecho.New(slog.Default()))
61
62 fmt.Println("atproto oauth golang tester server")
63
64 b, err := os.ReadFile("./jwks.json")
65 if err != nil {
66 if os.IsNotExist(err) {
67 return nil, fmt.Errorf("could not find jwks.json. does it exist? hint: run `go run ./cmd/cmd generate-jwks --prefix demo` to create one.")
68 }
69 return nil, err
70 }
71
72 k, err := jwk.ParseKey(b)
73 if err != nil {
74 return nil, err
75 }
76
77 pubKey, err := k.PublicKey()
78 if err != nil {
79 return nil, err
80 }
81
82 httpd := &http.Server{
83 Addr: serverAddr,
84 Handler: e,
85 }
86
87 fmt.Println("starting http server...")
88
89 return &TestServer{
90 httpd: httpd,
91 e: e,
92 jwksResponse: oauth.CreateJwksResponseObject(pubKey),
93 }, nil
94}
95
96func (s *TestServer) run() error {
97 s.e.GET("/oauth/client-metadata.json", s.handleClientMetadata)
98 s.e.GET("/oauth/jwks.json", s.handleJwks)
99
100 if err := s.httpd.ListenAndServe(); err != nil {
101 return err
102 }
103
104 return nil
105}
106
107func (s *TestServer) handleClientMetadata(e echo.Context) error {
108 metadata := map[string]any{
109 "client_id": serverMetadataUrl,
110 "client_name": "Atproto Oauth Golang Tester",
111 "client_uri": serverUrlRoot,
112 "logo_uri": fmt.Sprintf("%s/logo.png", serverUrlRoot),
113 "tos_uri": fmt.Sprintf("%s/tos", serverUrlRoot),
114 "policy_url": fmt.Sprintf("%s/policy", serverUrlRoot),
115 "redirect_uris": []string{serverCallbackUrl},
116 "grant_types": []string{"authorization_code", "refresh_token"},
117 "response_types": []string{"code"},
118 "application_type": "web",
119 "dpop_bound_access_tokens": true,
120 "jwks_uri": fmt.Sprintf("%s/oauth/jwks.json", serverUrlRoot),
121 "scope": "atproto transition:generic",
122 "token_endpoint_auth_method": "private_key_jwt",
123 "token_endpoint_auth_signing_alg": "ES256",
124 }
125
126 return e.JSON(200, metadata)
127}
128
129func (s *TestServer) handleJwks(e echo.Context) error {
130 return e.JSON(200, s.jwksResponse)
131}