Auth: Allow soft token revocation (#31601)

* Add revoked_at field to user auth token to allow soft revokes

* Allow soft token revocations

* Update token revocations and tests

* Return error info on revokedTokenErr

* Override session cookie only when no revokedErr nor API request

* Display modal on revoked token error

* Feedback: Refactor TokenRevokedModal to FC

* Add GetUserRevokedTokens into UserTokenService

* Backendsrv: adds tests and refactors soft token path

* Apply feedback

* Write redirect cookie on token revoked error

* Update TokenRevokedModal style

* Return meaningful error info

* Some UI changes

* Update backend_srv tests

* Minor style fix on backend_srv tests

* Replace deprecated method usage to publish events

* Fix backend_srv tests

* Apply suggestions from code review

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com>

* Apply suggestions from code review

* Apply suggestions from code review

Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com>

* Minor style fix after PR suggestion commit

* Apply suggestions from code review

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

* Prettier fixes

Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>
This commit is contained in:
Joan López de la Franca Beltran
2021-03-16 17:44:02 +01:00
committed by GitHub
parent a1c7e0630d
commit 610999cfa2
13 changed files with 286 additions and 30 deletions

View File

@@ -1,6 +1,7 @@
package middleware
import (
"errors"
"net/url"
"regexp"
"strconv"
@@ -34,6 +35,27 @@ func notAuthorized(c *models.ReqContext) {
return
}
writeRedirectCookie(c)
c.Redirect(setting.AppSubUrl + "/login")
}
func tokenRevoked(c *models.ReqContext, err *models.TokenRevokedError) {
if c.IsApiRequest() {
c.JSON(401, map[string]interface{}{
"message": "Token revoked",
"error": map[string]interface{}{
"id": "ERR_TOKEN_REVOKED",
"maxConcurrentSessions": err.MaxConcurrentSessions,
},
})
return
}
writeRedirectCookie(c)
c.Redirect(setting.AppSubUrl + "/login")
}
func writeRedirectCookie(c *models.ReqContext) {
redirectTo := c.Req.RequestURI
if setting.AppSubUrl != "" && !strings.HasPrefix(redirectTo, setting.AppSubUrl) {
redirectTo = setting.AppSubUrl + c.Req.RequestURI
@@ -43,7 +65,6 @@ func notAuthorized(c *models.ReqContext) {
redirectTo = removeForceLoginParams(redirectTo)
cookies.WriteCookie(c.Resp, "redirect_to", url.QueryEscape(redirectTo), 0, nil)
c.Redirect(setting.AppSubUrl + "/login")
}
var forceLoginParamsRegexp = regexp.MustCompile(`&?forceLogin=true`)
@@ -90,6 +111,13 @@ func Auth(options *AuthOptions) macaron.Handler {
requireLogin := !c.AllowAnonymous || forceLogin || options.ReqNoAnonynmous
if !c.IsSignedIn && options.ReqSignedIn && requireLogin {
lookupTokenErr, hasTokenErr := c.Data["lookupTokenErr"].(error)
var revokedErr *models.TokenRevokedError
if hasTokenErr && errors.As(lookupTokenErr, &revokedErr) {
tokenRevoked(c, revokedErr)
return
}
notAuthorized(c)
return
}