예제 #1
0
파일: main.go 프로젝트: siim-/siil
//Handle the root request
func handleRootRequest(rw http.ResponseWriter, rq *http.Request) {
	//Detect if the user is authenticated with Siil
	authenticated := false
	token := ""
	if tokenCookie, err := rq.Cookie("token"); err == nil {
		token = tokenCookie.Value
		if sess, err := session.GetSession(token); err == nil {
			authenticated = sess.SiteId == site.SIIL_SITE_ID
		}
	}

	if authenticated {
		owner, err := getOwnerFromSession(rq)
		if err != nil {
			log.Println(err)
			http.Redirect(rw, rq, "/signin/"+site.SIIL_SITE_ID, http.StatusFound)
			return
		}

		usr, err := user.FindById(int(owner))
		if err != nil {
			log.Println(err)
			http.Error(rw, "Invalid user", http.StatusInternalServerError)
			return
		}

		var sections string = ""
		sites, err := site.GetUsersSites(owner)
		if err != nil {
			log.Println(err)
			return
		} else {
			for _, s := range sites {
				titleArea := surroundWithRow(title(s.Name) + button(s.ClientId))
				descriptionListArea := surroundWithRow(surroundWithColumn(getDescriptionList(&s), "twelve"))
				sections += surroundWithSection(titleArea + descriptionListArea)
			}
		}

		response, err := templates["index.hbs"].Exec(map[string]interface{}{
			"Sections":   sections,
			"authed":     authenticated,
			"first_name": usr.FirstName,
			"last_name":  usr.LastName,
			"site_id":    site.SIIL_SITE_ID,
			"token":      token,
		})
		if err != nil {
			http.Error(rw, "Something broke", http.StatusInternalServerError)
		} else {
			rw.Write([]byte(response))
		}
	} else {
		if t, err := templates["index.hbs"].Exec(map[string]interface{}{"authed": authenticated, "site_id": site.SIIL_SITE_ID, "token": token}); err != nil {
			http.Error(rw, "Something broke", http.StatusInternalServerError)
		} else {
			rw.Write([]byte(t))
		}
	}
}
예제 #2
0
파일: functions.go 프로젝트: siim-/siil
func getOwnerFromSession(rq *http.Request) (uint, error) {
	cookie, err := rq.Cookie("token")
	if err != nil {
		return 0, err
	}

	session, err := session.GetSession(cookie.Value)
	if err != nil {
		return 0, err
	}

	return uint(session.UserId), nil
}
예제 #3
0
파일: signin.go 프로젝트: siim-/siil
func handleSuccessRequest(rw http.ResponseWriter, rq *http.Request) {
	if rq.Method != "POST" {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
	} else {
		switch rq.FormValue("siil_action") {
		case "signin":
			if token := rq.FormValue("token"); len(token) != session.TOKEN_LENGTH {
				http.Error(rw, "Invalid token provided", http.StatusBadRequest)
			} else {
				if _, err := session.GetSession(token); err != nil {
					log.Fatal(err)
					http.Error(rw, "No session", http.StatusUnauthorized)
				} else {
					cookie := http.Cookie{
						Name:  "token",
						Value: token,
					}
					http.SetCookie(rw, &cookie)
					http.Redirect(rw, rq, "/", http.StatusFound)
				}
			}
		case "signout":
			//Just clear the token cookie
			cookie := http.Cookie{
				Name:    "token",
				Value:   "lel",
				Expires: time.Now().UTC().Add(time.Minute * -2),
			}
			http.SetCookie(rw, &cookie)
			http.Redirect(rw, rq, "/", http.StatusFound)
		default:
			http.Error(rw, "Invalid action provided", http.StatusBadRequest)
		}

	}
}
예제 #4
0
파일: signout.go 프로젝트: siim-/siil
//Invalidate the session
func handleSignoutRequest(rw http.ResponseWriter, rq *http.Request) {
	if rq.Method != "POST" {
		http.Error(rw, "Invalid method", http.StatusMethodNotAllowed)
	} else {
		reqVars := mux.Vars(rq)
		if token, ok := reqVars["token"]; !ok || len(token) != session.TOKEN_LENGTH {
			http.Error(rw, "Bad token provided", http.StatusBadRequest)
		} else {
			if sess, err := session.GetSession(token); err != nil {
				http.Error(rw, "Session not found", http.StatusUnauthorized)
			} else {
				if !cert.ClientVerified(rq) {
					http.Error(rw, "Cert not provided", http.StatusBadRequest)
				} else {
					if userCert, err := cert.NewCertFromRequest(rq); err != nil {
						log.Println(err)
						http.Error(rw, "Failed to parse your client cert", http.StatusBadRequest)
					} else {
						if usr, err := user.Find(userCert); err != nil {
							log.Println(err)
							http.Error(rw, "We don't know you", http.StatusUnauthorized)
						} else {
							if usr.Id == sess.UserId {
								if err := sess.Delete(); err != nil {
									http.Error(rw, "Failed to end session", http.StatusInternalServerError)
								} else {
									wanted := site.Entity{ClientId: sess.SiteId}
									if err := wanted.Load(); err != nil {
										log.Println(err)
										if strings.Contains(err.Error(), "no rows") {
											http.Error(rw, "Site not found", http.StatusNotFound)
										} else {
											http.Error(rw, "Something broke", http.StatusInternalServerError)
										}
										return
									}
									if callback, err := url.Parse(wanted.CallbackURL); err != nil {
										http.Error(rw, "Invalid callback URL provided", http.StatusInternalServerError)
									} else {
										//Indicate signin action with GET parameter
										q := callback.Query()
										q.Set("siil_action", "signout")
										callback.RawQuery = q.Encode()
										if t, err := templates["success.hbs"].Exec(map[string]string{"token": sess.Token, "callback": callback.String()}); err != nil {
											log.Println(err)
											http.Error(rw, "Something broke", http.StatusInternalServerError)
										} else {
											rw.Write([]byte(t))
										}
									}
								}
							} else {
								http.Error(rw, "Session and user don't match", http.StatusBadRequest)
							}
						}
					}
				}
			}
		}
	}
}
예제 #5
0
파일: api.go 프로젝트: siim-/siil
//Provide JSON encoded information about the user related to this session
func handleAPISessionRequest(rw http.ResponseWriter, rq *http.Request) {
	if rq.Method != "GET" {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
	} else {
		if token, clientId := rq.FormValue("token"), rq.FormValue("client_id"); len(token) != session.TOKEN_LENGTH || len(clientId) != site.CLIENT_ID_LENGTH {
			http.Error(rw, "Invalid request", http.StatusBadRequest)
		} else {
			if sess, err := session.GetSession(token); err != nil {
				log.Println(err)
				http.Error(rw, "Not found", http.StatusNotFound)
			} else {
				//Check the client id's
				if sess.SiteId != clientId {
					http.Error(rw, "Unauthorized", http.StatusUnauthorized)
					return
				}
				s := site.Entity{ClientId: sess.SiteId}
				if err := s.Load(); err != nil {
					log.Println(err)
					http.Error(rw, "Not found", http.StatusNotFound)
					return
				}

				//Lets check the X-Authorization header
				if sig := rq.Header.Get("X-Authorization"); len(sig) == 0 {
					http.Error(rw, "Unauthorized (Missing signature in X-Authorization)", http.StatusUnauthorized)
				} else {
					sigHMAC, err := base64.StdEncoding.DecodeString(sig)
					if err != nil {
						log.Println(err)
						http.Error(rw, "Invalid signature provided", http.StatusUnauthorized)
						return
					}
					ourMAC := hmac.New(sha512.New, []byte(s.PrivateKey))
					ourMAC.Write([]byte(fmt.Sprintf("%s\t%s", clientId, token)))

					if !hmac.Equal(sigHMAC, ourMAC.Sum(nil)) {
						http.Error(rw, "Invalid signature provided", http.StatusUnauthorized)
					} else {
						if usr, err := user.FindById(sess.UserId); err != nil {
							log.Println(err)
							http.Error(rw, "Not found", http.StatusNotFound)
						} else {
							response := apiResponse{
								Token:     token,
								ExpiresAt: sess.ExpiresAt.Format(time.RFC3339),
								CreatedAt: sess.CreatedAt.Format(time.RFC3339),
								User:      usr,
								Site:      clientId,
							}

							//Generate verification HMAC
							verHMAC := hmac.New(sha512.New, []byte(s.PrivateKey))

							if m, err := json.Marshal(response); err != nil {
								log.Println(err)
								http.Error(rw, "Failed to sign response", http.StatusInternalServerError)
							} else {
								verHMAC.Write(m)
							}

							response.Verification = base64.StdEncoding.EncodeToString(verHMAC.Sum(nil))
							enc := json.NewEncoder(rw)
							rw.Header().Set("Content-Type", "application/json")
							if err := enc.Encode(response); err != nil {
								log.Println(err)
								http.Error(rw, "Failed to compose response", http.StatusInternalServerError)
							}
						}
					}
				}
			}
		}
	}
}