(ctx context.Context, params apikey.CreateParams)
| 563 | } |
| 564 | |
| 565 | func (api *API) createAPIKey(ctx context.Context, params apikey.CreateParams) (*http.Cookie, *database.APIKey, error) { |
| 566 | key, sessionToken, err := apikey.Generate(params) |
| 567 | if err != nil { |
| 568 | return nil, nil, xerrors.Errorf("generate API key: %w", err) |
| 569 | } |
| 570 | |
| 571 | newkey, err := api.Database.InsertAPIKey(ctx, key) |
| 572 | if err != nil { |
| 573 | return nil, nil, xerrors.Errorf("insert API key: %w", err) |
| 574 | } |
| 575 | |
| 576 | api.Telemetry.Report(&telemetry.Snapshot{ |
| 577 | APIKeys: []telemetry.APIKey{telemetry.ConvertAPIKey(newkey)}, |
| 578 | }) |
| 579 | |
| 580 | return api.DeploymentValues.HTTPCookies.Apply(&http.Cookie{ |
| 581 | Name: codersdk.SessionTokenCookie, |
| 582 | Value: sessionToken, |
| 583 | Path: "/", |
| 584 | HttpOnly: true, |
| 585 | // MaxAge is set so the browser persists the cookie to disk rather |
| 586 | // than keeping it in memory as a session cookie. Standalone PWAs |
| 587 | // (display: standalone) run in their own browser process, and |
| 588 | // mobile OSes kill that process when the app is swiped away — |
| 589 | // deleting in-memory cookies and forcing an unexpected login. |
| 590 | // |
| 591 | // We use a long static value (1 year) instead of the key's |
| 592 | // LifetimeSeconds because the server refreshes the key's |
| 593 | // ExpiresAt on activity but does not re-set the cookie. Tying |
| 594 | // MaxAge to the key lifetime would cause the cookie to expire |
| 595 | // client-side even when the server-side key is still valid. |
| 596 | // |
| 597 | // Security is not affected: the server validates ExpiresAt on |
| 598 | // every request regardless of the cookie's MaxAge. |
| 599 | MaxAge: int((365 * 24 * time.Hour).Seconds()), |
| 600 | }), &newkey, nil |
| 601 | } |
no test coverage detected