···
type OAuthHandler struct {
-
Idresolver *idresolver.Resolver
-
Store *sessions.CookieStore
-
Enforcer *rbac.Enforcer
func (o *OAuthHandler) Router() http.Handler {
···
r.Post("/login", o.login)
-
r.With(middleware.AuthMiddleware(o.OAuth)).Post("/logout", o.logout)
r.Get("/oauth/client-metadata.json", o.clientMetadata)
r.Get("/oauth/jwks.json", o.jwks)
···
func (o *OAuthHandler) clientMetadata(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
-
json.NewEncoder(w).Encode(o.OAuth.ClientMetadata())
func (o *OAuthHandler) jwks(w http.ResponseWriter, r *http.Request) {
-
jwks := o.Config.OAuth.Jwks
pubKey, err := pubKeyFromJwk(jwks)
log.Printf("error parsing public key: %v", err)
···
func (o *OAuthHandler) login(w http.ResponseWriter, r *http.Request) {
-
o.Pages.Login(w, pages.LoginParams{})
handle := strings.TrimPrefix(r.FormValue("handle"), "@")
-
resolved, err := o.Idresolver.ResolveIdent(r.Context(), handle)
log.Println("failed to resolve handle:", err)
-
o.Pages.Notice(w, "login-msg", fmt.Sprintf("\"%s\" is an invalid handle.", handle))
-
self := o.OAuth.ClientMetadata()
oauthClient, err := client.NewClient(
log.Println("failed to create oauth client:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
authServer, err := oauthClient.ResolvePdsAuthServer(r.Context(), resolved.PDSEndpoint())
log.Println("failed to resolve auth server:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
authMeta, err := oauthClient.FetchAuthServerMetadata(r.Context(), authServer)
log.Println("failed to fetch auth server metadata:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
dpopKey, err := helpers.GenerateKey(nil)
log.Println("failed to generate dpop key:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
dpopKeyJson, err := json.Marshal(dpopKey)
log.Println("failed to marshal dpop key:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
parResp, err := oauthClient.SendParAuthRequest(r.Context(), authServer, authMeta, handle, oauthScope, dpopKey)
log.Println("failed to send par auth request:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
-
err = db.SaveOAuthRequest(o.Db, db.OAuthRequest{
Did: resolved.DID.String(),
PdsUrl: resolved.PDSEndpoint(),
···
log.Println("failed to save oauth request:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
···
query.Add("client_id", self.ClientID)
query.Add("request_uri", parResp.RequestUri)
u.RawQuery = query.Encode()
-
o.Pages.HxRedirect(w, u.String())
func (o *OAuthHandler) callback(w http.ResponseWriter, r *http.Request) {
state := r.FormValue("state")
-
oauthRequest, err := db.GetOAuthRequestByState(o.Db, state)
log.Println("failed to get oauth request:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
-
err := db.DeleteOAuthRequestByState(o.Db, state)
log.Println("failed to delete oauth request for state:", state, err)
···
errorDescription := r.FormValue("error_description")
if error != "" || errorDescription != "" {
log.Printf("error: %s, %s", error, errorDescription)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
code := r.FormValue("code")
log.Println("missing code for state: ", state)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
iss := r.FormValue("iss")
log.Println("missing iss for state: ", state)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
-
self := o.OAuth.ClientMetadata()
oauthClient, err := client.NewClient(
log.Println("failed to create oauth client:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
jwk, err := helpers.ParseJWKFromBytes([]byte(oauthRequest.DpopPrivateJwk))
log.Println("failed to parse jwk:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
···
log.Println("failed to get token:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
if tokenResp.Scope != oauthScope {
log.Println("scope doesn't match:", tokenResp.Scope)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
-
err = o.OAuth.SaveSession(w, r, oauthRequest, tokenResp)
log.Println("failed to save session:", err)
-
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
log.Println("session saved successfully")
go o.addToDefaultKnot(oauthRequest.Did)
-
if !o.Config.Core.Dev {
-
err = o.Posthog.Enqueue(posthog.Capture{
DistinctId: oauthRequest.Did,
···
func (o *OAuthHandler) logout(w http.ResponseWriter, r *http.Request) {
-
err := o.OAuth.ClearSession(r, w)
log.Println("failed to clear session:", err)
http.Redirect(w, r, "/", http.StatusFound)
···
defaultKnot := "knot1.tangled.sh"
log.Printf("adding %s to default knot", did)
-
err := o.Enforcer.AddMember(defaultKnot, did)
log.Println("failed to add user to knot1.tangled.sh: ", err)
-
err = o.Enforcer.E.SavePolicy()
log.Println("failed to add user to knot1.tangled.sh: ", err)
-
secret, err := db.GetRegistrationKey(o.Db, defaultKnot)
log.Println("failed to get registration key for knot1.tangled.sh")
-
signedClient, err := knotclient.NewSignedClient(defaultKnot, secret, o.Config.Core.Dev)
resp, err := signedClient.AddMember(did)
log.Println("failed to add user to knot1.tangled.sh: ", err)
···
type OAuthHandler struct {
+
idResolver *idresolver.Resolver
+
store *sessions.CookieStore
+
enforcer *rbac.Enforcer
+
idResolver *idresolver.Resolver,
+
store *sessions.CookieStore,
+
enforcer *rbac.Enforcer,
+
posthog posthog.Client,
+
idResolver: idResolver,
func (o *OAuthHandler) Router() http.Handler {
···
r.Post("/login", o.login)
+
r.With(middleware.AuthMiddleware(o.oauth)).Post("/logout", o.logout)
r.Get("/oauth/client-metadata.json", o.clientMetadata)
r.Get("/oauth/jwks.json", o.jwks)
···
func (o *OAuthHandler) clientMetadata(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
+
json.NewEncoder(w).Encode(o.oauth.ClientMetadata())
func (o *OAuthHandler) jwks(w http.ResponseWriter, r *http.Request) {
+
jwks := o.config.OAuth.Jwks
pubKey, err := pubKeyFromJwk(jwks)
log.Printf("error parsing public key: %v", err)
···
func (o *OAuthHandler) login(w http.ResponseWriter, r *http.Request) {
+
o.pages.Login(w, pages.LoginParams{})
handle := strings.TrimPrefix(r.FormValue("handle"), "@")
+
resolved, err := o.idResolver.ResolveIdent(r.Context(), handle)
log.Println("failed to resolve handle:", err)
+
o.pages.Notice(w, "login-msg", fmt.Sprintf("\"%s\" is an invalid handle.", handle))
+
self := o.oauth.ClientMetadata()
oauthClient, err := client.NewClient(
log.Println("failed to create oauth client:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
authServer, err := oauthClient.ResolvePdsAuthServer(r.Context(), resolved.PDSEndpoint())
log.Println("failed to resolve auth server:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
authMeta, err := oauthClient.FetchAuthServerMetadata(r.Context(), authServer)
log.Println("failed to fetch auth server metadata:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
dpopKey, err := helpers.GenerateKey(nil)
log.Println("failed to generate dpop key:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
dpopKeyJson, err := json.Marshal(dpopKey)
log.Println("failed to marshal dpop key:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
parResp, err := oauthClient.SendParAuthRequest(r.Context(), authServer, authMeta, handle, oauthScope, dpopKey)
log.Println("failed to send par auth request:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
+
err = db.SaveOAuthRequest(o.db, db.OAuthRequest{
Did: resolved.DID.String(),
PdsUrl: resolved.PDSEndpoint(),
···
log.Println("failed to save oauth request:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
···
query.Add("client_id", self.ClientID)
query.Add("request_uri", parResp.RequestUri)
u.RawQuery = query.Encode()
+
o.pages.HxRedirect(w, u.String())
func (o *OAuthHandler) callback(w http.ResponseWriter, r *http.Request) {
state := r.FormValue("state")
+
oauthRequest, err := db.GetOAuthRequestByState(o.db, state)
log.Println("failed to get oauth request:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
+
err := db.DeleteOAuthRequestByState(o.db, state)
log.Println("failed to delete oauth request for state:", state, err)
···
errorDescription := r.FormValue("error_description")
if error != "" || errorDescription != "" {
log.Printf("error: %s, %s", error, errorDescription)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
code := r.FormValue("code")
log.Println("missing code for state: ", state)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
iss := r.FormValue("iss")
log.Println("missing iss for state: ", state)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
+
self := o.oauth.ClientMetadata()
oauthClient, err := client.NewClient(
log.Println("failed to create oauth client:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
jwk, err := helpers.ParseJWKFromBytes([]byte(oauthRequest.DpopPrivateJwk))
log.Println("failed to parse jwk:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
···
log.Println("failed to get token:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
if tokenResp.Scope != oauthScope {
log.Println("scope doesn't match:", tokenResp.Scope)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
+
err = o.oauth.SaveSession(w, r, oauthRequest, tokenResp)
log.Println("failed to save session:", err)
+
o.pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
log.Println("session saved successfully")
go o.addToDefaultKnot(oauthRequest.Did)
+
if !o.config.Core.Dev {
+
err = o.posthog.Enqueue(posthog.Capture{
DistinctId: oauthRequest.Did,
···
func (o *OAuthHandler) logout(w http.ResponseWriter, r *http.Request) {
+
err := o.oauth.ClearSession(r, w)
log.Println("failed to clear session:", err)
http.Redirect(w, r, "/", http.StatusFound)
···
defaultKnot := "knot1.tangled.sh"
log.Printf("adding %s to default knot", did)
+
err := o.enforcer.AddMember(defaultKnot, did)
log.Println("failed to add user to knot1.tangled.sh: ", err)
+
err = o.enforcer.E.SavePolicy()
log.Println("failed to add user to knot1.tangled.sh: ", err)
+
secret, err := db.GetRegistrationKey(o.db, defaultKnot)
log.Println("failed to get registration key for knot1.tangled.sh")
+
signedClient, err := knotclient.NewSignedClient(defaultKnot, secret, o.config.Core.Dev)
resp, err := signedClient.AddMember(did)
log.Println("failed to add user to knot1.tangled.sh: ", err)