user.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "github.com/gorilla/mux"
  8. "github.com/gorilla/websocket"
  9. "github.com/gravitl/netmaker/auth"
  10. "github.com/gravitl/netmaker/logger"
  11. "github.com/gravitl/netmaker/logic"
  12. "github.com/gravitl/netmaker/models"
  13. "github.com/gravitl/netmaker/mq"
  14. "github.com/gravitl/netmaker/servercfg"
  15. "golang.org/x/exp/slog"
  16. )
  17. var (
  18. upgrader = websocket.Upgrader{}
  19. )
  20. func userHandlers(r *mux.Router) {
  21. r.HandleFunc("/api/users/adm/hassuperadmin", hasSuperAdmin).Methods(http.MethodGet)
  22. r.HandleFunc("/api/users/adm/createsuperadmin", createSuperAdmin).Methods(http.MethodPost)
  23. r.HandleFunc("/api/users/adm/transfersuperadmin/{username}", logic.SecurityCheck(true, http.HandlerFunc(transferSuperAdmin))).Methods(http.MethodPost)
  24. r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods(http.MethodPost)
  25. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(updateUser))).Methods(http.MethodPut)
  26. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceUsers, http.HandlerFunc(createUser)))).Methods(http.MethodPost)
  27. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(deleteUser))).Methods(http.MethodDelete)
  28. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUser)))).Methods(http.MethodGet)
  29. r.HandleFunc("/api/users", logic.SecurityCheck(true, http.HandlerFunc(getUsers))).Methods(http.MethodGet)
  30. r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods(http.MethodGet)
  31. r.HandleFunc("/api/oauth/callback", auth.HandleAuthCallback).Methods(http.MethodGet)
  32. r.HandleFunc("/api/oauth/headless", auth.HandleHeadlessSSO)
  33. r.HandleFunc("/api/oauth/register/{regKey}", auth.RegisterHostSSO).Methods(http.MethodGet)
  34. }
  35. // swagger:route POST /api/users/adm/authenticate authenticate authenticateUser
  36. //
  37. // User authenticates using its password and retrieves a JWT for authorization.
  38. //
  39. // Schemes: https
  40. //
  41. // Security:
  42. // oauth
  43. //
  44. // Responses:
  45. // 200: successResponse
  46. func authenticateUser(response http.ResponseWriter, request *http.Request) {
  47. // Auth request consists of Mac Address and Password (from node that is authorizing
  48. // in case of Master, auth is ignored and mac is set to "mastermac"
  49. var authRequest models.UserAuthParams
  50. var errorResponse = models.ErrorResponse{
  51. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  52. }
  53. if !servercfg.IsBasicAuthEnabled() {
  54. logic.ReturnErrorResponse(response, request, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  55. return
  56. }
  57. decoder := json.NewDecoder(request.Body)
  58. decoderErr := decoder.Decode(&authRequest)
  59. defer request.Body.Close()
  60. if decoderErr != nil {
  61. logger.Log(0, "error decoding request body: ",
  62. decoderErr.Error())
  63. logic.ReturnErrorResponse(response, request, errorResponse)
  64. return
  65. }
  66. if val := request.Header.Get("From-Ui"); val == "true" {
  67. // request came from UI, if normal user block Login
  68. user, err := logic.GetUser(authRequest.UserName)
  69. if err != nil {
  70. logger.Log(0, authRequest.UserName, "user validation failed: ",
  71. err.Error())
  72. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  73. return
  74. }
  75. if !(user.IsAdmin || user.IsSuperAdmin) {
  76. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("only admins can access dashboard"), "unauthorized"))
  77. return
  78. }
  79. }
  80. username := authRequest.UserName
  81. jwt, err := logic.VerifyAuthRequest(authRequest)
  82. if err != nil {
  83. logger.Log(0, username, "user validation failed: ",
  84. err.Error())
  85. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "badrequest"))
  86. return
  87. }
  88. if jwt == "" {
  89. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  90. logger.Log(0, username, "jwt token is empty")
  91. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("no token returned"), "internal"))
  92. return
  93. }
  94. var successResponse = models.SuccessResponse{
  95. Code: http.StatusOK,
  96. Message: "W1R3: Device " + username + " Authorized",
  97. Response: models.SuccessfulUserLoginResponse{
  98. AuthToken: jwt,
  99. UserName: username,
  100. },
  101. }
  102. // Send back the JWT
  103. successJSONResponse, jsonError := json.Marshal(successResponse)
  104. if jsonError != nil {
  105. logger.Log(0, username,
  106. "error marshalling resp: ", err.Error())
  107. logic.ReturnErrorResponse(response, request, errorResponse)
  108. return
  109. }
  110. logger.Log(2, username, "was authenticated")
  111. response.Header().Set("Content-Type", "application/json")
  112. response.Write(successJSONResponse)
  113. go func() {
  114. if servercfg.IsPro && servercfg.GetRacAutoDisable() {
  115. // enable all associeated clients for the user
  116. clients, err := logic.GetAllExtClients()
  117. if err != nil {
  118. slog.Error("error getting clients: ", "error", err)
  119. return
  120. }
  121. for _, client := range clients {
  122. if client.OwnerID == username && !client.Enabled {
  123. slog.Info(fmt.Sprintf("enabling ext client %s for user %s due to RAC autodisabling feature", client.ClientID, client.OwnerID))
  124. if newClient, err := logic.ToggleExtClientConnectivity(&client, true); err != nil {
  125. slog.Error("error enabling ext client in RAC autodisable hook", "error", err)
  126. continue // dont return but try for other clients
  127. } else {
  128. // publish peer update to ingress gateway
  129. if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
  130. if err = mq.PublishPeerUpdate(); err != nil {
  131. slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }
  138. }()
  139. }
  140. // swagger:route GET /api/users/adm/hassuperadmin user hasSuperAdmin
  141. //
  142. // Checks whether the server has an admin.
  143. //
  144. // Schemes: https
  145. //
  146. // Security:
  147. // oauth
  148. //
  149. // Responses:
  150. // 200: hasAdmin
  151. func hasSuperAdmin(w http.ResponseWriter, r *http.Request) {
  152. w.Header().Set("Content-Type", "application/json")
  153. hasSuperAdmin, err := logic.HasSuperAdmin()
  154. if err != nil {
  155. logger.Log(0, "failed to check for admin: ", err.Error())
  156. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  157. return
  158. }
  159. json.NewEncoder(w).Encode(hasSuperAdmin)
  160. }
  161. // swagger:route GET /api/users/{username} user getUser
  162. //
  163. // Get an individual user.
  164. //
  165. // Schemes: https
  166. //
  167. // Security:
  168. // oauth
  169. //
  170. // Responses:
  171. // 200: userBodyResponse
  172. func getUser(w http.ResponseWriter, r *http.Request) {
  173. // set header.
  174. w.Header().Set("Content-Type", "application/json")
  175. var params = mux.Vars(r)
  176. usernameFetched := params["username"]
  177. user, err := logic.GetReturnUser(usernameFetched)
  178. if err != nil {
  179. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  180. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  181. return
  182. }
  183. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  184. json.NewEncoder(w).Encode(user)
  185. }
  186. // swagger:route GET /api/users user getUsers
  187. //
  188. // Get all users.
  189. //
  190. // Schemes: https
  191. //
  192. // Security:
  193. // oauth
  194. //
  195. // Responses:
  196. // 200: userBodyResponse
  197. func getUsers(w http.ResponseWriter, r *http.Request) {
  198. // set header.
  199. w.Header().Set("Content-Type", "application/json")
  200. users, err := logic.GetUsers()
  201. if err != nil {
  202. logger.Log(0, "failed to fetch users: ", err.Error())
  203. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  204. return
  205. }
  206. logic.SortUsers(users[:])
  207. logger.Log(2, r.Header.Get("user"), "fetched users")
  208. json.NewEncoder(w).Encode(users)
  209. }
  210. // swagger:route POST /api/users/adm/createsuperadmin user createAdmin
  211. //
  212. // Make a user an admin.
  213. //
  214. // Schemes: https
  215. //
  216. // Security:
  217. // oauth
  218. //
  219. // Responses:
  220. // 200: userBodyResponse
  221. func createSuperAdmin(w http.ResponseWriter, r *http.Request) {
  222. w.Header().Set("Content-Type", "application/json")
  223. var u models.User
  224. err := json.NewDecoder(r.Body).Decode(&u)
  225. if err != nil {
  226. slog.Error("error decoding request body", "error", err.Error())
  227. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  228. return
  229. }
  230. if !servercfg.IsBasicAuthEnabled() {
  231. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  232. return
  233. }
  234. err = logic.CreateSuperAdmin(&u)
  235. if err != nil {
  236. slog.Error("failed to create admin", "error", err.Error())
  237. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  238. return
  239. }
  240. logger.Log(1, u.UserName, "was made a super admin")
  241. json.NewEncoder(w).Encode(logic.ToReturnUser(u))
  242. }
  243. // swagger:route POST /api/users/adm/transfersuperadmin user transferSuperAdmin
  244. //
  245. // Transfers superadmin role to an admin user.
  246. //
  247. // Schemes: https
  248. //
  249. // Security:
  250. // oauth
  251. //
  252. // Responses:
  253. // 200: userBodyResponse
  254. func transferSuperAdmin(w http.ResponseWriter, r *http.Request) {
  255. w.Header().Set("Content-Type", "application/json")
  256. caller, err := logic.GetUser(r.Header.Get("user"))
  257. if err != nil {
  258. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  259. }
  260. if !caller.IsSuperAdmin {
  261. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only superadmin can assign the superadmin role to another user"), "forbidden"))
  262. return
  263. }
  264. var params = mux.Vars(r)
  265. username := params["username"]
  266. u, err := logic.GetUser(username)
  267. if err != nil {
  268. slog.Error("error getting user", "user", u.UserName, "error", err.Error())
  269. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  270. return
  271. }
  272. if !u.IsAdmin {
  273. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only admins can be promoted to superadmin role"), "forbidden"))
  274. return
  275. }
  276. if !servercfg.IsBasicAuthEnabled() {
  277. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  278. return
  279. }
  280. u.IsSuperAdmin = true
  281. u.IsAdmin = false
  282. err = logic.UpsertUser(*u)
  283. if err != nil {
  284. slog.Error("error updating user to superadmin: ", "user", u.UserName, "error", err.Error())
  285. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  286. return
  287. }
  288. caller.IsSuperAdmin = false
  289. caller.IsAdmin = true
  290. err = logic.UpsertUser(*caller)
  291. if err != nil {
  292. slog.Error("error demoting user to admin: ", "user", caller.UserName, "error", err.Error())
  293. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  294. return
  295. }
  296. slog.Info("user was made a super admin", "user", u.UserName)
  297. json.NewEncoder(w).Encode(logic.ToReturnUser(*u))
  298. }
  299. // swagger:route POST /api/users/{username} user createUser
  300. //
  301. // Create a user.
  302. //
  303. // Schemes: https
  304. //
  305. // Security:
  306. // oauth
  307. //
  308. // Responses:
  309. // 200: userBodyResponse
  310. func createUser(w http.ResponseWriter, r *http.Request) {
  311. w.Header().Set("Content-Type", "application/json")
  312. caller, err := logic.GetUser(r.Header.Get("user"))
  313. if err != nil {
  314. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  315. }
  316. var user models.User
  317. err = json.NewDecoder(r.Body).Decode(&user)
  318. if err != nil {
  319. logger.Log(0, user.UserName, "error decoding request body: ",
  320. err.Error())
  321. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  322. return
  323. }
  324. if !caller.IsSuperAdmin && user.IsAdmin {
  325. err = errors.New("only superadmin can create admin users")
  326. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  327. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  328. return
  329. }
  330. if user.IsSuperAdmin {
  331. err = errors.New("additional superadmins cannot be created")
  332. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  333. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  334. return
  335. }
  336. if !servercfg.IsPro && !user.IsAdmin {
  337. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  338. return
  339. }
  340. err = logic.CreateUser(&user)
  341. if err != nil {
  342. slog.Error("error creating new user: ", "user", user.UserName, "error", err.Error())
  343. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  344. return
  345. }
  346. slog.Info("user was created", "username", user.UserName)
  347. json.NewEncoder(w).Encode(logic.ToReturnUser(user))
  348. }
  349. // swagger:route PUT /api/users/{username} user updateUser
  350. //
  351. // Update a user.
  352. //
  353. // Schemes: https
  354. //
  355. // Security:
  356. // oauth
  357. //
  358. // Responses:
  359. // 200: userBodyResponse
  360. func updateUser(w http.ResponseWriter, r *http.Request) {
  361. w.Header().Set("Content-Type", "application/json")
  362. var params = mux.Vars(r)
  363. // start here
  364. var caller *models.User
  365. var err error
  366. var ismaster bool
  367. if r.Header.Get("user") == logic.MasterUser {
  368. ismaster = true
  369. } else {
  370. caller, err = logic.GetUser(r.Header.Get("user"))
  371. if err != nil {
  372. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  373. }
  374. }
  375. username := params["username"]
  376. user, err := logic.GetUser(username)
  377. if err != nil {
  378. logger.Log(0, username,
  379. "failed to update user info: ", err.Error())
  380. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  381. return
  382. }
  383. var userchange models.User
  384. // we decode our body request params
  385. err = json.NewDecoder(r.Body).Decode(&userchange)
  386. if err != nil {
  387. slog.Error("failed to decode body", "error ", err.Error())
  388. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  389. return
  390. }
  391. if user.UserName != userchange.UserName {
  392. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user in param and request body not matching"), "badrequest"))
  393. return
  394. }
  395. selfUpdate := false
  396. if !ismaster && caller.UserName == user.UserName {
  397. selfUpdate = true
  398. }
  399. if !ismaster && !selfUpdate {
  400. if caller.IsAdmin && user.IsSuperAdmin {
  401. slog.Error("non-superadmin user", "caller", caller.UserName, "attempted to update superadmin user", username)
  402. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  403. return
  404. }
  405. if !caller.IsAdmin && !caller.IsSuperAdmin {
  406. slog.Error("operation not allowed", "caller", caller.UserName, "attempted to update user", username)
  407. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  408. return
  409. }
  410. if caller.IsAdmin && user.IsAdmin {
  411. slog.Error("admin user cannot update another admin", "caller", caller.UserName, "attempted to update admin user", username)
  412. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("admin user cannot update another admin"), "forbidden"))
  413. return
  414. }
  415. if caller.IsAdmin && userchange.IsAdmin {
  416. err = errors.New("admin user cannot update role of an another user to admin")
  417. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  418. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  419. return
  420. }
  421. }
  422. if !ismaster && selfUpdate {
  423. if user.IsAdmin != userchange.IsAdmin || user.IsSuperAdmin != userchange.IsSuperAdmin {
  424. slog.Error("user cannot change his own role", "caller", caller.UserName, "attempted to update user role", username)
  425. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user not allowed to self assign role"), "forbidden"))
  426. return
  427. }
  428. }
  429. if ismaster {
  430. if !user.IsSuperAdmin && userchange.IsSuperAdmin {
  431. slog.Error("operation not allowed", "caller", logic.MasterUser, "attempted to update user role to superadmin", username)
  432. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("attempted to update user role to superadmin"), "forbidden"))
  433. return
  434. }
  435. }
  436. if auth.IsOauthUser(user) == nil && userchange.Password != "" {
  437. err := fmt.Errorf("cannot update user's password for an oauth user %s", username)
  438. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  439. return
  440. }
  441. user, err = logic.UpdateUser(&userchange, user)
  442. if err != nil {
  443. logger.Log(0, username,
  444. "failed to update user info: ", err.Error())
  445. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  446. return
  447. }
  448. logger.Log(1, username, "was updated")
  449. json.NewEncoder(w).Encode(logic.ToReturnUser(*user))
  450. }
  451. // swagger:route DELETE /api/users/{username} user deleteUser
  452. //
  453. // Delete a user.
  454. //
  455. // Schemes: https
  456. //
  457. // Security:
  458. // oauth
  459. //
  460. // Responses:
  461. // 200: userBodyResponse
  462. func deleteUser(w http.ResponseWriter, r *http.Request) {
  463. // Set header
  464. w.Header().Set("Content-Type", "application/json")
  465. // get params
  466. var params = mux.Vars(r)
  467. caller, err := logic.GetUser(r.Header.Get("user"))
  468. if err != nil {
  469. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  470. }
  471. username := params["username"]
  472. user, err := logic.GetUser(username)
  473. if err != nil {
  474. logger.Log(0, username,
  475. "failed to update user info: ", err.Error())
  476. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  477. return
  478. }
  479. if user.IsSuperAdmin {
  480. slog.Error(
  481. "failed to delete user: ", "user", username, "error", "superadmin cannot be deleted")
  482. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("superadmin cannot be deleted"), "internal"))
  483. return
  484. }
  485. if !caller.IsSuperAdmin {
  486. if caller.IsAdmin && user.IsAdmin {
  487. slog.Error(
  488. "failed to delete user: ", "user", username, "error", "admin cannot delete another admin user, including oneself")
  489. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("admin cannot delete another admin user, including oneself"), "internal"))
  490. return
  491. }
  492. }
  493. success, err := logic.DeleteUser(username)
  494. if err != nil {
  495. logger.Log(0, username,
  496. "failed to delete user: ", err.Error())
  497. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  498. return
  499. } else if !success {
  500. err := errors.New("delete unsuccessful")
  501. logger.Log(0, username, err.Error())
  502. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  503. return
  504. }
  505. // check and delete extclient with this ownerID
  506. go func() {
  507. extclients, err := logic.GetAllExtClients()
  508. if err != nil {
  509. slog.Error("failed to get extclients", "error", err)
  510. return
  511. }
  512. for _, extclient := range extclients {
  513. if extclient.OwnerID == user.UserName {
  514. err = logic.DeleteExtClient(extclient.Network, extclient.ClientID)
  515. if err != nil {
  516. slog.Error("failed to delete extclient",
  517. "id", extclient.ClientID, "owner", user.UserName, "error", err)
  518. }
  519. }
  520. }
  521. }()
  522. logger.Log(1, username, "was deleted")
  523. json.NewEncoder(w).Encode(params["username"] + " deleted.")
  524. }
  525. // Called when vpn client dials in to start the auth flow and first stage is to get register URL itself
  526. func socketHandler(w http.ResponseWriter, r *http.Request) {
  527. // Upgrade our raw HTTP connection to a websocket based one
  528. conn, err := upgrader.Upgrade(w, r, nil)
  529. if err != nil {
  530. logger.Log(0, "error during connection upgrade for node sign-in:", err.Error())
  531. return
  532. }
  533. if conn == nil {
  534. logger.Log(0, "failed to establish web-socket connection during node sign-in")
  535. return
  536. }
  537. // Start handling the session
  538. go auth.SessionHandler(conn)
  539. }