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)
}
Example #2
0
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)
}
Example #3
0
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)
}
Example #4
0
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))
}
Example #5
0
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)
}
Example #6
0
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)
}
Example #7
0
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)
}
Example #8
0
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)
}
Example #9
0
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)
}
Example #10
0
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)
}