func (h passwordHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") matches := regexp.MustCompile(`/Users/(.*)/password$`).FindStringSubmatch(req.URL.Path) id := matches[1] user, ok := h.users.Get(id) if !ok { common.Error(w, http.StatusUnauthorized, "Not authorized", "access_denied") return } var document documents.ChangePasswordRequest err := json.NewDecoder(req.Body).Decode(&document) if err != nil { panic(err) } if !h.canUpdateUserPassword(id, token, user.Password, document.OldPassword) { common.Error(w, http.StatusUnauthorized, "Not authorized", "access_denied") return } user.Password = document.Password h.users.Update(user) }
func (h createHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") if ok := h.tokens.Validate(token, []string{"scim"}, []string{"scim.write"}); !ok { common.Error(w, http.StatusUnauthorized, "Full authentication is required to access this resource", "unauthorized") return } requestBody, err := ioutil.ReadAll(req.Body) if err != nil { panic(err) } var document documents.CreateGroupRequest err = json.Unmarshal(requestBody, &document) if err != nil { panic(err) } if _, ok := h.groups.GetByName(document.DisplayName); ok { common.Error(w, http.StatusConflict, fmt.Sprintf("A group with displayName: %s already exists.", document.DisplayName), "scim_resource_already_exists") return } group := domain.NewGroupFromCreateDocument(document) h.groups.Add(group) response, err := json.Marshal(group.ToDocument()) if err != nil { panic(err) } w.WriteHeader(http.StatusCreated) w.Write(response) }
func (h createHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") if ok := h.tokens.Validate(token, []string{"clients"}, []string{"clients.write"}); !ok { common.Error(w, http.StatusUnauthorized, "Full authentication is required to access this resource", "unauthorized") return } var document documents.CreateClientRequest err := json.NewDecoder(req.Body).Decode(&document) if err != nil { panic(err) } client := domain.NewClientFromDocument(document) if err := client.Validate(); err != nil { common.Error(w, http.StatusBadRequest, err.Error(), "invalid_client") return } h.clients.Add(client) response, err := json.Marshal(client.ToDocument()) if err != nil { panic(err) } w.WriteHeader(http.StatusCreated) w.Write(response) }
func (h listHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { query, err := url.ParseQuery(req.URL.RawQuery) if err != nil { panic(err) } filter := query.Get("filter") matches := regexp.MustCompile(`(.*) (.*) '(.*)'$`).FindStringSubmatch(filter) parameter := matches[1] operator := matches[2] value := matches[3] if !validParameter(parameter) { common.Error(w, http.StatusBadRequest, fmt.Sprintf("Invalid filter expression: [%s]", filter), "scim") return } if !validOperator(operator) { common.Error(w, http.StatusBadRequest, fmt.Sprintf("Invalid filter expression: [%s]", filter), "scim") return } user, _ := h.users.Get(value) list := domain.UsersList{user} response, err := json.Marshal(list.ToDocument()) if err != nil { panic(err) } w.WriteHeader(http.StatusOK) w.Write([]byte(response)) }
func (h updateHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") if ok := h.tokens.Validate(token, []string{"scim"}, []string{"scim.write"}); !ok { common.Error(w, http.StatusUnauthorized, "Full authentication is required to access this resource", "unauthorized") return } requestBody, err := ioutil.ReadAll(req.Body) if err != nil { panic(err) } contentType := req.Header.Get("Content-Type") if contentType != "application/json" { if contentType == "" { contentType = http.DetectContentType(requestBody) } common.Error(w, http.StatusBadRequest, fmt.Sprintf("Content type '%s' not supported", contentType), "scim") return } var document documents.UpdateUserRequest err = json.Unmarshal(requestBody, &document) if err != nil { panic(err) } user := domain.NewUserFromUpdateDocument(document) matches := regexp.MustCompile(`/Users/(.*)$`).FindStringSubmatch(req.URL.Path) id := matches[1] existingUser, ok := h.users.Get(id) if !ok { common.Error(w, http.StatusNotFound, fmt.Sprintf("User %s does not exist", user.ID), "scim_resource_not_found") return } version, err := strconv.ParseInt(req.Header.Get("If-Match"), 10, 64) if err != nil || existingUser.Version != int(version) { common.Error(w, http.StatusBadRequest, "Missing If-Match for PUT", "scim") return } h.users.Update(user) response, err := json.Marshal(user.ToDocument()) if err != nil { panic(err) } w.WriteHeader(http.StatusOK) w.Write(response) }
func (h tokenHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { // TODO: actually check the basic auth values _, _, ok := req.BasicAuth() if !ok { common.Error(w, http.StatusUnauthorized, "An Authentication object was not found in the SecurityContext", "unauthorized") return } err := req.ParseForm() if err != nil { panic(err) } clientID := req.Form.Get("client_id") scopes := []string{"scim.write", "scim.read", "password.write"} t := domain.Token{ ClientID: clientID, Scopes: scopes, Audiences: []string{"scim", "password"}, } response, err := json.Marshal(t.ToDocument()) if err != nil { panic(err) } w.Write(response) }
func (h createHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") if ok := h.tokens.Validate(token, []string{"scim"}, []string{"scim.write"}); !ok { common.Error(w, http.StatusUnauthorized, "Full authentication is required to access this resource", "unauthorized") return } requestBody, err := ioutil.ReadAll(req.Body) if err != nil { panic(err) } contentType := req.Header.Get("Content-Type") if contentType != "application/json" { if contentType == "" { contentType = http.DetectContentType(requestBody) } common.Error(w, http.StatusBadRequest, fmt.Sprintf("Content type '%s' not supported", contentType), "scim") return } var document documents.CreateUserRequest err = json.Unmarshal(requestBody, &document) if err != nil { panic(err) } if _, ok := h.users.GetByName(document.UserName); ok { common.Error(w, http.StatusConflict, fmt.Sprintf("Username already in use: %s", document.UserName), "scim_resource_already_exists") return } user := domain.NewUserFromCreateDocument(document) if err := user.Validate(); err != nil { common.Error(w, http.StatusBadRequest, err.Error(), "invalid_scim_resource") return } h.users.Add(user) response, err := json.Marshal(user.ToDocument()) if err != nil { panic(err) } w.WriteHeader(http.StatusCreated) w.Write(response) }
func (h deleteHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") if ok := h.tokens.Validate(token, []string{"scim"}, []string{"scim.write"}); !ok { common.Error(w, http.StatusUnauthorized, "Full authentication is required to access this resource", "unauthorized") return } matches := regexp.MustCompile(`/Groups/(.*)$`).FindStringSubmatch(req.URL.Path) id := matches[1] if ok := h.groups.Delete(id); !ok { common.Error(w, http.StatusNotFound, fmt.Sprintf("Group %s does not exist", id), "scim_resource_not_found") return } w.WriteHeader(http.StatusOK) }
func (h deleteHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") if len(token) == 0 { common.Error(w, http.StatusUnauthorized, "Full authentication is required to access this resource", "unauthorized") return } if ok := h.tokens.Validate(token, []string{"clients"}, []string{"clients.write"}); !ok { common.Error(w, http.StatusForbidden, "Invalid token does not contain resource id (clients)", "access_denied") return } matches := regexp.MustCompile(`/oauth/clients/(.*)$`).FindStringSubmatch(req.URL.Path) id := matches[1] if ok := h.clients.Delete(id); !ok { panic("foo") } w.WriteHeader(http.StatusOK) }
func (h getHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") if ok := h.tokens.Validate(token, []string{"clients"}, []string{"clients.read"}); !ok { common.Error(w, http.StatusUnauthorized, "Full authentication is required to access this resource", "unauthorized") return } matches := regexp.MustCompile(`/oauth/clients/(.*)$`).FindStringSubmatch(req.URL.Path) id := matches[1] client, ok := h.clients.Get(id) if !ok { common.NotFound(w, fmt.Sprintf("Client %s does not exist", id)) return } response, err := json.Marshal(client.ToDocument()) if err != nil { panic(err) } w.WriteHeader(http.StatusOK) w.Write(response) }
func (h authorizeHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { if req.Header.Get("Accept") != "application/json" { h.redirectToLogin(w) return } requestQuery := req.URL.Query() clientID := requestQuery.Get("client_id") responseType := requestQuery.Get("response_type") if clientID != "cf" { h.redirectToLogin(w) return } if responseType != "token" { h.redirectToLogin(w) return } req.ParseForm() userName := req.Form.Get("username") user, ok := h.users.GetByName(userName) if !ok { common.Error(w, http.StatusNotFound, fmt.Sprintf("User %s does not exist", userName), "scim_resource_not_found") return } if req.Form.Get("source") != "credentials" { h.redirectToLogin(w) return } if req.Form.Get("password") != user.Password { h.redirectToLogin(w) return } scopes := strings.Join(h.tokens.DefaultScopes, " ") t := h.tokens.Encrypt(domain.Token{ UserID: user.ID, Scopes: h.tokens.DefaultScopes, Audiences: []string{}, }) redirectURI := requestQuery.Get("redirect_uri") query := url.Values{ "token_type": []string{"bearer"}, "access_token": []string{t}, "expires_in": []string{"599"}, "scope": []string{scopes}, "jti": []string{"ad0efc96-ed29-43ef-be75-85a4b4f105b5"}, } location := fmt.Sprintf("%s#%s", redirectURI, query.Encode()) w.Header().Set("Location", location) w.WriteHeader(http.StatusFound) }