tryAuthenticate attempts to authenticate the request using the database. On success it returns the user and, as a side effect, sets the following values on the Echo context: - contextKeySource ("auth_source"): always set, one of UsageSourceWeb / UsageSourceAPIKey. UsageSourceLegacy is set elsewhere
(c echo.Context, db *gorm.DB, appConfig *config.ApplicationConfig)
| 452 | // contextKeyUser and contextKeyRole are populated by the parent Middleware |
| 453 | // after this function returns. |
| 454 | func tryAuthenticate(c echo.Context, db *gorm.DB, appConfig *config.ApplicationConfig) *User { |
| 455 | hmacSecret := appConfig.Auth.APIKeyHMACSecret |
| 456 | |
| 457 | // a. Session cookie -> web UI |
| 458 | if cookie, err := c.Cookie(sessionCookie); err == nil && cookie.Value != "" { |
| 459 | if user, session := ValidateSession(db, cookie.Value, hmacSecret); user != nil { |
| 460 | // Store session for rotation check in middleware |
| 461 | c.Set("_auth_session", session) |
| 462 | c.Set(contextKeySource, UsageSourceWeb) |
| 463 | return user |
| 464 | } |
| 465 | } |
| 466 | |
| 467 | // b. Authorization: Bearer |
| 468 | authHeader := c.Request().Header.Get("Authorization") |
| 469 | if strings.HasPrefix(authHeader, "Bearer ") { |
| 470 | token := strings.TrimPrefix(authHeader, "Bearer ") |
| 471 | |
| 472 | // b1. Session token via Bearer -> still web UI |
| 473 | if user, _ := ValidateSession(db, token, hmacSecret); user != nil { |
| 474 | c.Set(contextKeySource, UsageSourceWeb) |
| 475 | return user |
| 476 | } |
| 477 | |
| 478 | // b2. Named API key |
| 479 | if key, err := ValidateAPIKey(db, token, hmacSecret); err == nil { |
| 480 | c.Set(contextKeySource, UsageSourceAPIKey) |
| 481 | c.Set(contextKeyAPIKey, key) |
| 482 | return &key.User |
| 483 | } |
| 484 | } |
| 485 | |
| 486 | // c. x-api-key / xi-api-key -> named API key |
| 487 | for _, header := range []string{"x-api-key", "xi-api-key"} { |
| 488 | if k := c.Request().Header.Get(header); k != "" { |
| 489 | if apiKey, err := ValidateAPIKey(db, k, hmacSecret); err == nil { |
| 490 | c.Set(contextKeySource, UsageSourceAPIKey) |
| 491 | c.Set(contextKeyAPIKey, apiKey) |
| 492 | return &apiKey.User |
| 493 | } |
| 494 | } |
| 495 | } |
| 496 | |
| 497 | // d. token cookie -> named API key |
| 498 | if cookie, err := c.Cookie("token"); err == nil && cookie.Value != "" { |
| 499 | if key, err := ValidateAPIKey(db, cookie.Value, hmacSecret); err == nil { |
| 500 | c.Set(contextKeySource, UsageSourceAPIKey) |
| 501 | c.Set(contextKeyAPIKey, key) |
| 502 | return &key.User |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | return nil |
| 507 | } |
| 508 | |
| 509 | // extractKey extracts an API key from the request (all sources). |
| 510 | func extractKey(c echo.Context) string { |
no test coverage detected