Skip to content
Snippets Groups Projects
Select Git revision
  • ab254c38a406977d0f07b078e42dc24c4fd5521f
  • main default protected
  • React-Branch
3 results

auth.go

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    auth.go 4.29 KiB
    package auth
    
    import (
    	"crypto/sha256"
    	logging "dcsg2900-threattotal/logs"
    	"dcsg2900-threattotal/utils"
    	"encoding/json"
    	"fmt"
    	"time"
    )
    
    // Authenticate function, takes a code or a token,
    // returns a bool, and if the input is a valid code a hash is also returned.
    func Authenticate(code string, token string) (authenticated bool, hash string) {
    	authenticated = false
    	var err bool
    	if code != "" {
    		fmt.Println("Hash is not empty")
    		hash, err = addUser(code)
    		fmt.Println("hash is: ", hash)
    		if !err {
    			return
    		}
    		authenticated = true
    		fmt.Println("Returning: ", authenticated, hash)
    		return authenticated, hash
    	} else if token != "" {
    		_, authenticated = getAuth(token)
    		return
    	}
    	return
    }
    
    // Func which adds a user to the database and returns a code
    func addUser(code string) (hash string, auth bool) {
    	tokenResponse, auth := CodeToToken(code)
    	if !auth {
    		return "", false
    	}
    	//hash = tokenToHash(tokenResponse)
    	// Add the hash to the database with tokenResponse as the value
    
    	return tokenResponse, true
    }
    
    // Func which takes a code and returns an authentication token.
    // Inspiration from the go-oidc examples: https://github.com/coreos/go-oidc/blob/v3/example/userinfo/app.go
    // and https://github.com/coreos/go-oidc/blob/v3/example/idtoken/app.go
    func CodeToToken(code string) (token string, authenticated bool) {
    	// Get the token
    	oauth2Token, err := utils.Config.Exchange(utils.Ctx, code)
    	if err != nil {
    		fmt.Println("Failed to exchange token: " + err.Error())
    		return "", false
    	}
    	// Extra fields contain: scope, token_type and id_token
    
    	// Get the jwt
    	rawIDToken, error := oauth2Token.Extra("id_token").(string)
    	if !error {
    		fmt.Println("No jwt returned.")
    		logging.Logerror(nil, "No JWT returned AUTH.go:")
    		return "", false
    	}
    
    	// Verify the jwt
    	idToken, err := utils.Verifier.Verify(utils.Ctx, rawIDToken)
    	if err != nil {
    		fmt.Println("Failed to validate the jwt.")
    		logging.Logerror(err, "Failed to validate JWT Auth.GO: ")
    		return
    	}
    
    	var dataTest map[string]interface{}
    	// Parse the userdata in the jwt
    	idToken.Claims(&dataTest)
    	fmt.Println("JWT claims: ", dataTest)
    
    	var data utils.IdAndJwt
    	data.Oauth2Token = *oauth2Token
    	data.Jwt = *idToken
    	data.Claims = dataTest
    
    	marshalledTokens, err := json.Marshal(data)
    	if err != nil {
    		fmt.Println("Error marshalling tokens in CodeToToken")
    		logging.Logerror(err, "Error marshalling tokens in CodeToToken Auth.go:")
    		return "", false
    	}
    
    	hash := tokenToHash(oauth2Token.AccessToken)
    
    	// Add to the database
    	_, err = utils.Conn.Do("SETEX", "user:"+hash, (oauth2Token.Expiry.Unix() - time.Now().Unix()), marshalledTokens)
    	if err != nil {
    		fmt.Println("Error adding data to redis:" + err.Error())
    		logging.Logerror(err, "Error adding data to redis Auth.go:")
    		return "", false
    	}
    
    	return hash, true
    }
    
    func getAuth(hash string) (token string, err bool) {
    	value, error := utils.Conn.Do("GET", "user:"+hash)
    	if value == nil {
    		if error != nil {
    			fmt.Println("Error:" + error.Error())
    			logging.Logerror(error, "Error in CacheSearch getAuth:")
    
    		}
    		fmt.Println("No Cache hit")
    		return "", false
    	} else {
    
    		var responseData utils.IdAndJwt
    		error := json.Unmarshal(value.([]byte), &responseData)
    		if error != nil {
    			fmt.Println("Error unmarshalling")
    			logging.Logerror(error, "Error unmarshalling GetAuth:")
    
    			// If there is an error delete the key
    			value, error := utils.Conn.Do("DEL", token)
    			if error != nil {
    				fmt.Println("Failed deleting key in redis: ", err)
    				logging.Logerror(error, "Error Failed deleting redis key, getAuth:")
    
    			}
    			fmt.Println("Redis delete response: ", value)
    			return "", false
    		}
    
    		return responseData.Oauth2Token.AccessToken, true
    	}
    }
    
    // Func which takes an authentication token and returns a sha256 hash of it.
    func tokenToHash(code string) (hash string) {
    	// Create the sha256 hash
    	fileHash := sha256.New()
    	fileHash.Write([]byte(code))
    
    	return fmt.Sprintf("%x", fileHash.Sum(nil))
    }
    
    // Functtion which takes a user and deletes it from the backend, for log out purposes.
    func Logout(hash string) bool {
    
    	// Delete the database item
    	_, error := utils.Conn.Do("DEL", "user:"+hash)
    	if error != nil {
    		fmt.Println("Error removing data from redis:" + error.Error())
    		logging.Logerror(error, "Error removing data from redis Auth.go:")
    		return false
    	}
    
    	// Return true if successfull
    	return true
    }