package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net" "net/http" "net/url" "strings" "github.com/valyala/fasttemplate" ) //ClientsInformationStruct export type ClientsInformationStruct []struct { ClientID string `json:"client-id"` ClientSecret string `json:"client-secret"` Domain string `json:"domain"` ServiceName string `json:"service-name"` ServiceImage string `json:"service-image"` Scope []string `json:"scope"` } //UsersInformationStruct shouldn be exported type UsersInformationStruct []struct { Scope []struct { Name string `json:"name"` Value string `json:"value"` } `json:"scope"` Granted []struct { ClientID struct { Scope []string `json:"scope"` Status string `json:"status"` } `json:"client-id"` } `json:"granted"` } func main() { http.HandleFunc("/login", loginHandler) http.HandleFunc("/chklogin", chkloginHandler) http.Handle("/asset/", http.StripPrefix("/asset/", http.FileServer(http.Dir("./asset")))) http.ListenAndServe(":8080", nil) } func loginHandler(w http.ResponseWriter, r *http.Request) { _, _, ServiceName, ServiceImage, responseType, clientID, redirectURI, scope, state, nonce := confirmClientInformation(w, r) //serve file //push assembled data to page parsedPage, err := templateLoad("login.html", map[string]interface{}{ "service-name": string(ServiceName), "service-image": string(ServiceImage), "response_type": string(responseType), "client_id": string(clientID), "redirect_uri": string(redirectURI), "scope": string(scope), "state": string(state), "nonce": string(nonce), }) if err != nil { log.Println("Error. Unable to load login.html") } w.Write([]byte(parsedPage)) } func chkloginHandler(w http.ResponseWriter, r *http.Request) { // Call ParseForm() to parse the raw query and update r.PostForm and r.Form. if err := r.ParseForm(); err != nil { errHandler(w, r, "Missing post parameter") } data, err := ioutil.ReadFile("./user.json") if err != nil { fmt.Print(err) } var UsersInformation UsersInformationStruct err = json.Unmarshal(data, &UsersInformation) email := r.FormValue("email") password := r.FormValue("password") fmt.Println(email, password) } func errHandler(w http.ResponseWriter, r *http.Request, errorMsg string) { //push assembled data to page parsedPage, err := templateLoad("error.html", map[string]interface{}{ "error": string(errorMsg), }) if err != nil { log.Println("Error. Unable to show error. Additionally, the error page also had error.") } w.Write([]byte(parsedPage)) //sendTextResponse(w, parsedPage) } func confirmClientInformation(w http.ResponseWriter, r *http.Request) (string, string, string, string, string, string, string, string, string, string) { responseType := getGET(w, r, "response_type") if string(responseType) != "code" { errHandler(w, r, "Url param response_type was incompatible") } // clientID := getGET(w, r, "client_id") // redirectURI := getGET(w, r, "redirect_uri") redirectURIParsed, err := url.Parse(redirectURI) host, _, _ := net.SplitHostPort(redirectURIParsed.Host) // scope := getGET(w, r, "scope") state := getGET(w, r, "state") nonce := getGET(w, r, "nonce") //let say the GET request was good, then let us find does client-id and domain match our record data, err := ioutil.ReadFile("./client-id.json") if err != nil { fmt.Print(err) } var ClientsInformation ClientsInformationStruct err = json.Unmarshal(data, &ClientsInformation) if err != nil { fmt.Println("error:", err) } //process DB DBClientID := "" DBClientSecret := "" DBDomain := "" DBServiceName := "" DBServiceImage := "" var DBScope []string for _, ClientInformation := range ClientsInformation { if ClientInformation.ClientID == clientID { DBClientID = ClientInformation.ClientID DBClientSecret = ClientInformation.ClientSecret DBDomain = ClientInformation.Domain DBServiceName = ClientInformation.ServiceName DBServiceImage = ClientInformation.ServiceImage DBScope = ClientInformation.Scope } } if DBClientID == "" { errHandler(w, r, "client_id does not exist in our database.") } //check the record does it match if DBDomain != host { errHandler(w, r, "client_id and redirect_uri not match the system record.") } //check if scope is available for that client scopeArr := strings.Split(scope, " ") for _, scopeItem := range scopeArr { if !contains(DBScope, scopeItem) { errHandler(w, r, "scope not match our system record.") } } return DBClientSecret, DBDomain, DBServiceName, DBServiceImage, responseType, clientID, redirectURI, scope, state, nonce } func confirmUserInfo(w http.ResponseWriter, r *http.Request, username string) { } func getGET(w http.ResponseWriter, r *http.Request, name string) string { response, ok := r.URL.Query()[name] if !ok || len(response[0]) < 1 { errHandler(w, r, "Url param "+name+" was missing") } return response[0] } func templateLoad(filename string, replacement map[string]interface{}) (string, error) { content, err := ioutil.ReadFile(filename) if err != nil { return "", nil } t := fasttemplate.New(string(content), "{{", "}}") s := t.ExecuteString(replacement) return string(s), nil } //https://ispycode.com/GO/Collections/Arrays/Check-if-item-is-in-array func contains(arr []string, str string) bool { for _, a := range arr { if a == str { return true } } return false }