// gomuks - A terminal Matrix client written in Go. // Copyright (C) 2020 Tulir Asokan // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package matrix import ( "context" "errors" "net/http" "net/url" "time" "maunium.net/go/mautrix" "maunium.net/go/gomuks/debug" "maunium.net/go/gomuks/lib/open" ) const uiaFallbackPage = ` gomuks user-interactive auth

Please complete the login in the popup window

Keep this page open while logging in, it will close automatically after the login finishes.

` func (c *Container) UIAFallback(loginType mautrix.AuthType, sessionID string) error { errChan := make(chan error, 1) server := &http.Server{Addr: ":29325"} server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { w.Header().Add("Content-Type", "text/html") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(uiaFallbackPage)) } else if r.Method == "POST" || r.Method == "DELETE" { w.Header().Add("Content-Type", "text/html") w.WriteHeader(http.StatusOK) go func() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() err := server.Shutdown(ctx) if err != nil { debug.Printf("Failed to shut down SSO server: %v\n", err) } if r.Method == "DELETE" { errChan <- errors.New("login cancelled") } else { errChan <- nil } }() } else { w.WriteHeader(http.StatusMethodNotAllowed) } }) go server.ListenAndServe() defer server.Close() authURL := c.client.BuildURLWithQuery(mautrix.ClientURLPath{"v3", "auth", loginType, "fallback", "web"}, map[string]string{ "session": sessionID, }) link := url.URL{ Scheme: "http", Host: "localhost:29325", Path: "/", Fragment: authURL, } err := open.Open(link.String()) if err != nil { return err } err = <-errChan return err }