OAuth: Introduce user_refresh_token setting and make it default for the selected providers (#71533)
* First changes * WIP docs * Align current tests * Add test for UseRefreshToken * Update docs * Fix * Remove unnecessary AuthCodeURL from generic_oauth * Change GitHub to disable use_refresh_token by default
This commit is contained in:
@@ -3,10 +3,12 @@ package sync
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
||||
@@ -15,15 +17,19 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
errExpiredAccessToken = errutil.NewBase(errutil.StatusUnauthorized, "oauth.expired-token")
|
||||
errExpiredAccessToken = errutil.NewBase(
|
||||
errutil.StatusUnauthorized,
|
||||
"oauth.expired-token",
|
||||
errutil.WithPublicMessage("OAuth access token expired"))
|
||||
)
|
||||
|
||||
func ProvideOAuthTokenSync(service oauthtoken.OAuthTokenService, sessionService auth.UserTokenService) *OAuthTokenSync {
|
||||
func ProvideOAuthTokenSync(service oauthtoken.OAuthTokenService, sessionService auth.UserTokenService, socialService social.Service) *OAuthTokenSync {
|
||||
return &OAuthTokenSync{
|
||||
log.New("oauth_token.sync"),
|
||||
localcache.New(maxOAuthTokenCacheTTL, 15*time.Minute),
|
||||
service,
|
||||
sessionService,
|
||||
socialService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +38,7 @@ type OAuthTokenSync struct {
|
||||
cache *localcache.CacheService
|
||||
service oauthtoken.OAuthTokenService
|
||||
sessionService auth.UserTokenService
|
||||
socialService social.Service
|
||||
}
|
||||
|
||||
func (s *OAuthTokenSync) SyncOauthTokenHook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
||||
@@ -64,6 +71,19 @@ func (s *OAuthTokenSync) SyncOauthTokenHook(ctx context.Context, identity *authn
|
||||
return nil
|
||||
}
|
||||
|
||||
// get the token's auth provider (f.e. azuread)
|
||||
provider := strings.TrimPrefix(token.AuthModule, "oauth_")
|
||||
currentOAuthInfo := s.socialService.GetOAuthInfoProvider(provider)
|
||||
if currentOAuthInfo == nil {
|
||||
s.log.Warn("OAuth provider not found", "provider", provider)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if refresh token handling is disabled for this provider, we can skip the hook
|
||||
if !currentOAuthInfo.UseRefreshToken {
|
||||
return nil
|
||||
}
|
||||
|
||||
expires := token.OAuthExpiry.Round(0).Add(-oauthtoken.ExpiryDelta)
|
||||
// token has not expired, so we don't have to refresh it
|
||||
if !expires.Before(time.Now()) {
|
||||
@@ -78,14 +98,14 @@ func (s *OAuthTokenSync) SyncOauthTokenHook(ctx context.Context, identity *authn
|
||||
}
|
||||
|
||||
if err := s.service.InvalidateOAuthTokens(ctx, token); err != nil {
|
||||
s.log.FromContext(ctx).Error("Failed invalidate OAuth tokens", "id", identity.ID, "error", err)
|
||||
s.log.FromContext(ctx).Error("Failed to invalidate OAuth tokens", "id", identity.ID, "error", err)
|
||||
}
|
||||
|
||||
if err := s.sessionService.RevokeToken(ctx, identity.SessionToken, false); err != nil {
|
||||
s.log.FromContext(ctx).Error("Failed to revoke session token", "id", identity.ID, "tokenId", identity.SessionToken.Id, "error", err)
|
||||
}
|
||||
|
||||
return errExpiredAccessToken.Errorf("oauth access token could not be refreshed: %w", auth.ErrInvalidSessionToken)
|
||||
return errExpiredAccessToken.Errorf("oauth access token could not be refreshed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user