예제 #1
0
파일: signin.go 프로젝트: siim-/siil
func handleSigninRequest(rw http.ResponseWriter, rq *http.Request) {
	reqVars := mux.Vars(rq)

	if siteId, ok := reqVars["site"]; !ok || len(siteId) == 0 {
		http.Error(rw, "Site ID must be provided", http.StatusBadRequest)
		return
	} else {
		wanted := site.Entity{ClientId: 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 result, err := templates["signin.hbs"].Exec(wanted); err != nil {
			log.Println(err)
			http.Error(rw, "Something broke", http.StatusInternalServerError)
			return
		} else {
			rw.Write([]byte(result))
		}
	}
}
예제 #2
0
파일: api.go 프로젝트: siim-/siil
//Provide information about the active id card user
func handleAPIMeRequest(rw http.ResponseWriter, rq *http.Request) {
	switch rq.Method {
	case "GET":
		if !cert.ClientVerified(rq) {
			http.Error(rw, "Certificate not provided", http.StatusBadRequest)
		} else {
			if c, err := cert.NewCertFromRequest(rq); err != nil {
				http.Error(rw, "Certificate not provided", http.StatusBadRequest)
			} else {
				if clientId := rq.FormValue("client_id"); len(clientId) == 0 {
					http.Error(rw, "Invalid client_id provided", http.StatusBadRequest)
				} else {
					//Check origin header validity
					if origin := rq.Header.Get("Origin"); len(origin) != 0 {
						if u, err := url.Parse(origin); err != nil {
							http.Error(rw, "Invalid origin provided", http.StatusBadRequest)
							return
						} else {
							s := site.Entity{Domain: u.Host}
							if err := s.Load(); err == nil && s.ClientId == clientId {
								rw.Header().Set("Access-Control-Allow-Origin", origin)
								rw.Header().Set("Access-Control-Allow-Methods", "GET")
								rw.Header().Set("Access-Control-Allow-Credentials", "true")
							} else {
								http.Error(rw, "Origin not allowed", http.StatusUnauthorized)
								return
							}
						}
					}
					s := site.Entity{ClientId: clientId}
					if err := s.Load(); err != nil {
						http.Error(rw, "Invalid client_id provided", http.StatusBadRequest)
						return
					}
					if usr, err := user.Find(c); err != nil {
						http.Error(rw, "Looks like we don't know you", http.StatusUnauthorized)
					} else {
						if s.HasActiveSessionFor(usr) {
							enc := json.NewEncoder(rw)
							rw.Header().Set("Content-Type", "application/json")
							if err := enc.Encode(usr); err != nil {
								log.Println(err)
								http.Error(rw, "Failed to compose response", http.StatusInternalServerError)
							}
						} else {
							http.Error(rw, "Computer says no", http.StatusUnauthorized)
						}
					}
				}
			}
		}
	default:
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
	}
}
예제 #3
0
파일: signin.go 프로젝트: siim-/siil
func handleSessionCreation(rw http.ResponseWriter, rq *http.Request) {
	reqVars := mux.Vars(rq)

	if rq.Method != "POST" {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
	} else if siteId, ok := reqVars["site"]; !ok {
		http.Error(rw, "Site ID must be provided", http.StatusBadRequest)
	} else {
		wanted := site.Entity{ClientId: 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 !cert.ClientVerified(rq) {
			http.Error(rw, "Client certificate not provided. Please restart your browser to provide it.", 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 userEntity, err := user.FindOrCreate(userCert); err != nil {
					log.Println(err)
					http.Error(rw, "Something broke", http.StatusInternalServerError)
				} else {
					if sess, err := session.NewSession(&wanted, userEntity); err != nil {
						log.Println(err)
						http.Error(rw, "Something broke", http.StatusInternalServerError)
					} else {
						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", "signin")
							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))
							}
						}
					}
				}
			}
		}
	}
}
예제 #4
0
파일: editsite.go 프로젝트: siim-/siil
func checkSiteAndUserConnetion(rq *http.Request, siteId string) (*site.Entity, error) {
	owner, err := getOwnerFromSession(rq)
	if err != nil {
		return nil, err
	}

	s := site.Entity{ClientId: siteId}
	if err := s.Load(); err != nil {
		log.Println(err)
		return nil, errors.New("Failed to find site")
	}

	if s.Owner != owner {
		return nil, errors.New("Site owner doesn't match session owner.")
	}

	return &s, nil
}
예제 #5
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)
							}
						}
					}
				}
			}
		}
	}
}
예제 #6
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)
							}
						}
					}
				}
			}
		}
	}
}