diff --git a/lib/auth/apiserver.go b/lib/auth/apiserver.go index 96c31b09f003..dc1afafbb562 100644 --- a/lib/auth/apiserver.go +++ b/lib/auth/apiserver.go @@ -97,7 +97,7 @@ func NewAPIServer(config *APIConfig) http.Handler { srv.PUT("/:version/users/:user/web/password", srv.withAuth(srv.changePassword)) srv.POST("/:version/users/:user/web/password", srv.withAuth(srv.upsertPassword)) srv.POST("/:version/users/:user/web/password/check", srv.withAuth(srv.checkPassword)) - srv.POST("/:version/users/:user/web/sessions", srv.withAuth(srv.extendWebSession)) + srv.POST("/:version/users/:user/web/sessions", srv.withAuth(srv.createWebSession)) srv.POST("/:version/users/:user/web/authenticate", srv.withAuth(srv.authenticateWebUser)) srv.POST("/:version/users/:user/ssh/authenticate", srv.withAuth(srv.authenticateSSHUser)) srv.GET("/:version/users/:user/web/sessions/:sid", srv.withAuth(srv.getWebSession)) @@ -672,21 +672,24 @@ type createWebSessionReq struct { PrevSessionID string `json:"prev_session_id"` } -func (s *APIServer) extendWebSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) { +func (s *APIServer) createWebSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) { var req *createWebSessionReq if err := httplib.ReadJSON(r, &req); err != nil { return nil, trace.Wrap(err) } user := p.ByName("user") - if req.PrevSessionID == "" { - return nil, trace.BadParameter("previous session ID missing") + if req.PrevSessionID != "" { + sess, err := auth.ExtendWebSession(user, req.PrevSessionID) + if err != nil { + return nil, trace.Wrap(err) + } + return sess, nil } - - sess, err := auth.ExtendWebSession(user, req.PrevSessionID) + sess, err := auth.CreateWebSession(user) if err != nil { return nil, trace.Wrap(err) } - return sess, nil + return rawMessage(services.GetWebSessionMarshaler().MarshalWebSession(sess, services.WithVersion(version))) } func (s *APIServer) authenticateWebUser(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) { diff --git a/lib/auth/auth.go b/lib/auth/auth.go index a4153baef771..7ab170f8f574 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -651,6 +651,28 @@ func (s *AuthServer) ExtendWebSession(user string, prevSessionID string, identit return sess, nil } +// CreateWebSession creates a new web session for user without any +// checks, is used by admins +func (s *AuthServer) CreateWebSession(user string, identity *tlsca.Identity) (services.WebSession, error) { + fmt.Printf("--> CreateWebSession: %v.\n", identity.Username) + roles, traits, err := services.ExtractFromIdentity(s, identity) + if err != nil { + return nil, trace.Wrap(err) + } + sess, err := s.NewWebSession(user, roles, traits) + if err != nil { + return nil, trace.Wrap(err) + } + if err := s.UpsertWebSession(user, sess); err != nil { + return nil, trace.Wrap(err) + } + sess, err = services.GetWebSessionMarshaler().GenerateWebSession(sess) + if err != nil { + return nil, trace.Wrap(err) + } + return sess, nil +} + // GenerateTokenRequest is a request to generate auth token type GenerateTokenRequest struct { // Token if provided sets the token value, otherwise will be auto generated diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index a8249fdd28b1..ca94e2d46357 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -592,6 +592,13 @@ func (a *AuthWithRoles) GetU2FSignRequest(user string, password []byte) (*u2f.Si return a.authServer.U2FSignRequest(user, password) } +func (a *AuthWithRoles) CreateWebSession(user string) (services.WebSession, error) { + if err := a.currentUserAction(user); err != nil { + return nil, trace.Wrap(err) + } + return a.authServer.CreateWebSession(user, &a.identity) +} + func (a *AuthWithRoles) ExtendWebSession(user, prevSessionID string) (services.WebSession, error) { if err := a.currentUserAction(user); err != nil { return nil, trace.Wrap(err) diff --git a/lib/auth/clt.go b/lib/auth/clt.go index 9c732d332c36..296f7216aab2 100644 --- a/lib/auth/clt.go +++ b/lib/auth/clt.go @@ -1025,6 +1025,18 @@ func (c *Client) ExtendWebSession(user string, prevSessionID string) (services.W return services.GetWebSessionMarshaler().UnmarshalWebSession(out.Bytes()) } +// CreateWebSession creates a new web session for a user +func (c *Client) CreateWebSession(user string) (services.WebSession, error) { + out, err := c.PostJSON( + c.Endpoint("users", user, "web", "sessions"), + createWebSessionReq{}, + ) + if err != nil { + return nil, trace.Wrap(err) + } + return services.GetWebSessionMarshaler().UnmarshalWebSession(out.Bytes()) +} + // AuthenticateWebUser authenticates web user, creates and returns web session // in case if authentication is successful func (c *Client) AuthenticateWebUser(req AuthenticateUserRequest) (services.WebSession, error) { @@ -2143,6 +2155,8 @@ type WebService interface { // ExtendWebSession creates a new web session for a user based on another // valid web session ExtendWebSession(user string, prevSessionID string) (services.WebSession, error) + // CreateWebSession creates a new web session for a user + CreateWebSession(user string) (services.WebSession, error) // DeleteWebSession deletes a web session for this user by id DeleteWebSession(user string, sid string) error }