2021-03-31 10:40:44 -05:00
|
|
|
package contexthandler
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2022-07-07 09:28:04 -05:00
|
|
|
"net/http"
|
2021-03-31 10:40:44 -05:00
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/login"
|
|
|
|
"github.com/grafana/grafana/pkg/models"
|
2022-07-20 07:50:06 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/user"
|
2021-03-31 10:40:44 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
const InvalidJWT = "Invalid JWT"
|
2022-01-13 10:15:22 -06:00
|
|
|
const UserNotFound = "User not found"
|
2021-03-31 10:40:44 -05:00
|
|
|
|
|
|
|
func (h *ContextHandler) initContextWithJWT(ctx *models.ReqContext, orgId int64) bool {
|
|
|
|
if !h.Cfg.JWTAuthEnabled || h.Cfg.JWTAuthHeaderName == "" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
jwtToken := ctx.Req.Header.Get(h.Cfg.JWTAuthHeaderName)
|
2022-07-27 09:10:47 -05:00
|
|
|
if jwtToken == "" && h.Cfg.JWTAuthURLLogin {
|
|
|
|
jwtToken = ctx.Req.URL.Query().Get("auth_token")
|
|
|
|
}
|
|
|
|
|
2021-03-31 10:40:44 -05:00
|
|
|
if jwtToken == "" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
claims, err := h.JWTAuthService.Verify(ctx.Req.Context(), jwtToken)
|
|
|
|
if err != nil {
|
|
|
|
ctx.Logger.Debug("Failed to verify JWT", "error", err)
|
2022-07-07 09:28:04 -05:00
|
|
|
ctx.JsonApiErr(http.StatusUnauthorized, InvalidJWT, err)
|
2021-03-31 10:40:44 -05:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
query := models.GetSignedInUserQuery{OrgId: orgId}
|
|
|
|
|
2022-01-13 10:15:22 -06:00
|
|
|
sub, _ := claims["sub"].(string)
|
|
|
|
|
|
|
|
if sub == "" {
|
|
|
|
ctx.Logger.Warn("Got a JWT without the mandatory 'sub' claim", "error", err)
|
2022-07-07 09:28:04 -05:00
|
|
|
ctx.JsonApiErr(http.StatusUnauthorized, InvalidJWT, err)
|
2022-01-13 10:15:22 -06:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
extUser := &models.ExternalUserInfo{
|
|
|
|
AuthModule: "jwt",
|
|
|
|
AuthId: sub,
|
|
|
|
}
|
|
|
|
|
2021-03-31 10:40:44 -05:00
|
|
|
if key := h.Cfg.JWTAuthUsernameClaim; key != "" {
|
|
|
|
query.Login, _ = claims[key].(string)
|
2022-01-13 10:15:22 -06:00
|
|
|
extUser.Login, _ = claims[key].(string)
|
2021-03-31 10:40:44 -05:00
|
|
|
}
|
|
|
|
if key := h.Cfg.JWTAuthEmailClaim; key != "" {
|
|
|
|
query.Email, _ = claims[key].(string)
|
2022-01-13 10:15:22 -06:00
|
|
|
extUser.Email, _ = claims[key].(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
if name, _ := claims["name"].(string); name != "" {
|
|
|
|
extUser.Name = name
|
2021-03-31 10:40:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if query.Login == "" && query.Email == "" {
|
|
|
|
ctx.Logger.Debug("Failed to get an authentication claim from JWT")
|
2022-07-07 09:28:04 -05:00
|
|
|
ctx.JsonApiErr(http.StatusUnauthorized, InvalidJWT, err)
|
2021-03-31 10:40:44 -05:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2022-01-13 10:15:22 -06:00
|
|
|
if h.Cfg.JWTAuthAutoSignUp {
|
|
|
|
upsert := &models.UpsertUserCommand{
|
|
|
|
ReqContext: ctx,
|
|
|
|
SignupAllowed: h.Cfg.JWTAuthAutoSignUp,
|
|
|
|
ExternalUser: extUser,
|
2022-07-15 04:21:09 -05:00
|
|
|
UserLookupParams: models.UserLookupParams{
|
|
|
|
UserID: nil,
|
|
|
|
Login: &query.Login,
|
|
|
|
Email: &query.Email,
|
|
|
|
},
|
2022-01-13 10:15:22 -06:00
|
|
|
}
|
2022-04-08 03:33:19 -05:00
|
|
|
if err := h.loginService.UpsertUser(ctx.Req.Context(), upsert); err != nil {
|
2022-01-13 10:15:22 -06:00
|
|
|
ctx.Logger.Error("Failed to upsert JWT user", "error", err)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-06 09:31:26 -05:00
|
|
|
if err := h.SQLStore.GetSignedInUserWithCacheCtx(ctx.Req.Context(), &query); err != nil {
|
2022-07-20 07:50:06 -05:00
|
|
|
if errors.Is(err, user.ErrUserNotFound) {
|
2021-03-31 10:40:44 -05:00
|
|
|
ctx.Logger.Debug(
|
|
|
|
"Failed to find user using JWT claims",
|
|
|
|
"email_claim", query.Email,
|
|
|
|
"username_claim", query.Login,
|
|
|
|
)
|
|
|
|
err = login.ErrInvalidCredentials
|
2022-07-07 09:28:04 -05:00
|
|
|
ctx.JsonApiErr(http.StatusUnauthorized, UserNotFound, err)
|
2021-03-31 10:40:44 -05:00
|
|
|
} else {
|
|
|
|
ctx.Logger.Error("Failed to get signed in user", "error", err)
|
2022-07-07 09:28:04 -05:00
|
|
|
ctx.JsonApiErr(http.StatusUnauthorized, InvalidJWT, err)
|
2021-03-31 10:40:44 -05:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.SignedInUser = query.Result
|
|
|
|
ctx.IsSignedIn = true
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|