From bec399dca3e6caf4d103ae67dc16e537b86652c5 Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Wed, 30 Apr 2014 18:19:57 +0200 Subject: [PATCH] Implemented httpheader userid handler. --- server.conf.in | 17 ++++++--- src/app/spreed-speakfreely-server/sessions.go | 2 +- src/app/spreed-speakfreely-server/users.go | 36 ++++++++++++++++--- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/server.conf.in b/server.conf.in index 17770e13..69367aa5 100644 --- a/server.conf.in +++ b/server.conf.in @@ -98,14 +98,23 @@ sessionSecret = the-default-secret-do-not-keep-me [users] ; Set to true to enable user functionality. enabled = false -; Set authorization mode for users. Currently implemented is the "sharedsecret" -; mode which does validate the userid with a HMAC authentication secret. -; The format goes like this: -; BASE64(HMAC-SHA-256(secret, expirationTimestampInSeconds:userid)) +; Set users authorization mode. +; sharedsecret: +; Validates the userid with a HMAC authentication secret. +; The format goes like this: +; BASE64(HMAC-SHA-256(secret, expirationTimestampInSeconds:userid)) +; httpheader: +; The userid is provided as an HTTP header. The server does not do any +; validation. This usually only makes sense with a front end HTTPS proxy which +; does the authentication and injects the user id as HTTP header for sessions +; REST requests. In mode httpheader, allowRegistration should be false. ;mode = sharedsecret ; The shared secred for HMAC validation in "sharedsecret" mode. Best use 32 or ; 64 bytes of random data. ;sharedsecret_secret = some-secret-do-not-keep +; The HTTP header name where to find the userid in "httpheader" mode. +;httpheader_header = x-userid + ; The server can create new userids if enabled. Set allowRegistration to true to ; enable userid creation/registration. Users are created to match the settings ; of the currently configured mode (see above). diff --git a/src/app/spreed-speakfreely-server/sessions.go b/src/app/spreed-speakfreely-server/sessions.go index 0018c535..82074ea1 100644 --- a/src/app/spreed-speakfreely-server/sessions.go +++ b/src/app/spreed-speakfreely-server/sessions.go @@ -84,7 +84,7 @@ func (sessions *Sessions) Patch(request *http.Request) (int, interface{}, http.H } // Validate with users handler. - userid, err := sessions.users.handler.Validate(&snr) + userid, err := sessions.users.handler.Validate(&snr, request) if err != nil { error = true log.Println("Session patch failed - users validation failed.", err) diff --git a/src/app/spreed-speakfreely-server/users.go b/src/app/spreed-speakfreely-server/users.go index e42616ec..bcb75206 100644 --- a/src/app/spreed-speakfreely-server/users.go +++ b/src/app/spreed-speakfreely-server/users.go @@ -38,8 +38,8 @@ import ( ) type UsersHandler interface { - Validate(snr *SessionNonceRequest) (string, error) - Create(snr *UserNonce) (*UserNonce, error) + Validate(snr *SessionNonceRequest, request *http.Request) (string, error) + Create(snr *UserNonce, request *http.Request) (*UserNonce, error) } type UsersSharedsecretHandler struct { @@ -54,7 +54,7 @@ func (uh *UsersSharedsecretHandler) createHMAC(useridCombo string) string { } -func (uh *UsersSharedsecretHandler) Validate(snr *SessionNonceRequest) (string, error) { +func (uh *UsersSharedsecretHandler) Validate(snr *SessionNonceRequest, request *http.Request) (string, error) { // Parse UseridCombo. useridCombo := strings.SplitN(snr.UseridCombo, ":", 2) @@ -79,7 +79,7 @@ func (uh *UsersSharedsecretHandler) Validate(snr *SessionNonceRequest) (string, } -func (uh *UsersSharedsecretHandler) Create(un *UserNonce) (*UserNonce, error) { +func (uh *UsersSharedsecretHandler) Create(un *UserNonce, request *http.Request) (*UserNonce, error) { // TODO(longsleep): Make this configureable - One year for now ... expiration := time.Now().Add(time.Duration(1) * time.Hour * 24 * 31 * 12) @@ -91,6 +91,26 @@ func (uh *UsersSharedsecretHandler) Create(un *UserNonce) (*UserNonce, error) { } +type UsersHTTPHeaderHandler struct { + headerName string +} + +func (uh *UsersHTTPHeaderHandler) Validate(snr *SessionNonceRequest, request *http.Request) (string, error) { + + userid := request.Header.Get(uh.headerName) + if userid == "" { + return "", errors.New("no userid provided") + } + return userid, nil + +} + +func (uh *UsersHTTPHeaderHandler) Create(un *UserNonce, request *http.Request) (*UserNonce, error) { + + return nil, errors.New("create is not possible in httpheader mode") + +} + type UserNonce struct { Nonce string `json:"nonce"` Userid string `json:"userid"` @@ -117,6 +137,12 @@ func NewUsers(hub *Hub, realm string, runtime phoenix.Runtime) *Users { if secret != "" { handler = &UsersSharedsecretHandler{secret: []byte(secret)} } + case "httpheader": + headerName, _ := runtime.GetString("users", "httpheader_header") + if headerName == "" { + headerName = "x-users" + } + handler = &UsersHTTPHeaderHandler{headerName: headerName} default: mode = "" } @@ -163,7 +189,7 @@ func (users *Users) Post(request *http.Request) (int, interface{}, http.Header) return 400, NewApiError("users_request_failed", fmt.Sprintf("Error: %q", err)), http.Header{"Content-Type": {"application/json"}} } - un, err := users.handler.Create(&UserNonce{Nonce: nonce, Userid: userid, Success: true}) + un, err := users.handler.Create(&UserNonce{Nonce: nonce, Userid: userid, Success: true}, request) if err != nil { return 400, NewApiError("users_create_failed", fmt.Sprintf("Error: %q", err)), http.Header{"Content-Type": {"application/json"}} }