//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) } }
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)) } } } } } } } }
//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) } } } } } } } }