forked from
tangled.org/core
Monorepo for Tangled
1package oauth
2
3import (
4 "encoding/json"
5 "log"
6 "net/http"
7
8 "github.com/go-chi/chi/v5"
9 "github.com/lestrrat-go/jwx/v2/jwk"
10 "github.com/posthog/posthog-go"
11)
12
13func (o *OAuth) Router() http.Handler {
14 r := chi.NewRouter()
15
16 r.Get("/oauth/client-metadata.json", o.clientMetadata)
17 r.Get("/oauth/jwks.json", o.jwks)
18 r.Get("/oauth/callback", o.callback)
19 return r
20}
21
22func (o *OAuth) clientMetadata(w http.ResponseWriter, r *http.Request) {
23 doc := o.ClientApp.Config.ClientMetadata()
24 doc.JWKSURI = &o.JwksUri
25
26 w.Header().Set("Content-Type", "application/json")
27 if err := json.NewEncoder(w).Encode(doc); err != nil {
28 http.Error(w, err.Error(), http.StatusInternalServerError)
29 return
30 }
31}
32
33func (o *OAuth) jwks(w http.ResponseWriter, r *http.Request) {
34 jwks := o.Config.OAuth.Jwks
35 pubKey, err := pubKeyFromJwk(jwks)
36 if err != nil {
37 log.Printf("error parsing public key: %v", err)
38 http.Error(w, err.Error(), http.StatusInternalServerError)
39 return
40 }
41
42 response := map[string]any{
43 "keys": []jwk.Key{pubKey},
44 }
45
46 w.Header().Set("Content-Type", "application/json")
47 w.WriteHeader(http.StatusOK)
48 json.NewEncoder(w).Encode(response)
49}
50
51func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) {
52 ctx := r.Context()
53
54 sessData, err := o.ClientApp.ProcessCallback(ctx, r.URL.Query())
55 if err != nil {
56 http.Error(w, err.Error(), http.StatusInternalServerError)
57 return
58 }
59
60 if err := o.SaveSession(w, r, sessData); err != nil {
61 http.Error(w, err.Error(), http.StatusInternalServerError)
62 return
63 }
64
65 if !o.Config.Core.Dev {
66 err = o.Posthog.Enqueue(posthog.Capture{
67 DistinctId: sessData.AccountDID.String(),
68 Event: "signin",
69 })
70 if err != nil {
71 log.Println("failed to enqueue posthog event:", err)
72 }
73 }
74
75 http.Redirect(w, r, "/", http.StatusFound)
76}