func (s *Server) RefreshToken(creds oidc.ClientCredentials, scopes scope.Scopes, token string) (*jose.JWT, error) { ok, err := s.ClientManager.Authenticate(creds) if err != nil { log.Errorf("Failed fetching client %s from repo: %v", creds.ID, err) return nil, oauth2.NewError(oauth2.ErrorServerError) } if !ok { log.Errorf("Failed to Authenticate client %s", creds.ID) return nil, oauth2.NewError(oauth2.ErrorInvalidClient) } userID, rtScopes, err := s.RefreshTokenRepo.Verify(creds.ID, token) switch err { case nil: break case refresh.ErrorInvalidToken: return nil, oauth2.NewError(oauth2.ErrorInvalidRequest) case refresh.ErrorInvalidClientID: return nil, oauth2.NewError(oauth2.ErrorInvalidClient) default: return nil, oauth2.NewError(oauth2.ErrorServerError) } if len(scopes) == 0 { scopes = rtScopes } else { if !rtScopes.Contains(scopes) { return nil, oauth2.NewError(oauth2.ErrorInvalidRequest) } } user, err := s.UserRepo.Get(nil, userID) if err != nil { // The error can be user.ErrorNotFound, but we are not deleting // user at this moment, so this shouldn't happen. log.Errorf("Failed to fetch user %q from repo: %v: ", userID, err) return nil, oauth2.NewError(oauth2.ErrorServerError) } signer, err := s.KeyManager.Signer() if err != nil { log.Errorf("Failed to refresh ID token: %v", err) return nil, oauth2.NewError(oauth2.ErrorServerError) } now := time.Now() expireAt := now.Add(session.DefaultSessionValidityWindow) claims := oidc.NewClaims(s.IssuerURL.String(), user.ID, creds.ID, now, expireAt) user.AddToClaims(claims) s.addClaimsFromScope(claims, scope.Scopes(scopes), creds.ID) jwt, err := jose.NewSignedJWT(claims, signer) if err != nil { log.Errorf("Failed to generate ID token: %v", err) return nil, oauth2.NewError(oauth2.ErrorServerError) } log.Infof("New token sent: clientID=%s", creds.ID) return jwt, nil }
func (s *Server) RefreshToken(creds oidc.ClientCredentials, scopes scope.Scopes, token string) (*jose.JWT, string, time.Time, error) { ok, err := s.ClientManager.Authenticate(creds) if err != nil { log.Errorf("Failed fetching client %s from repo: %v", creds.ID, err) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } if !ok { log.Errorf("Failed to Authenticate client %s", creds.ID) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorInvalidClient) } userID, connectorID, rtScopes, err := s.RefreshTokenRepo.Verify(creds.ID, token) switch err { case nil: break case refresh.ErrorInvalidToken: return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorInvalidRequest) case refresh.ErrorInvalidClientID: return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorInvalidClient) default: return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } if len(scopes) == 0 { scopes = rtScopes } else { if !rtScopes.Contains(scopes) { return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorInvalidRequest) } } usr, err := s.UserRepo.Get(nil, userID) if err != nil { // The error can be user.ErrorNotFound, but we are not deleting // user at this moment, so this shouldn't happen. log.Errorf("Failed to fetch user %q from repo: %v: ", userID, err) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } var groups []string if rtScopes.HasScope(scope.ScopeGroups) { conn, ok := s.connector(connectorID) if !ok { log.Errorf("refresh token contained invalid connector ID (%s)", connectorID) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } grouper, ok := conn.(connector.GroupsConnector) if !ok { log.Errorf("refresh token requested groups for connector (%s) that doesn't support groups", connectorID) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } remoteIdentities, err := s.UserRepo.GetRemoteIdentities(nil, userID) if err != nil { log.Errorf("failed to get remote identities: %v", err) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } remoteIdentity, ok := func() (user.RemoteIdentity, bool) { for _, ri := range remoteIdentities { if ri.ConnectorID == connectorID { return ri, true } } return user.RemoteIdentity{}, false }() if !ok { log.Errorf("failed to get remote identity for connector %s", connectorID) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } if groups, err = grouper.Groups(remoteIdentity.ID); err != nil { log.Errorf("failed to get groups for refresh token: %v", connectorID) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } } signer, err := s.KeyManager.Signer() if err != nil { log.Errorf("Failed to refresh ID token: %v", err) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } now := time.Now() expiresAt := now.Add(session.DefaultSessionValidityWindow) claims := oidc.NewClaims(s.IssuerURL.String(), usr.ID, creds.ID, now, expiresAt) usr.AddToClaims(claims) if rtScopes.HasScope(scope.ScopeGroups) { if groups == nil { groups = []string{} } claims["groups"] = groups } s.addClaimsFromScope(claims, scope.Scopes(scopes), creds.ID) jwt, err := jose.NewSignedJWT(claims, signer) if err != nil { log.Errorf("Failed to generate ID token: %v", err) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } refreshToken, err := s.RefreshTokenRepo.RenewRefreshToken(creds.ID, userID, token) if err != nil { log.Errorf("Failed to generate new refresh token: %v", err) return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError) } log.Infof("New token sent: clientID=%s", creds.ID) return jwt, refreshToken, expiresAt, nil }