// authenticate is called prior to processing incoming requests. it implements the client // authentication logic, which mostly consist of validating GPG signed tokens and setting the // identity of the signer in the request context func authenticate(pass handler, adminRequired bool) handler { return func(w http.ResponseWriter, r *http.Request) { var ( err error inv mig.Investigator ) opid := getOpID(r) context.Set(r, opID, opid) context.Set(r, apiRequestCategory, RequestCategoryInvestigator) if !ctx.Authentication.Enabled { inv.Name = "authdisabled" inv.ID = 0 inv.IsAdmin = true goto authorized } if r.Header.Get("X-PGPAUTHORIZATION") == "" { inv.Name = "authmissing" inv.ID = -1 resource := cljs.New(fmt.Sprintf("%s%s", ctx.Server.Host, r.URL.String())) resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: "X-PGPAUTHORIZATION header not found"}) respond(http.StatusUnauthorized, resource, w, r) return } inv, err = verifySignedToken(r.Header.Get("X-PGPAUTHORIZATION")) if err != nil { inv.Name = "authfailed" inv.ID = -1 resource := cljs.New(fmt.Sprintf("%s%s", ctx.Server.Host, r.URL.String())) resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: fmt.Sprintf("Authorization verification failed with error '%v'", err)}) respond(http.StatusUnauthorized, resource, w, r) return } authorized: // store investigator identity in request context context.Set(r, authenticatedInvName, inv.Name) context.Set(r, authenticatedInvID, inv.ID) context.Set(r, authenticatedInvIsAdmin, inv.IsAdmin) // Validate investigator is an administrator if required if adminRequired { if !inv.IsAdmin { inv.Name = "authfailed" inv.ID = -1 ctx.Channels.Log <- mig.Log{ OpID: getOpID(r), Desc: fmt.Sprintf("Investigator '%v' %v has insufficient privileges to access API function", getInvName(r), getInvID(r)), }.Info() resource := cljs.New(fmt.Sprintf("%s%s", ctx.Server.Host, r.URL.String())) resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: "Insufficient privileges"}) respond(http.StatusUnauthorized, resource, w, r) return } } // accept request pass(w, r) } }
// authenticate is called prior to processing incoming requests. it implements the client // authentication logic, which mostly consist of validating GPG signed tokens and setting the // identity of the signer in the request context func authenticate(pass handler) handler { return func(w http.ResponseWriter, r *http.Request) { var ( err error inv mig.Investigator ) opid := getOpID(r) context.Set(r, opID, opid) if !ctx.Authentication.Enabled { inv.Name = "authdisabled" inv.ID = 0 goto authorized } if r.Header.Get("X-PGPAUTHORIZATION") == "" { inv.Name = "authmissing" inv.ID = -1 resource := cljs.New(fmt.Sprintf("%s%s", ctx.Server.Host, r.URL.String())) resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: "X-PGPAUTHORIZATION header not found"}) respond(401, resource, w, r) return } inv, err = verifySignedToken(r.Header.Get("X-PGPAUTHORIZATION")) if err != nil { inv.Name = "authfailed" inv.ID = -1 resource := cljs.New(fmt.Sprintf("%s%s", ctx.Server.Host, r.URL.String())) resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: fmt.Sprintf("Authorization verification failed with error '%v'", err)}) respond(401, resource, w, r) return } authorized: // store investigator identity in request context context.Set(r, authenticatedInvName, inv.Name) context.Set(r, authenticatedInvID, inv.ID) // accept request pass(w, r) } }