mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-26 21:01:32 +08:00
Netmaker Desktop Session Duration (#3543)
* feat(go): allow different session durations for client apps; * feat(go): assume call is from netdesk app if header absent; * feat(go): allow header; * feat(go): set client jwt validity duration on migration.
This commit is contained in:
@@ -77,7 +77,7 @@ func SessionHandler(conn *websocket.Conn) {
|
|||||||
_, err := logic.VerifyAuthRequest(models.UserAuthParams{
|
_, err := logic.VerifyAuthRequest(models.UserAuthParams{
|
||||||
UserName: registerMessage.User,
|
UserName: registerMessage.User,
|
||||||
Password: registerMessage.Password,
|
Password: registerMessage.Password,
|
||||||
})
|
}, logic.NetclientApp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -89,6 +89,7 @@ type ServerConfig struct {
|
|||||||
DeployedByOperator bool `yaml:"deployed_by_operator"`
|
DeployedByOperator bool `yaml:"deployed_by_operator"`
|
||||||
Environment string `yaml:"environment"`
|
Environment string `yaml:"environment"`
|
||||||
JwtValidityDuration time.Duration `yaml:"jwt_validity_duration" swaggertype:"primitive,integer" format:"int64"`
|
JwtValidityDuration time.Duration `yaml:"jwt_validity_duration" swaggertype:"primitive,integer" format:"int64"`
|
||||||
|
JwtValidityDurationClients time.Duration `yaml:"jwt_validity_duration_clients" swaggertype:"primitive,integer" format:"int64"`
|
||||||
RacRestrictToSingleNetwork bool `yaml:"rac_restrict_to_single_network"`
|
RacRestrictToSingleNetwork bool `yaml:"rac_restrict_to_single_network"`
|
||||||
CacheEnabled string `yaml:"caching_enabled"`
|
CacheEnabled string `yaml:"caching_enabled"`
|
||||||
EndpointDetection bool `yaml:"endpoint_detection"`
|
EndpointDetection bool `yaml:"endpoint_detection"`
|
||||||
|
@@ -56,6 +56,7 @@ func HandleRESTRequests(wg *sync.WaitGroup, ctx context.Context) {
|
|||||||
"Content-Type",
|
"Content-Type",
|
||||||
"authorization",
|
"authorization",
|
||||||
"From-Ui",
|
"From-Ui",
|
||||||
|
"X-Application-Name",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
originsOk := handlers.AllowedOrigins(strings.Split(servercfg.GetAllowedOrigin(), ","))
|
originsOk := handlers.AllowedOrigins(strings.Split(servercfg.GetAllowedOrigin(), ","))
|
||||||
|
@@ -253,6 +253,10 @@ func deleteUserAccessTokens(w http.ResponseWriter, r *http.Request) {
|
|||||||
// @Failure 401 {object} models.ErrorResponse
|
// @Failure 401 {object} models.ErrorResponse
|
||||||
// @Failure 500 {object} models.ErrorResponse
|
// @Failure 500 {object} models.ErrorResponse
|
||||||
func authenticateUser(response http.ResponseWriter, request *http.Request) {
|
func authenticateUser(response http.ResponseWriter, request *http.Request) {
|
||||||
|
appName := request.Header.Get("X-Application-Name")
|
||||||
|
if appName == "" {
|
||||||
|
appName = logic.NetmakerDesktopApp
|
||||||
|
}
|
||||||
|
|
||||||
// Auth request consists of Mac Address and Password (from node that is authorizing
|
// Auth request consists of Mac Address and Password (from node that is authorizing
|
||||||
// in case of Master, auth is ignored and mac is set to "mastermac"
|
// in case of Master, auth is ignored and mac is set to "mastermac"
|
||||||
@@ -343,7 +347,7 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
username := authRequest.UserName
|
username := authRequest.UserName
|
||||||
jwt, err := logic.VerifyAuthRequest(authRequest)
|
jwt, err := logic.VerifyAuthRequest(authRequest, appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(0, username, "user validation failed: ",
|
logger.Log(0, username, "user validation failed: ",
|
||||||
err.Error())
|
err.Error())
|
||||||
@@ -576,6 +580,11 @@ func completeTOTPSetup(w http.ResponseWriter, r *http.Request) {
|
|||||||
func verifyTOTP(w http.ResponseWriter, r *http.Request) {
|
func verifyTOTP(w http.ResponseWriter, r *http.Request) {
|
||||||
username := r.Header.Get("user")
|
username := r.Header.Get("user")
|
||||||
|
|
||||||
|
appName := r.Header.Get("X-Application-Name")
|
||||||
|
if appName == "" {
|
||||||
|
appName = logic.NetmakerDesktopApp
|
||||||
|
}
|
||||||
|
|
||||||
var req models.UserTOTPVerificationParams
|
var req models.UserTOTPVerificationParams
|
||||||
err := json.NewDecoder(r.Body).Decode(&req)
|
err := json.NewDecoder(r.Body).Decode(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -601,7 +610,7 @@ func verifyTOTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if totp.Validate(req.TOTP, user.TOTPSecret) {
|
if totp.Validate(req.TOTP, user.TOTPSecret) {
|
||||||
jwt, err := logic.CreateUserJWT(user.UserName, user.PlatformRoleID)
|
jwt, err := logic.CreateUserJWT(user.UserName, user.PlatformRoleID, appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("error creating token: %v", err)
|
err = fmt.Errorf("error creating token: %v", err)
|
||||||
logger.Log(0, err.Error())
|
logger.Log(0, err.Error())
|
||||||
|
@@ -24,6 +24,12 @@ const (
|
|||||||
auth_key = "netmaker_auth"
|
auth_key = "netmaker_auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DashboardApp = "dashboard"
|
||||||
|
NetclientApp = "netclient"
|
||||||
|
NetmakerDesktopApp = "netmaker-desktop"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
superUser = models.User{}
|
superUser = models.User{}
|
||||||
)
|
)
|
||||||
@@ -178,7 +184,8 @@ func CreateUser(user *models.User) error {
|
|||||||
user.AuthType = models.OAuth
|
user.AuthType = models.OAuth
|
||||||
}
|
}
|
||||||
AddGlobalNetRolesToAdmins(user)
|
AddGlobalNetRolesToAdmins(user)
|
||||||
_, err = CreateUserJWT(user.UserName, user.PlatformRoleID)
|
// create user will always be called either from API or Dashboard.
|
||||||
|
_, err = CreateUserJWT(user.UserName, user.PlatformRoleID, DashboardApp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(0, "failed to generate token", err.Error())
|
logger.Log(0, "failed to generate token", err.Error())
|
||||||
return err
|
return err
|
||||||
@@ -212,7 +219,7 @@ func CreateSuperAdmin(u *models.User) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VerifyAuthRequest - verifies an auth request
|
// VerifyAuthRequest - verifies an auth request
|
||||||
func VerifyAuthRequest(authRequest models.UserAuthParams) (string, error) {
|
func VerifyAuthRequest(authRequest models.UserAuthParams, appName string) (string, error) {
|
||||||
var result models.User
|
var result models.User
|
||||||
if authRequest.UserName == "" {
|
if authRequest.UserName == "" {
|
||||||
return "", errors.New("username can't be empty")
|
return "", errors.New("username can't be empty")
|
||||||
@@ -245,7 +252,7 @@ func VerifyAuthRequest(authRequest models.UserAuthParams) (string, error) {
|
|||||||
return tokenString, nil
|
return tokenString, nil
|
||||||
} else {
|
} else {
|
||||||
// Create a new JWT for the node
|
// Create a new JWT for the node
|
||||||
tokenString, err := CreateUserJWT(authRequest.UserName, result.PlatformRoleID)
|
tokenString, err := CreateUserJWT(authRequest.UserName, result.PlatformRoleID, appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("error creating jwt", "error", err)
|
slog.Error("error creating jwt", "error", err)
|
||||||
return "", err
|
return "", err
|
||||||
@@ -483,8 +490,9 @@ func GetState(state string) (*models.SsoState, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetState - sets a state with new expiration
|
// SetState - sets a state with new expiration
|
||||||
func SetState(state string) error {
|
func SetState(appName, state string) error {
|
||||||
s := models.SsoState{
|
s := models.SsoState{
|
||||||
|
AppName: appName,
|
||||||
Value: state,
|
Value: state,
|
||||||
Expiration: time.Now().Add(models.DefaultExpDuration),
|
Expiration: time.Now().Add(models.DefaultExpDuration),
|
||||||
}
|
}
|
||||||
|
@@ -83,9 +83,13 @@ func CreateUserAccessJwtToken(username string, role models.UserRoleID, d time.Ti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateUserJWT - creates a user jwt token
|
// CreateUserJWT - creates a user jwt token
|
||||||
func CreateUserJWT(username string, role models.UserRoleID) (response string, err error) {
|
func CreateUserJWT(username string, role models.UserRoleID, appName string) (response string, err error) {
|
||||||
settings := GetServerSettings()
|
duration := GetJwtValidityDuration()
|
||||||
expirationTime := time.Now().Add(time.Duration(settings.JwtValidityDuration) * time.Minute)
|
if appName == NetclientApp || appName == NetmakerDesktopApp {
|
||||||
|
duration = GetJwtValidityDurationForClients()
|
||||||
|
}
|
||||||
|
|
||||||
|
expirationTime := time.Now().Add(duration)
|
||||||
claims := &models.UserClaims{
|
claims := &models.UserClaims{
|
||||||
UserName: username,
|
UserName: username,
|
||||||
Role: role,
|
Role: role,
|
||||||
|
@@ -62,6 +62,9 @@ func GetServerSettingsFromEnv() (s models.ServerSettings) {
|
|||||||
Telemetry: servercfg.Telemetry(),
|
Telemetry: servercfg.Telemetry(),
|
||||||
BasicAuth: servercfg.IsBasicAuthEnabled(),
|
BasicAuth: servercfg.IsBasicAuthEnabled(),
|
||||||
JwtValidityDuration: servercfg.GetJwtValidityDurationFromEnv() / 60,
|
JwtValidityDuration: servercfg.GetJwtValidityDurationFromEnv() / 60,
|
||||||
|
// setting client's jwt validity duration to be the same as that of
|
||||||
|
// dashboard.
|
||||||
|
JwtValidityDurationClients: servercfg.GetJwtValidityDurationFromEnv() / 60,
|
||||||
RacRestrictToSingleNetwork: servercfg.GetRacRestrictToSingleNetwork(),
|
RacRestrictToSingleNetwork: servercfg.GetRacRestrictToSingleNetwork(),
|
||||||
EndpointDetection: servercfg.IsEndpointDetectionEnabled(),
|
EndpointDetection: servercfg.IsEndpointDetectionEnabled(),
|
||||||
AllowedEmailDomains: servercfg.GetAllowedEmailDomains(),
|
AllowedEmailDomains: servercfg.GetAllowedEmailDomains(),
|
||||||
@@ -139,6 +142,7 @@ func GetServerConfig() config.ServerConfig {
|
|||||||
cfg.IsPro = "yes"
|
cfg.IsPro = "yes"
|
||||||
}
|
}
|
||||||
cfg.JwtValidityDuration = time.Duration(settings.JwtValidityDuration) * time.Minute
|
cfg.JwtValidityDuration = time.Duration(settings.JwtValidityDuration) * time.Minute
|
||||||
|
cfg.JwtValidityDurationClients = time.Duration(settings.JwtValidityDurationClients) * time.Minute
|
||||||
cfg.RacRestrictToSingleNetwork = settings.RacRestrictToSingleNetwork
|
cfg.RacRestrictToSingleNetwork = settings.RacRestrictToSingleNetwork
|
||||||
cfg.MetricInterval = settings.MetricInterval
|
cfg.MetricInterval = settings.MetricInterval
|
||||||
cfg.ManageDNS = settings.ManageDNS
|
cfg.ManageDNS = settings.ManageDNS
|
||||||
@@ -201,7 +205,13 @@ func Telemetry() string {
|
|||||||
|
|
||||||
// GetJwtValidityDuration - returns the JWT validity duration in minutes
|
// GetJwtValidityDuration - returns the JWT validity duration in minutes
|
||||||
func GetJwtValidityDuration() time.Duration {
|
func GetJwtValidityDuration() time.Duration {
|
||||||
return GetServerConfig().JwtValidityDuration
|
return time.Duration(GetServerSettings().JwtValidityDuration) * time.Minute
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetJwtValidityDurationForClients returns the JWT validity duration in
|
||||||
|
// minutes for clients.
|
||||||
|
func GetJwtValidityDurationForClients() time.Duration {
|
||||||
|
return time.Duration(GetServerSettings().JwtValidityDurationClients) * time.Minute
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRacRestrictToSingleNetwork - returns whether the feature to allow simultaneous network connections via RAC is enabled
|
// GetRacRestrictToSingleNetwork - returns whether the feature to allow simultaneous network connections via RAC is enabled
|
||||||
|
@@ -641,5 +641,8 @@ func settings() {
|
|||||||
if settings.DefaultDomain == "" {
|
if settings.DefaultDomain == "" {
|
||||||
settings.DefaultDomain = servercfg.GetDefaultDomain()
|
settings.DefaultDomain = servercfg.GetDefaultDomain()
|
||||||
}
|
}
|
||||||
|
if settings.JwtValidityDurationClients == 0 {
|
||||||
|
settings.JwtValidityDurationClients = servercfg.GetJwtValidityDurationFromEnv() / 60
|
||||||
|
}
|
||||||
logic.UpsertServerSettings(settings)
|
logic.UpsertServerSettings(settings)
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,12 @@ type ServerSettings struct {
|
|||||||
IDPSyncInterval string `json:"idp_sync_interval"`
|
IDPSyncInterval string `json:"idp_sync_interval"`
|
||||||
Telemetry string `json:"telemetry"`
|
Telemetry string `json:"telemetry"`
|
||||||
BasicAuth bool `json:"basic_auth"`
|
BasicAuth bool `json:"basic_auth"`
|
||||||
|
// JwtValidityDuration is the validity duration of auth tokens for users
|
||||||
|
// on the dashboard (NMUI).
|
||||||
JwtValidityDuration int `json:"jwt_validity_duration"`
|
JwtValidityDuration int `json:"jwt_validity_duration"`
|
||||||
|
// JwtValidityDurationClients is the validity duration of auth tokens for
|
||||||
|
// users on the clients (NetDesk).
|
||||||
|
JwtValidityDurationClients int `json:"jwt_validity_duration_clients"`
|
||||||
MFAEnforced bool `json:"mfa_enforced"`
|
MFAEnforced bool `json:"mfa_enforced"`
|
||||||
RacRestrictToSingleNetwork bool `json:"rac_restrict_to_single_network"`
|
RacRestrictToSingleNetwork bool `json:"rac_restrict_to_single_network"`
|
||||||
EndpointDetection bool `json:"endpoint_detection"`
|
EndpointDetection bool `json:"endpoint_detection"`
|
||||||
|
@@ -7,6 +7,7 @@ const DefaultExpDuration = time.Minute * 5
|
|||||||
|
|
||||||
// SsoState - holds SSO sign-in session data
|
// SsoState - holds SSO sign-in session data
|
||||||
type SsoState struct {
|
type SsoState struct {
|
||||||
|
AppName string `json:"app_name"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
Expiration time.Time `json:"expiration"`
|
Expiration time.Time `json:"expiration"`
|
||||||
}
|
}
|
||||||
|
@@ -40,13 +40,18 @@ func initAzureAD(redirectURL string, clientID string, clientSecret string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleAzureLogin(w http.ResponseWriter, r *http.Request) {
|
func handleAzureLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
appName := r.Header.Get("X-Application-Name")
|
||||||
|
if appName == "" {
|
||||||
|
appName = logic.NetmakerDesktopApp
|
||||||
|
}
|
||||||
|
|
||||||
var oauth_state_string = logic.RandomString(user_signin_length)
|
var oauth_state_string = logic.RandomString(user_signin_length)
|
||||||
if auth_provider == nil {
|
if auth_provider == nil {
|
||||||
handleOauthNotConfigured(w)
|
handleOauthNotConfigured(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := logic.SetState(oauth_state_string); err != nil {
|
if err := logic.SetState(appName, oauth_state_string); err != nil {
|
||||||
handleOauthNotConfigured(w)
|
handleOauthNotConfigured(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -56,9 +61,15 @@ func handleAzureLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleAzureCallback(w http.ResponseWriter, r *http.Request) {
|
func handleAzureCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
var rState, rCode = getStateAndCode(r)
|
var rState, rCode = getStateAndCode(r)
|
||||||
var content, err = getAzureUserInfo(rState, rCode)
|
|
||||||
|
state, err := logic.GetState(rState)
|
||||||
|
if err != nil {
|
||||||
|
handleOauthNotValid(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := getAzureUserInfo(rState, rCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(1, "error when getting user info from azure:", err.Error())
|
logger.Log(1, "error when getting user info from azure:", err.Error())
|
||||||
if strings.Contains(err.Error(), "invalid oauth state") || strings.Contains(err.Error(), "failed to fetch user email from SSO state") {
|
if strings.Contains(err.Error(), "invalid oauth state") || strings.Contains(err.Error(), "failed to fetch user email from SSO state") {
|
||||||
@@ -179,7 +190,7 @@ func handleAzureCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
Password: newPass,
|
Password: newPass,
|
||||||
}
|
}
|
||||||
|
|
||||||
var jwt, jwtErr = logic.VerifyAuthRequest(authRequest)
|
var jwt, jwtErr = logic.VerifyAuthRequest(authRequest, state.AppName)
|
||||||
if jwtErr != nil {
|
if jwtErr != nil {
|
||||||
logger.Log(1, "could not parse jwt for user", authRequest.UserName)
|
logger.Log(1, "could not parse jwt for user", authRequest.UserName)
|
||||||
return
|
return
|
||||||
|
@@ -40,13 +40,18 @@ func initGithub(redirectURL string, clientID string, clientSecret string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleGithubLogin(w http.ResponseWriter, r *http.Request) {
|
func handleGithubLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
appName := r.Header.Get("X-Application-Name")
|
||||||
|
if appName == "" {
|
||||||
|
appName = logic.NetmakerDesktopApp
|
||||||
|
}
|
||||||
|
|
||||||
var oauth_state_string = logic.RandomString(user_signin_length)
|
var oauth_state_string = logic.RandomString(user_signin_length)
|
||||||
if auth_provider == nil {
|
if auth_provider == nil {
|
||||||
handleOauthNotConfigured(w)
|
handleOauthNotConfigured(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := logic.SetState(oauth_state_string); err != nil {
|
if err := logic.SetState(appName, oauth_state_string); err != nil {
|
||||||
handleOauthNotConfigured(w)
|
handleOauthNotConfigured(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -56,9 +61,15 @@ func handleGithubLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleGithubCallback(w http.ResponseWriter, r *http.Request) {
|
func handleGithubCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
var rState, rCode = getStateAndCode(r)
|
var rState, rCode = getStateAndCode(r)
|
||||||
var content, err = getGithubUserInfo(rState, rCode)
|
|
||||||
|
state, err := logic.GetState(rState)
|
||||||
|
if err != nil {
|
||||||
|
handleOauthNotValid(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := getGithubUserInfo(rState, rCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(1, "error when getting user info from github:", err.Error())
|
logger.Log(1, "error when getting user info from github:", err.Error())
|
||||||
if strings.Contains(err.Error(), "invalid oauth state") || strings.Contains(err.Error(), "failed to fetch user email from SSO state") {
|
if strings.Contains(err.Error(), "invalid oauth state") || strings.Contains(err.Error(), "failed to fetch user email from SSO state") {
|
||||||
@@ -170,7 +181,7 @@ func handleGithubCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
Password: newPass,
|
Password: newPass,
|
||||||
}
|
}
|
||||||
|
|
||||||
var jwt, jwtErr = logic.VerifyAuthRequest(authRequest)
|
var jwt, jwtErr = logic.VerifyAuthRequest(authRequest, state.AppName)
|
||||||
if jwtErr != nil {
|
if jwtErr != nil {
|
||||||
logger.Log(1, "could not parse jwt for user", authRequest.UserName)
|
logger.Log(1, "could not parse jwt for user", authRequest.UserName)
|
||||||
return
|
return
|
||||||
|
@@ -40,13 +40,18 @@ func initGoogle(redirectURL string, clientID string, clientSecret string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
|
func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
appName := r.Header.Get("X-Application-Name")
|
||||||
|
if appName == "" {
|
||||||
|
appName = logic.NetmakerDesktopApp
|
||||||
|
}
|
||||||
|
|
||||||
var oauth_state_string = logic.RandomString(user_signin_length)
|
var oauth_state_string = logic.RandomString(user_signin_length)
|
||||||
if auth_provider == nil {
|
if auth_provider == nil {
|
||||||
handleOauthNotConfigured(w)
|
handleOauthNotConfigured(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Log(0, "Setting OAuth State ", oauth_state_string)
|
logger.Log(0, "Setting OAuth State ", oauth_state_string)
|
||||||
if err := logic.SetState(oauth_state_string); err != nil {
|
if err := logic.SetState(appName, oauth_state_string); err != nil {
|
||||||
handleOauthNotConfigured(w)
|
handleOauthNotConfigured(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -56,10 +61,16 @@ func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
|
func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
var rState, rCode = getStateAndCode(r)
|
var rState, rCode = getStateAndCode(r)
|
||||||
logger.Log(0, "Fetched OAuth State ", rState)
|
logger.Log(0, "Fetched OAuth State ", rState)
|
||||||
var content, err = getGoogleUserInfo(rState, rCode)
|
|
||||||
|
state, err := logic.GetState(rState)
|
||||||
|
if err != nil {
|
||||||
|
handleOauthNotValid(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := getGoogleUserInfo(rState, rCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(1, "error when getting user info from google:", err.Error())
|
logger.Log(1, "error when getting user info from google:", err.Error())
|
||||||
if strings.Contains(err.Error(), "invalid oauth state") {
|
if strings.Contains(err.Error(), "invalid oauth state") {
|
||||||
@@ -162,7 +173,7 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
Password: newPass,
|
Password: newPass,
|
||||||
}
|
}
|
||||||
|
|
||||||
var jwt, jwtErr = logic.VerifyAuthRequest(authRequest)
|
var jwt, jwtErr = logic.VerifyAuthRequest(authRequest, state.AppName)
|
||||||
if jwtErr != nil {
|
if jwtErr != nil {
|
||||||
logger.Log(1, "could not parse jwt for user", authRequest.UserName)
|
logger.Log(1, "could not parse jwt for user", authRequest.UserName)
|
||||||
return
|
return
|
||||||
|
@@ -86,7 +86,7 @@ func HandleHeadlessSSOCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
jwt, jwtErr := logic.VerifyAuthRequest(models.UserAuthParams{
|
jwt, jwtErr := logic.VerifyAuthRequest(models.UserAuthParams{
|
||||||
UserName: user.UserName,
|
UserName: user.UserName,
|
||||||
Password: newPass,
|
Password: newPass,
|
||||||
})
|
}, logic.NetclientApp)
|
||||||
if jwtErr != nil {
|
if jwtErr != nil {
|
||||||
logger.Log(1, "could not parse jwt for user", userClaims.getUserName())
|
logger.Log(1, "could not parse jwt for user", userClaims.getUserName())
|
||||||
return
|
return
|
||||||
|
@@ -52,13 +52,18 @@ func initOIDC(redirectURL string, clientID string, clientSecret string, issuer s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleOIDCLogin(w http.ResponseWriter, r *http.Request) {
|
func handleOIDCLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
appName := r.Header.Get("X-Application-Name")
|
||||||
|
if appName == "" {
|
||||||
|
appName = logic.NetmakerDesktopApp
|
||||||
|
}
|
||||||
|
|
||||||
var oauth_state_string = logic.RandomString(user_signin_length)
|
var oauth_state_string = logic.RandomString(user_signin_length)
|
||||||
if auth_provider == nil {
|
if auth_provider == nil {
|
||||||
handleOauthNotConfigured(w)
|
handleOauthNotConfigured(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := logic.SetState(oauth_state_string); err != nil {
|
if err := logic.SetState(appName, oauth_state_string); err != nil {
|
||||||
handleOauthNotConfigured(w)
|
handleOauthNotConfigured(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -67,10 +72,15 @@ func handleOIDCLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleOIDCCallback(w http.ResponseWriter, r *http.Request) {
|
func handleOIDCCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
var rState, rCode = getStateAndCode(r)
|
var rState, rCode = getStateAndCode(r)
|
||||||
|
|
||||||
var content, err = getOIDCUserInfo(rState, rCode)
|
state, err := logic.GetState(rState)
|
||||||
|
if err != nil {
|
||||||
|
handleOauthNotValid(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := getOIDCUserInfo(rState, rCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(1, "error when getting user info from callback:", err.Error())
|
logger.Log(1, "error when getting user info from callback:", err.Error())
|
||||||
if strings.Contains(err.Error(), "invalid oauth state") {
|
if strings.Contains(err.Error(), "invalid oauth state") {
|
||||||
@@ -170,7 +180,7 @@ func handleOIDCCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
Password: newPass,
|
Password: newPass,
|
||||||
}
|
}
|
||||||
|
|
||||||
var jwt, jwtErr = logic.VerifyAuthRequest(authRequest)
|
var jwt, jwtErr = logic.VerifyAuthRequest(authRequest, state.AppName)
|
||||||
if jwtErr != nil {
|
if jwtErr != nil {
|
||||||
logger.Log(1, "could not parse jwt for user", authRequest.UserName, jwtErr.Error())
|
logger.Log(1, "could not parse jwt for user", authRequest.UserName, jwtErr.Error())
|
||||||
return
|
return
|
||||||
|
@@ -38,82 +38,7 @@ func SetHost() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetServerConfig - gets the server config into memory from file or env
|
// GetJwtValidityDurationFromEnv - returns the JWT validity duration in seconds
|
||||||
func GetServerConfig() config.ServerConfig {
|
|
||||||
var cfg config.ServerConfig
|
|
||||||
cfg.APIConnString = GetAPIConnString()
|
|
||||||
cfg.CoreDNSAddr = GetCoreDNSAddr()
|
|
||||||
cfg.APIHost = GetAPIHost()
|
|
||||||
cfg.APIPort = GetAPIPort()
|
|
||||||
cfg.MasterKey = "(hidden)"
|
|
||||||
cfg.DNSKey = "(hidden)"
|
|
||||||
cfg.AllowedOrigin = GetAllowedOrigin()
|
|
||||||
cfg.RestBackend = "off"
|
|
||||||
cfg.NodeID = GetNodeID()
|
|
||||||
cfg.BrokerType = GetBrokerType()
|
|
||||||
cfg.EmqxRestEndpoint = GetEmqxRestEndpoint()
|
|
||||||
if AutoUpdateEnabled() {
|
|
||||||
cfg.NetclientAutoUpdate = "enabled"
|
|
||||||
} else {
|
|
||||||
cfg.NetclientAutoUpdate = "disabled"
|
|
||||||
}
|
|
||||||
if IsRestBackend() {
|
|
||||||
cfg.RestBackend = "on"
|
|
||||||
}
|
|
||||||
cfg.DNSMode = "off"
|
|
||||||
if IsDNSMode() {
|
|
||||||
cfg.DNSMode = "on"
|
|
||||||
}
|
|
||||||
cfg.DisplayKeys = "off"
|
|
||||||
if IsDisplayKeys() {
|
|
||||||
cfg.DisplayKeys = "on"
|
|
||||||
}
|
|
||||||
cfg.DisableRemoteIPCheck = "off"
|
|
||||||
if DisableRemoteIPCheck() {
|
|
||||||
cfg.DisableRemoteIPCheck = "on"
|
|
||||||
}
|
|
||||||
cfg.Database = GetDB()
|
|
||||||
cfg.Platform = GetPlatform()
|
|
||||||
cfg.Version = GetVersion()
|
|
||||||
cfg.PublicIp = GetServerHostIP()
|
|
||||||
|
|
||||||
// == auth config ==
|
|
||||||
var authInfo = GetAuthProviderInfo()
|
|
||||||
cfg.AuthProvider = authInfo[0]
|
|
||||||
cfg.ClientID = authInfo[1]
|
|
||||||
cfg.ClientSecret = authInfo[2]
|
|
||||||
cfg.FrontendURL = GetFrontendURL()
|
|
||||||
cfg.Telemetry = Telemetry()
|
|
||||||
cfg.Server = GetServer()
|
|
||||||
cfg.Verbosity = GetVerbosity()
|
|
||||||
cfg.IsPro = "no"
|
|
||||||
if IsPro {
|
|
||||||
cfg.IsPro = "yes"
|
|
||||||
}
|
|
||||||
cfg.JwtValidityDuration = GetJwtValidityDuration()
|
|
||||||
cfg.RacRestrictToSingleNetwork = GetRacRestrictToSingleNetwork()
|
|
||||||
cfg.MetricInterval = GetMetricInterval()
|
|
||||||
cfg.ManageDNS = GetManageDNS()
|
|
||||||
cfg.Stun = IsStunEnabled()
|
|
||||||
cfg.StunServers = GetStunServers()
|
|
||||||
cfg.DefaultDomain = GetDefaultDomain()
|
|
||||||
return cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetJwtValidityDuration - returns the JWT validity duration in seconds
|
|
||||||
func GetJwtValidityDuration() time.Duration {
|
|
||||||
var defaultDuration = time.Duration(24) * time.Hour
|
|
||||||
if os.Getenv("JWT_VALIDITY_DURATION") != "" {
|
|
||||||
t, err := strconv.Atoi(os.Getenv("JWT_VALIDITY_DURATION"))
|
|
||||||
if err != nil {
|
|
||||||
return defaultDuration
|
|
||||||
}
|
|
||||||
return time.Duration(t) * time.Second
|
|
||||||
}
|
|
||||||
return defaultDuration
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetJwtValidityDuration - returns the JWT validity duration in seconds
|
|
||||||
func GetJwtValidityDurationFromEnv() int {
|
func GetJwtValidityDurationFromEnv() int {
|
||||||
var defaultDuration = 43200
|
var defaultDuration = 43200
|
||||||
if os.Getenv("JWT_VALIDITY_DURATION") != "" {
|
if os.Getenv("JWT_VALIDITY_DURATION") != "" {
|
||||||
|
Reference in New Issue
Block a user