main.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. //ClientInformationStruct 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. func main() {
  23. http.HandleFunc("/login", loginHandler)
  24. http.Handle("/asset/", http.StripPrefix("/asset/", http.FileServer(http.Dir("./asset"))))
  25. http.ListenAndServe(":8080", nil)
  26. }
  27. func loginHandler(w http.ResponseWriter, r *http.Request) {
  28. responseType, ok := r.URL.Query()["response_type"]
  29. if !ok || len(responseType[0]) < 1 {
  30. errHandler(w, r, "Url param response_type was missing")
  31. return
  32. }
  33. if string(responseType[0]) != "code" {
  34. errHandler(w, r, "Url param response_type was incompatible")
  35. return
  36. }
  37. clientID, ok := r.URL.Query()["client_id"]
  38. if !ok || len(clientID[0]) < 1 {
  39. errHandler(w, r, "Url param client_id was missing")
  40. return
  41. }
  42. redirectURI, ok := r.URL.Query()["redirect_uri"]
  43. if !ok || len(redirectURI[0]) < 1 {
  44. errHandler(w, r, "Url param redirect_uri was missing")
  45. return
  46. }
  47. redirectURIParsed, err := url.Parse(redirectURI[0])
  48. host, _, _ := net.SplitHostPort(redirectURIParsed.Host)
  49. scope, ok := r.URL.Query()["scope"]
  50. if !ok || len(scope[0]) < 1 {
  51. errHandler(w, r, "Url param scope was missing")
  52. return
  53. }
  54. state, ok := r.URL.Query()["state"]
  55. if !ok || len(state[0]) < 1 {
  56. errHandler(w, r, "Url param state was missing")
  57. return
  58. }
  59. nonce, ok := r.URL.Query()["nonce"]
  60. if !ok || len(nonce[0]) < 1 {
  61. errHandler(w, r, "Url param nonce was missing")
  62. return
  63. }
  64. //let say the GET request was good, then let us find does client-id and domain match our record
  65. data, err := ioutil.ReadFile("./client-id.json")
  66. if err != nil {
  67. fmt.Print(err)
  68. }
  69. var ClientsInformation ClientsInformationStruct
  70. err = json.Unmarshal(data, &ClientsInformation)
  71. if err != nil {
  72. fmt.Println("error:", err)
  73. }
  74. //process DB
  75. DBClientID := ""
  76. //DBClientSecret := ""
  77. DBDomain := ""
  78. DBServiceName := ""
  79. DBServiceImage := ""
  80. var DBScope []string
  81. for _, ClientInformation := range ClientsInformation {
  82. if ClientInformation.ClientID == clientID[0] {
  83. DBClientID = ClientInformation.ClientID
  84. //DBClientSecret = ClientInformation.ClientSecret
  85. DBDomain = ClientInformation.Domain
  86. DBServiceName = ClientInformation.ServiceName
  87. DBServiceImage = ClientInformation.ServiceImage
  88. DBScope = ClientInformation.Scope
  89. }
  90. }
  91. if DBClientID == "" {
  92. errHandler(w, r, "client_id does not exist in our database.")
  93. return
  94. }
  95. //check the record does it match
  96. if DBDomain != host {
  97. errHandler(w, r, "client_id and redirect_uri not match the system record.")
  98. return
  99. }
  100. //check if scope is available for that client
  101. scopeArr := strings.Split(scope[0], " ")
  102. for _, scopeItem := range scopeArr {
  103. if !contains(DBScope, scopeItem) {
  104. errHandler(w, r, "scope not match our system record.")
  105. return
  106. }
  107. }
  108. //serve file
  109. //push assembled data to page
  110. parsedPage, err := templateLoad("login.html", map[string]interface{}{
  111. "service-name": string(DBServiceName),
  112. "service-image": string(DBServiceImage),
  113. })
  114. if err != nil {
  115. log.Println("Error. Unable to show error. Additionally, the error page also had error.")
  116. }
  117. w.Write([]byte(parsedPage))
  118. }
  119. func errHandler(w http.ResponseWriter, r *http.Request, errorMsg string) {
  120. //push assembled data to page
  121. parsedPage, err := templateLoad("error.html", map[string]interface{}{
  122. "error": string(errorMsg),
  123. })
  124. if err != nil {
  125. log.Println("Error. Unable to show error. Additionally, the error page also had error.")
  126. }
  127. w.Write([]byte(parsedPage))
  128. //sendTextResponse(w, parsedPage)
  129. }
  130. func templateLoad(filename string, replacement map[string]interface{}) (string, error) {
  131. content, err := ioutil.ReadFile(filename)
  132. if err != nil {
  133. return "", nil
  134. }
  135. t := fasttemplate.New(string(content), "{{", "}}")
  136. s := t.ExecuteString(replacement)
  137. return string(s), nil
  138. }
  139. //https://ispycode.com/GO/Collections/Arrays/Check-if-item-is-in-array
  140. func contains(arr []string, str string) bool {
  141. for _, a := range arr {
  142. if a == str {
  143. return true
  144. }
  145. }
  146. return false
  147. }