Commit 4989b89a authored by Nicolas Pernoud's avatar Nicolas Pernoud
Browse files

chore: refactored tokens

parent d3bbc89f
Pipeline #14500 passed with stages
in 2 minutes and 36 seconds
......@@ -57,7 +57,7 @@ type TokenData struct {
func ValidateAuthMiddleware(next http.Handler, allowedRoles []string, checkXSRF bool) http.Handler {
roleChecker := func(w http.ResponseWriter, r *http.Request) {
user := TokenData{}
checkXSRF, err := tokens.Manager.ExtractAndValidateToken(r, authTokenKey, &user, checkXSRF)
checkXSRF, err := tokens.ExtractAndValidateToken(r, authTokenKey, &user, checkXSRF)
// Handle WebDav authentication
if err != nil && isWebdav(r.UserAgent()) {
// Test if the user password is directly given in the request, if so populate the user
......@@ -195,7 +195,7 @@ func GetShareToken(w http.ResponseWriter, r *http.Request) {
user.URL = wantedToken.URL
user.ReadOnly = wantedToken.ReadOnly
user.SharingUserLogin = wantedToken.Sharedfor
token, err := tokens.Manager.CreateToken(user, time.Now().Add(time.Hour*time.Duration(24*wantedToken.Lifespan)))
token, err := tokens.CreateToken(user, time.Now().Add(time.Hour*time.Duration(24*wantedToken.Lifespan)))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
......
......@@ -71,7 +71,7 @@ func (m Manager) HandleInMemoryLogin(w http.ResponseWriter, r *http.Request) {
return
}
tokenData := TokenData{User: User{ID: user.ID, Login: user.Login, Email: user.Email, Roles: user.Roles}, XSRFToken: xsrfToken}
tokens.Manager.StoreData(tokenData, m.Hostname, authTokenKey, tokenLifetime, w)
tokens.CreateCookie(tokenData, m.Hostname, authTokenKey, tokenLifetime, w)
// Log the connexion
log.Logger.Printf("| %v (%v %v) | Login success | %v | %v", user.Login, user.Name, user.Surname, r.RemoteAddr, log.GetCityAndCountryFromRequest(r))
}
......
......@@ -50,7 +50,7 @@ func (m Manager) HandleOAuth2Login(w http.ResponseWriter, r *http.Request) {
if err != nil {
log.Logger.Fatalf("Error generating OAuth2 strate string :%v\n", err)
}
tokens.Manager.StoreData(oauthStateString, m.Hostname, oAuth2StateKey, 30*time.Second, w)
tokens.CreateCookie(oauthStateString, m.Hostname, oAuth2StateKey, 30*time.Second, w)
url := m.Config.AuthCodeURL(oauthStateString)
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}
......@@ -60,7 +60,7 @@ func (m Manager) HandleOAuth2Callback() http.Handler {
oauth2Handler := func(w http.ResponseWriter, r *http.Request) {
// Recover state from tokens
var oauthState string
_, err := tokens.Manager.ExtractAndValidateToken(r, oAuth2StateKey, &oauthState, false)
_, err := tokens.ExtractAndValidateToken(r, oAuth2StateKey, &oauthState, false)
if err != nil {
fmt.Println("Code exchange failed with ", err)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
......@@ -133,7 +133,7 @@ func (m Manager) HandleOAuth2Callback() http.Handler {
return
}
tokenData := TokenData{User: user, XSRFToken: xsrfToken}
tokens.Manager.StoreData(tokenData, m.Hostname, authTokenKey, 24*time.Hour, w)
tokens.CreateCookie(tokenData, m.Hostname, authTokenKey, 24*time.Hour, w)
// Log the connexion
log.Logger.Printf("| %v (%v %v) | Login success | %v | %v", user.Login, user.Name, user.Surname, req.RemoteAddr, log.GetCityAndCountryFromRequest(req))
// Redirect
......
......@@ -22,8 +22,8 @@ import (
var (
now = time.Now
// Manager is the current token manager
Manager manager
// m is the current token manager
m manager
)
// manager manages tokens
......@@ -34,7 +34,7 @@ type manager struct {
// Init inits the main token manager
func Init(keyfile string, debug bool) {
Manager = newManager(keyfile, debug)
m = newManager(keyfile, debug)
}
// newManager creates a manager
......@@ -67,10 +67,10 @@ type Token struct {
Data []byte
}
// StoreData creates a token with the given data and returns it in a cookie
func (m manager) StoreData(data interface{}, hostName string, cookieName string, duration time.Duration, w http.ResponseWriter) {
// CreateCookie creates a token with the given data and returns it in a cookie
func CreateCookie(data interface{}, hostName string, cookieName string, duration time.Duration, w http.ResponseWriter) {
expiration := now().Add(duration)
value, err := m.CreateToken(data, expiration)
value, err := CreateToken(data, expiration)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
......@@ -80,7 +80,7 @@ func (m manager) StoreData(data interface{}, hostName string, cookieName string,
}
// CreateToken creates a token with the given data
func (m manager) CreateToken(data interface{}, expiration time.Time) (string, error) {
func CreateToken(data interface{}, expiration time.Time) (string, error) {
// Marshall the data
d, err := json.Marshal(data)
if err != nil {
......@@ -98,7 +98,10 @@ func (m manager) CreateToken(data interface{}, expiration time.Time) (string, er
}
// Compress with deflate
var csToken bytes.Buffer
c, err := flate.NewWriter(&csToken, flate.BestCompression)
var c *flate.Writer
if c, err = flate.NewWriter(&csToken, flate.BestCompression); err != nil {
return "", err
}
if _, err := c.Write(sToken); err != nil {
return "", err
}
......@@ -113,7 +116,7 @@ func (m manager) CreateToken(data interface{}, expiration time.Time) (string, er
}
// ExtractAndValidateToken extracts the token from the request, validates it, and return the data n the value pointed to by v
func (m manager) ExtractAndValidateToken(r *http.Request, cookieName string, v interface{}, checkXSRF bool) (bool, error) {
func ExtractAndValidateToken(r *http.Request, cookieName string, v interface{}, checkXSRF bool) (bool, error) {
becsToken, checkXSRF, err := func(r *http.Request, checkXSRF bool) (string, bool, error) {
// Try to extract from the query
query := r.URL.Query().Get("token")
......@@ -142,13 +145,13 @@ func (m manager) ExtractAndValidateToken(r *http.Request, cookieName string, v i
}(r, checkXSRF)
if err == nil {
return checkXSRF, m.unstoreData(becsToken, v)
return checkXSRF, unstoreData(becsToken, v)
}
return false, err
}
// unstoreData decrypt, uncompress, unserialize the token, and returns the data n the value pointed to by v
func (m manager) unstoreData(becsToken string, v interface{}) error {
func unstoreData(becsToken string, v interface{}) error {
// Decrypt the token
ecsToken, err := base64.StdEncoding.DecodeString(becsToken)
if err != nil {
......@@ -181,6 +184,10 @@ func (m manager) unstoreData(becsToken string, v interface{}) error {
}
// Update the data
err = json.Unmarshal(token.Data, v)
if err != nil {
return fmt.Errorf("failed to unmarshall data")
}
// Return no error if everything is fine
return nil
}
......
......@@ -43,14 +43,14 @@ func TestManagerCreateTokenUnStoreData(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := manager{
m = manager{
key: tt.fields.encryptKey,
debugMode: tt.fields.debugMode,
}
token, _ := m.CreateToken(tt.args.data, tt.args.expiration)
token, _ := CreateToken(tt.args.data, tt.args.expiration)
m.key = tt.fields.decryptKey
v := user{}
err := m.unstoreData(token, &v)
err := unstoreData(token, &v)
got := tt.args.data == v
if (err != nil) != tt.wantErr {
t.Errorf("manager.(un)storeData() error = %v, wantErr %v", err, tt.wantErr)
......
......@@ -32,7 +32,7 @@
<div class="navbar-brand">
<div class="navbar-item">
<a class="button is-primary is-rounded is-outlined" href="https://www.github.com/nicolaspernoud/Vestibule" target="_blank" rel="noopener noreferrer">
<span>4.5.13</span>
<span>4.5.14</span>
<span class="icon">
<svg
class="svg-inline--fa fa-github fa-w-16"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment