Skip to content

Conversation

@drstrangelooker
Copy link
Collaborator

The Looker Go SDK was not automatically refreshing expired authentication tokens, causing authentication to fail after one hour. This change modifies the AuthSession to proactively manage the token's lifecycle. An IsActive method was added to check the token's validity, and a Login method was added to refresh the token when needed. The Do method was updated to call Login before making any API requests, ensuring the token is always active.

Fixes #1606 🦕

The Looker Go SDK was not automatically refreshing expired authentication tokens, causing authentication to fail after one hour. This change modifies the AuthSession to proactively manage the token's lifecycle. An IsActive method was added to check the token's validity, and a Login method was added to refresh the token when needed. The Do method was updated to call Login before making any API requests, ensuring the token is always active.
@drstrangelooker drstrangelooker requested a review from a team as a code owner October 23, 2025 19:03
@gemini-code-assist
Copy link

Summary of Changes

Hello @drstrangelooker, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical issue in the Looker Go SDK where authentication tokens were not automatically refreshed, leading to authentication failures after their one-hour expiry. The changes introduce a robust token management system within the AuthSession, allowing it to proactively check token validity and refresh tokens as needed before making API calls, ensuring continuous and reliable authentication for the SDK.

Highlights

  • Token Management: The AuthSession struct now includes fields to store the current oauth2.Token and its oauth2.TokenSource, enabling direct management of the authentication token lifecycle within the session.
  • Token Validity Check: A new IsActive() method has been added to AuthSession to determine if the current authentication token is still valid, incorporating a 10-second leeway before its actual expiration time.
  • Token Refresh Mechanism: A Login() method was introduced to AuthSession which proactively refreshes the authentication token using the stored TokenSource if the current token is found to be inactive or expired.
  • Proactive Authentication: The AuthSession.Do() method now calls Login() before executing any API requests, ensuring that an active and valid authentication token is always used, thereby preventing failures due to expired tokens.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces automatic token refresh for the Go SDK by adding IsActive and Login methods to AuthSession and calling Login before each API request. This is a good improvement to handle expired tokens proactively. My main feedback is regarding thread safety. The new stateful nature of AuthSession introduces a data race when used concurrently. I've provided a suggestion to add a mutex and update the new methods to be thread-safe. This is important for the reliability of the SDK in concurrent applications.

Comment on lines +46 to 65
func (s *AuthSession) IsActive() bool {
if s.token == nil {
return false
}
leeway := time.Second * 10
return s.token.Expiry.After(time.Now().Add(leeway))
}

func (s *AuthSession) Login() (*oauth2.Token, error) {
if s.IsActive() {
return s.token, nil
}

token, err := s.source.Token()
if err != nil {
return nil, err
}
s.token = token
return token, nil
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The AuthSession is likely to be used concurrently, but the new methods IsActive and Login introduce data races when accessing the s.token field. IsActive reads s.token while Login writes to it, without any synchronization.

To make AuthSession thread-safe, you should add a sync.RWMutex to the struct:

import "sync" type AuthSession struct { // ... other fields token *oauth2.Token source oauth2.TokenSource mu sync.RWMutex }

Then, you can update IsActive and Login to use this mutex. The implementation below uses a read-lock for checking the token and a write-lock for refreshing it, which is efficient. It also uses the double-checked locking pattern to prevent unnecessary locking when the token is valid.

I've also replaced the magic number 10 * time.Second with a constant for better readability.

const tokenLeeway = 10 * time.Second func (s *AuthSession) IsActive() bool { s.mu.RLock() defer s.mu.RUnlock() if s.token == nil { return false	} return s.token.Expiry.After(time.Now().Add(tokenLeeway)) } func (s *AuthSession) Login() (*oauth2.Token, error) { // First, check with a read lock to avoid contention if the token is valid. s.mu.RLock() if s.token != nil && s.token.Expiry.After(time.Now().Add(tokenLeeway)) { token := s.token s.mu.RUnlock() return token, nil	} s.mu.RUnlock() // If the token is invalid or nil, acquire a write lock to refresh it. s.mu.Lock() defer s.mu.Unlock() // Re-check after obtaining the write lock, in case another goroutine refreshed it. if s.token != nil && s.token.Expiry.After(time.Now().Add(tokenLeeway)) { return s.token, nil	} token, err := s.source.Token() if err != nil { return nil, err	} s.token = token return token, nil }
@github-actions
Copy link
Contributor

github-actions bot commented Oct 23, 2025

Go Tests

  6 files    6 suites   2m 14s ⏱️
 50 tests  50 ✅ 0 💤 0 ❌
120 runs  120 ✅ 0 💤 0 ❌

Results for commit 218e428.

♻️ This comment has been updated with latest results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants