// UpdateAPIKey is the handler for PUT /organizations/{globalid}/apikeys/{label} // Updates the label or other properties of a key. func (api OrganizationsAPI) UpdateAPIKey(w http.ResponseWriter, r *http.Request) { organization := mux.Vars(r)["globalid"] oldlabel := mux.Vars(r)["label"] apiKey := APIKey{} if err := json.NewDecoder(r.Body).Decode(&apiKey); err != nil { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } if !isValidAPIKeyLabel(apiKey.Label) { log.Debug("Invalid label: ", apiKey.Label) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } mgr := oauthservice.NewManager(r) err := mgr.UpdateClient(organization, oldlabel, apiKey.Label, apiKey.CallbackURL, apiKey.ClientCredentialsGrantType) if err != nil && db.IsDup(err) { log.Debug("Duplicate label") http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict) return } if err != nil { log.Error("Error renaming api secret label", err.Error()) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) }
// Handler return HTTP handler representation of this middleware func (om *Oauth2oauth_2_0Middleware) Handler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var atscopestring string var username string accessToken := om.GetAccessToken(r) if accessToken != "" { //TODO: cache oauthMgr := oauthservice.NewManager(r) at, err := oauthMgr.GetAccessToken(accessToken) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if at == nil { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } atscopestring = at.Scope username = at.Username } else { w.WriteHeader(401) return } scopes := []string{} contractID := mux.Vars(r)["contractId"] contractMngr := contractdb.NewManager(r) isParticipant, err := contractMngr.IsParticipant(contractID, username) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if isParticipant { scopes = append(scopes, "contract:participant") scopes = append(scopes, "contract:read") } log.Debug("Available scopes: ", scopes) log.Debug("Atscopestring scope: ", atscopestring) // check scopes if !om.CheckScopes(scopes) { w.WriteHeader(403) return } next.ServeHTTP(w, r) }) }
// DeleteAPIKey is the handler for DELETE /organizations/{globalid}/apikeys/{label} // Removes an API key func (api OrganizationsAPI) DeleteAPIKey(w http.ResponseWriter, r *http.Request) { organization := mux.Vars(r)["globalid"] label := mux.Vars(r)["label"] mgr := oauthservice.NewManager(r) err := mgr.DeleteClient(organization, label) if err != nil { log.Error("Error deleting organization:", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.WriteHeader(http.StatusNoContent) }
// GetAPIKeyLabels is the handler for GET /organizations/{globalid}/apikeys // Get the list of active api keys. The secrets themselves are not included. func (api OrganizationsAPI) GetAPIKeyLabels(w http.ResponseWriter, r *http.Request) { organization := mux.Vars(r)["globalid"] mgr := oauthservice.NewManager(r) labels, err := mgr.GetClientLabels(organization) if err != nil { log.Error("Error getting a client secret labels: ", err.Error()) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(labels) }
// CreateNewAPIKey is the handler for POST /organizations/{globalid}/apikeys // Create a new API Key, a secret itself should not be provided, it will be generated // serverside. func (api OrganizationsAPI) CreateNewAPIKey(w http.ResponseWriter, r *http.Request) { organization := mux.Vars(r)["globalid"] apiKey := APIKey{} if err := json.NewDecoder(r.Body).Decode(&apiKey); err != nil { log.Debug("Error decoding apikey: ", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } //TODO: validate key, not just the label property if !isValidAPIKeyLabel(apiKey.Label) { log.Debug("Invalid label: ", apiKey.Label) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } log.Debug("Creating apikey:", apiKey) c := oauthservice.NewOauth2Client(organization, apiKey.Label, apiKey.CallbackURL, apiKey.ClientCredentialsGrantType) mgr := oauthservice.NewManager(r) err := mgr.CreateClient(c) if db.IsDup(err) { log.Debug("Duplicate label") http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict) return } if err != nil { log.Error("Error creating api secret label", err.Error()) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } apiKey.Secret = c.Secret w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(apiKey) }
// GetAPIKey is the handler for GET /organizations/{globalid}/apikeys/{label} func (api OrganizationsAPI) GetAPIKey(w http.ResponseWriter, r *http.Request) { organization := mux.Vars(r)["globalid"] label := mux.Vars(r)["label"] mgr := oauthservice.NewManager(r) client, err := mgr.GetClient(organization, label) if err != nil { log.Error("Error getting a client: ", err.Error()) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if client == nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } apiKey := FromOAuthClient(client) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(apiKey) }
// Handler return HTTP handler representation of this middleware func (om *Oauth2oauth_2_0Middleware) Handler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var scopes []string protectedOrganization := mux.Vars(r)["globalid"] var atscopestring string var username string var clientID string var globalID string accessToken := om.GetAccessToken(r) if accessToken != "" { //TODO: cache oauthMgr := oauthservice.NewManager(r) at, err := oauthMgr.GetAccessToken(accessToken) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if at == nil { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } globalID = at.GlobalID username = at.Username atscopestring = at.Scope clientID = at.ClientID } else { if webuser, ok := context.GetOk(r, "webuser"); ok { if parsedusername, ok := webuser.(string); ok && parsedusername != "" { username = parsedusername atscopestring = "admin" clientID = itsyouonlineClientID } } } if (username == "" && globalID == "") || clientID == "" { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } context.Set(r, "authenticateduser", username) //If the authorized organization is the protected organization itself or is a parent of it if len(globalID) > 0 && (globalID == protectedOrganization || strings.HasPrefix(protectedOrganization, globalID+".")) { scopes = []string{atscopestring} } else { orgMgr := organization.NewManager(r) isOwner, err := orgMgr.IsOwner(protectedOrganization, username) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if isOwner && ((clientID == itsyouonlineClientID && atscopestring == "admin") || scopeStringContainsScope(atscopestring, "user:admin")) { scopes = []string{"organization:owner"} } else { isMember, err := orgMgr.IsMember(protectedOrganization, username) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if isMember && ((clientID == itsyouonlineClientID && atscopestring == "admin") || scopeStringContainsScope(atscopestring, "user:admin")) { scopes = []string{"organization:member"} } } } //TODO: scopes "organization:info", "organization:contracts:read" log.Debug("Available scopes: ", scopes) // check scopes if !om.CheckScopes(scopes) { w.WriteHeader(403) return } next.ServeHTTP(w, r) }) }
// DeleteOrganization is the handler for DELETE /organizations/{globalid} // Deletes an organization and all data linked to it (join-organization-invitations, oauth_access_tokens, oauth_clients, authorizations) func (api OrganizationsAPI) DeleteOrganization(w http.ResponseWriter, r *http.Request) { globalid := mux.Vars(r)["globalid"] orgMgr := organization.NewManager(r) logoMgr := organization.NewLogoManager(r) if !orgMgr.Exists(globalid) { writeErrorResponse(w, http.StatusNotFound, "organization_not_found") return } suborganizations, err := orgMgr.GetSubOrganizations(globalid) if handleServerError(w, "fetching suborganizations", err) { return } if len(suborganizations) != 0 { writeErrorResponse(w, 422, "organization_has_children") return } err = orgMgr.Remove(globalid) if handleServerError(w, "removing organization", err) { return } // Remove the organizations as a member/ an owner of other organizations organizations, err := orgMgr.AllByOrg(globalid) if handleServerError(w, "fetching organizations where this org is an owner/a member", err) { return } for _, org := range organizations { err = orgMgr.RemoveOrganization(org.Globalid, globalid) if handleServerError(w, "removing organizations as a member / an owner of another organization", err) { return } } if logoMgr.Exists(globalid) { err = logoMgr.Remove(globalid) if handleServerError(w, "removing organization logo", err) { return } } orgReqMgr := invitations.NewInvitationManager(r) err = orgReqMgr.RemoveAll(globalid) if handleServerError(w, "removing organization invitations", err) { return } oauthMgr := oauthservice.NewManager(r) err = oauthMgr.RemoveTokensByGlobalId(globalid) if handleServerError(w, "removing organization oauth accesstokens", err) { return } err = oauthMgr.DeleteAllForOrganization(globalid) if handleServerError(w, "removing client secrets", err) { return } err = oauthMgr.RemoveClientsById(globalid) if handleServerError(w, "removing organization oauth clients", err) { return } userMgr := user.NewManager(r) err = userMgr.DeleteAllAuthorizations(globalid) if handleServerError(w, "removing all authorizations", err) { return } err = oauthMgr.RemoveClientsById(globalid) if handleServerError(w, "removing organization oauth clients", err) { return } l2faMgr := organization.NewLast2FAManager(r) err = l2faMgr.RemoveByOrganization(globalid) if handleServerError(w, "removing organization 2FA history", err) { return } w.WriteHeader(http.StatusNoContent) }
// Handler return HTTP handler representation of this middleware func (om *Oauth2oauth_2_0Middleware) Handler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var atscopestring string var username string var clientID string scopes := []string{} jwtstring := om.GetJWT(r) accessToken := om.GetAccessToken(r) if jwtstring != "" { token, err := jwt.Parse(jwtstring, func(token *jwt.Token) (interface{}, error) { // Don't forget to validate the alg is what you expect: if token.Method != jwt.SigningMethodES384 { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } return &security.JWTPublicKey, nil }) if err != nil || !token.Valid { log.Error(err) http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } username = token.Claims["username"].(string) clientID = token.Claims["aud"].(string) atscopestring = token.Claims["scope"].(string) } else if accessToken != "" { //TODO: cache oauthMgr := oauthservice.NewManager(r) at, err := oauthMgr.GetAccessToken(accessToken) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if at == nil { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } username = at.Username atscopestring = at.Scope clientID = at.ClientID } else { if webuser, ok := context.GetOk(r, "webuser"); ok { if parsedusername, ok := webuser.(string); ok && parsedusername != "" { username = parsedusername atscopestring = "admin" clientID = "itsyouonline" } } } if username == "" || clientID == "" { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } protectedUsername := mux.Vars(r)["username"] if protectedUsername == username && clientID == "itsyouonline" && atscopestring == "admin" { scopes = append(scopes, "user:admin") } if strings.HasPrefix(atscopestring, "user:"******"user:info") } for _, scope := range strings.Split(atscopestring, ",") { scope = strings.Trim(scope, " ") scopes = append(scopes, scope) } log.Debug("Available scopes: ", scopes) context.Set(r, "client_id", clientID) context.Set(r, "availablescopes", atscopestring) // check scopes if !om.CheckScopes(scopes) { http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden) return } next.ServeHTTP(w, r) }) }