main.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "log"
  7. "net"
  8. "net/http"
  9. "net/url"
  10. "strings"
  11. "github.com/valyala/fasttemplate"
  12. )
  13. //ClientsInformationStruct export
  14. type ClientsInformationStruct []struct {
  15. ClientID string `json:"client-id"`
  16. ClientSecret string `json:"client-secret"`
  17. Domain string `json:"domain"`
  18. ServiceName string `json:"service-name"`
  19. ServiceImage string `json:"service-image"`
  20. Scope []string `json:"scope"`
  21. }
  22. //UsersInformationStruct shouldn be exported
  23. type UsersInformationStruct []struct {
  24. Scope []struct {
  25. Name string `json:"name"`
  26. Value string `json:"value"`
  27. } `json:"scope"`
  28. Granted []struct {
  29. ClientID struct {
  30. Scope []string `json:"scope"`
  31. Status string `json:"status"`
  32. } `json:"client-id"`
  33. } `json:"granted"`
  34. }
  35. func main() {
  36. http.HandleFunc("/login", loginHandler)
  37. http.HandleFunc("/chklogin", chkloginHandler)
  38. http.Handle("/asset/", http.StripPrefix("/asset/", http.FileServer(http.Dir("./asset"))))
  39. http.ListenAndServe(":8080", nil)
  40. }
  41. func loginHandler(w http.ResponseWriter, r *http.Request) {
  42. _, _, ServiceName, ServiceImage, responseType, clientID, redirectURI, scope, state, nonce := confirmClientInformation(w, r)
  43. //serve file
  44. //push assembled data to page
  45. parsedPage, err := templateLoad("login.html", map[string]interface{}{
  46. "service-name": string(ServiceName),
  47. "service-image": string(ServiceImage),
  48. "response_type": string(responseType),
  49. "client_id": string(clientID),
  50. "redirect_uri": string(redirectURI),
  51. "scope": string(scope),
  52. "state": string(state),
  53. "nonce": string(nonce),
  54. })
  55. if err != nil {
  56. log.Println("Error. Unable to load login.html")
  57. }
  58. w.Write([]byte(parsedPage))
  59. }
  60. func chkloginHandler(w http.ResponseWriter, r *http.Request) {
  61. // Call ParseForm() to parse the raw query and update r.PostForm and r.Form.
  62. if err := r.ParseForm(); err != nil {
  63. errHandler(w, r, "Missing post parameter")
  64. }
  65. data, err := ioutil.ReadFile("./user.json")
  66. if err != nil {
  67. fmt.Print(err)
  68. }
  69. var UsersInformation UsersInformationStruct
  70. err = json.Unmarshal(data, &UsersInformation)
  71. email := r.FormValue("email")
  72. password := r.FormValue("password")
  73. fmt.Println(email, password)
  74. }
  75. func errHandler(w http.ResponseWriter, r *http.Request, errorMsg string) {
  76. //push assembled data to page
  77. parsedPage, err := templateLoad("error.html", map[string]interface{}{
  78. "error": string(errorMsg),
  79. })
  80. if err != nil {
  81. log.Println("Error. Unable to show error. Additionally, the error page also had error.")
  82. }
  83. w.Write([]byte(parsedPage))
  84. //sendTextResponse(w, parsedPage)
  85. }
  86. func confirmClientInformation(w http.ResponseWriter, r *http.Request) (string, string, string, string, string, string, string, string, string, string) {
  87. responseType := getGET(w, r, "response_type")
  88. if string(responseType) != "code" {
  89. errHandler(w, r, "Url param response_type was incompatible")
  90. }
  91. //
  92. clientID := getGET(w, r, "client_id")
  93. //
  94. redirectURI := getGET(w, r, "redirect_uri")
  95. redirectURIParsed, err := url.Parse(redirectURI)
  96. host, _, _ := net.SplitHostPort(redirectURIParsed.Host)
  97. //
  98. scope := getGET(w, r, "scope")
  99. state := getGET(w, r, "state")
  100. nonce := getGET(w, r, "nonce")
  101. //let say the GET request was good, then let us find does client-id and domain match our record
  102. data, err := ioutil.ReadFile("./client-id.json")
  103. if err != nil {
  104. fmt.Print(err)
  105. }
  106. var ClientsInformation ClientsInformationStruct
  107. err = json.Unmarshal(data, &ClientsInformation)
  108. if err != nil {
  109. fmt.Println("error:", err)
  110. }
  111. //process DB
  112. DBClientID := ""
  113. DBClientSecret := ""
  114. DBDomain := ""
  115. DBServiceName := ""
  116. DBServiceImage := ""
  117. var DBScope []string
  118. for _, ClientInformation := range ClientsInformation {
  119. if ClientInformation.ClientID == clientID {
  120. DBClientID = ClientInformation.ClientID
  121. DBClientSecret = ClientInformation.ClientSecret
  122. DBDomain = ClientInformation.Domain
  123. DBServiceName = ClientInformation.ServiceName
  124. DBServiceImage = ClientInformation.ServiceImage
  125. DBScope = ClientInformation.Scope
  126. }
  127. }
  128. if DBClientID == "" {
  129. errHandler(w, r, "client_id does not exist in our database.")
  130. }
  131. //check the record does it match
  132. if DBDomain != host {
  133. errHandler(w, r, "client_id and redirect_uri not match the system record.")
  134. }
  135. //check if scope is available for that client
  136. scopeArr := strings.Split(scope, " ")
  137. for _, scopeItem := range scopeArr {
  138. if !contains(DBScope, scopeItem) {
  139. errHandler(w, r, "scope not match our system record.")
  140. }
  141. }
  142. return DBClientSecret, DBDomain, DBServiceName, DBServiceImage, responseType, clientID, redirectURI, scope, state, nonce
  143. }
  144. func confirmUserInfo(w http.ResponseWriter, r *http.Request, username string) {
  145. }
  146. func getGET(w http.ResponseWriter, r *http.Request, name string) string {
  147. response, ok := r.URL.Query()[name]
  148. if !ok || len(response[0]) < 1 {
  149. errHandler(w, r, "Url param "+name+" was missing")
  150. }
  151. return response[0]
  152. }
  153. func templateLoad(filename string, replacement map[string]interface{}) (string, error) {
  154. content, err := ioutil.ReadFile(filename)
  155. if err != nil {
  156. return "", nil
  157. }
  158. t := fasttemplate.New(string(content), "{{", "}}")
  159. s := t.ExecuteString(replacement)
  160. return string(s), nil
  161. }
  162. //https://ispycode.com/GO/Collections/Arrays/Check-if-item-is-in-array
  163. func contains(arr []string, str string) bool {
  164. for _, a := range arr {
  165. if a == str {
  166. return true
  167. }
  168. }
  169. return false
  170. }