package server import ( "crypto/rand" "encoding/hex" "encoding/json" "io" "net/http" ) type AuthProvider interface { ProviderName() string ProviderID() *string ProviderType() string } type AuthProviderBase struct { Name string `json:"name"` ID *string `json:"id"` Type string `json:"type"` } func (bp *AuthProviderBase) ProviderName() string { return bp.Name } func (bp *AuthProviderBase) ProviderID() *string { return bp.ID } func (bp *AuthProviderBase) ProviderType() string { return bp.Type } type LocalProvider struct { AuthProviderBase } var HomeAssistant = "homeassistant" func hassProvider() *LocalProvider { return &LocalProvider{ AuthProviderBase: AuthProviderBase{ Name: "Home Assistant Local", Type: HomeAssistant, }, } } // TODO: make this configurable func (s *Server) providersHandler(w http.ResponseWriter, r *http.Request) { providers := []AuthProvider{ hassProvider(), } rjs, err := json.Marshal(providers) if err != nil { panic(err) } logRequest(http.StatusOK, r) w.Header()["Content-Type"] = []string{"application/json"} _, err = w.Write(rjs) if err != nil { panic(err) } } func (s *Server) authorizeHandler(w http.ResponseWriter, r *http.Request) { authPage, err := s.rootFS.Open("authorize.html") if err != nil { panic(err) } defer authPage.Close() logRequest(http.StatusOK, r) _, err = io.Copy(w, authPage) if err != nil { panic(err) } } type flowRequest struct { ClientID string `json:"client_id"` Handler []*string `json:"handler"` RedirectURI string `json:"redirect_uri"` } type FlowSchemaItem struct { Type string `json:"type"` Name string `json:"name"` Required bool `json:"required"` } type FlowType string const ( TypeForm FlowType = "form" ) type FlowID string type Step string const ( StepInit Step = "init" ) type flowResponse struct { Type FlowType `json:"type"` ID FlowID `json:"flow_id"` Handler []*string `json:"handler"` StepID Step `json:"step_id"` Schema []FlowSchemaItem `json:"data_schema"` Errors []string `json:"errors"` DescPlace *string `json:"description_placeholders"` LastStep *string `json:"last_step"` } func GenFlowID() FlowID { b := make([]byte, 16) if _, err := rand.Read(b); err != nil { panic(err) } return FlowID(hex.EncodeToString(b)) } func (s *Server) loginFlowHandler(w http.ResponseWriter, r *http.Request) { var flowReq flowRequest err := json.NewDecoder(r.Body).Decode(&flowReq) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } resp := flowResponse{ Type: TypeForm, ID: GenFlowID(), StepID: StepInit, Schema: []FlowSchemaItem{ { Type: "string", Name: "username", Required: true, }, { Type: "string", Name: "password", Required: true, }, }, Handler: []*string{ &HomeAssistant, nil, }, Errors: []string{}, } w.Header()["Content-Type"] = []string{"application/json"} respByte, err := json.Marshal(&resp) _, err = w.Write(respByte) if err != nil { panic(err) } }