mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: deduplicate OAuth login code (#3575)
This commit is contained in:
+33
-28
@@ -77,7 +77,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
user, organizationID, err := api.createUser(r.Context(), createUserRequest{
|
||||
user, organizationID, err := api.createUser(r.Context(), api.Database, createUserRequest{
|
||||
CreateUserRequest: codersdk.CreateUserRequest{
|
||||
Email: createUser.Email,
|
||||
Username: createUser.Username,
|
||||
@@ -246,7 +246,7 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
user, _, err := api.createUser(r.Context(), createUserRequest{
|
||||
user, _, err := api.createUser(r.Context(), api.Database, createUserRequest{
|
||||
CreateUserRequest: req,
|
||||
LoginType: database.LoginTypePassword,
|
||||
})
|
||||
@@ -722,16 +722,22 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
sessionToken, created := api.createAPIKey(rw, r, createAPIKeyParams{
|
||||
cookie, err := api.createAPIKey(r, createAPIKeyParams{
|
||||
UserID: user.ID,
|
||||
LoginType: database.LoginTypePassword,
|
||||
})
|
||||
if !created {
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Failed to create API key.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
http.SetCookie(rw, cookie)
|
||||
|
||||
httpapi.Write(rw, http.StatusCreated, codersdk.LoginWithPasswordResponse{
|
||||
SessionToken: sessionToken,
|
||||
SessionToken: cookie.Value,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -745,7 +751,7 @@ func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
lifeTime := time.Hour * 24 * 7
|
||||
sessionToken, created := api.createAPIKey(rw, r, createAPIKeyParams{
|
||||
cookie, err := api.createAPIKey(r, createAPIKeyParams{
|
||||
UserID: user.ID,
|
||||
LoginType: database.LoginTypePassword,
|
||||
// All api generated keys will last 1 week. Browser login tokens have
|
||||
@@ -753,11 +759,19 @@ func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
ExpiresAt: database.Now().Add(lifeTime),
|
||||
LifetimeSeconds: int64(lifeTime.Seconds()),
|
||||
})
|
||||
if !created {
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Failed to create API key.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusCreated, codersdk.GenerateAPIKeyResponse{Key: sessionToken})
|
||||
// We intentionally do not set the cookie on the response here.
|
||||
// Setting the cookie will couple the browser sesion to the API
|
||||
// key we return here, meaning logging out of the website would
|
||||
// invalid your CLI key.
|
||||
httpapi.Write(rw, http.StatusCreated, codersdk.GenerateAPIKeyResponse{Key: cookie.Value})
|
||||
}
|
||||
|
||||
func (api *API) apiKey(rw http.ResponseWriter, r *http.Request) {
|
||||
@@ -840,14 +854,10 @@ type createAPIKeyParams struct {
|
||||
LifetimeSeconds int64
|
||||
}
|
||||
|
||||
func (api *API) createAPIKey(rw http.ResponseWriter, r *http.Request, params createAPIKeyParams) (string, bool) {
|
||||
func (api *API) createAPIKey(r *http.Request, params createAPIKeyParams) (*http.Cookie, error) {
|
||||
keyID, keySecret, err := generateAPIKeyIDSecret()
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error generating API key.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return "", false
|
||||
return nil, xerrors.Errorf("generate API key: %w", err)
|
||||
}
|
||||
hashed := sha256.Sum256([]byte(keySecret))
|
||||
|
||||
@@ -885,11 +895,7 @@ func (api *API) createAPIKey(rw http.ResponseWriter, r *http.Request, params cre
|
||||
LoginType: params.LoginType,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error inserting API key.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return "", false
|
||||
return nil, xerrors.Errorf("insert API key: %w", err)
|
||||
}
|
||||
|
||||
api.Telemetry.Report(&telemetry.Snapshot{
|
||||
@@ -898,15 +904,14 @@ func (api *API) createAPIKey(rw http.ResponseWriter, r *http.Request, params cre
|
||||
|
||||
// This format is consumed by the APIKey middleware.
|
||||
sessionToken := fmt.Sprintf("%s-%s", keyID, keySecret)
|
||||
http.SetCookie(rw, &http.Cookie{
|
||||
return &http.Cookie{
|
||||
Name: codersdk.SessionTokenKey,
|
||||
Value: sessionToken,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
Secure: api.SecureAuthCookie,
|
||||
})
|
||||
return sessionToken, true
|
||||
}, nil
|
||||
}
|
||||
|
||||
type createUserRequest struct {
|
||||
@@ -914,13 +919,13 @@ type createUserRequest struct {
|
||||
LoginType database.LoginType
|
||||
}
|
||||
|
||||
func (api *API) createUser(ctx context.Context, req createUserRequest) (database.User, uuid.UUID, error) {
|
||||
func (api *API) createUser(ctx context.Context, store database.Store, req createUserRequest) (database.User, uuid.UUID, error) {
|
||||
var user database.User
|
||||
return user, req.OrganizationID, api.Database.InTx(func(db database.Store) error {
|
||||
return user, req.OrganizationID, store.InTx(func(tx database.Store) error {
|
||||
orgRoles := make([]string, 0)
|
||||
// If no organization is provided, create a new one for the user.
|
||||
if req.OrganizationID == uuid.Nil {
|
||||
organization, err := db.InsertOrganization(ctx, database.InsertOrganizationParams{
|
||||
organization, err := tx.InsertOrganization(ctx, database.InsertOrganizationParams{
|
||||
ID: uuid.New(),
|
||||
Name: req.Username,
|
||||
CreatedAt: database.Now(),
|
||||
@@ -953,7 +958,7 @@ func (api *API) createUser(ctx context.Context, req createUserRequest) (database
|
||||
}
|
||||
|
||||
var err error
|
||||
user, err = db.InsertUser(ctx, params)
|
||||
user, err = tx.InsertUser(ctx, params)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create user: %w", err)
|
||||
}
|
||||
@@ -962,7 +967,7 @@ func (api *API) createUser(ctx context.Context, req createUserRequest) (database
|
||||
if err != nil {
|
||||
return xerrors.Errorf("generate user gitsshkey: %w", err)
|
||||
}
|
||||
_, err = db.InsertGitSSHKey(ctx, database.InsertGitSSHKeyParams{
|
||||
_, err = tx.InsertGitSSHKey(ctx, database.InsertGitSSHKeyParams{
|
||||
UserID: user.ID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
@@ -972,7 +977,7 @@ func (api *API) createUser(ctx context.Context, req createUserRequest) (database
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert user gitsshkey: %w", err)
|
||||
}
|
||||
_, err = db.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
|
||||
_, err = tx.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
|
||||
OrganizationID: req.OrganizationID,
|
||||
UserID: user.ID,
|
||||
CreatedAt: database.Now(),
|
||||
|
||||
Reference in New Issue
Block a user