oauth

package
v0.9.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ChatGPTAuthEndpoint  = "https://auth.openai.com/oauth/authorize"
	ChatGPTTokenEndpoint = "https://auth.openai.com/oauth/token"
	// Temporary until we figure out how term-llm can get a proper client ID
	ChatGPTClientID     = "app_EMoamEEZ73f0CkXaXp7hrann"
	ChatGPTRedirectURI  = "http://localhost:1455/auth/callback"
	ChatGPTScopes       = "openid profile email offline_access"
	ChatGPTCallbackPort = 1455
)
View Source
const (
	ChatGPTDeviceAuthBaseURL     = "https://auth.openai.com/api/accounts"
	ChatGPTDeviceVerificationURL = "https://auth.openai.com/codex/device"
	ChatGPTDeviceRedirectURI     = "https://auth.openai.com/deviceauth/callback"
)

The device code flow talks to OpenAI's /deviceauth endpoints. It is the same flow codex uses for headless/remote sign-in — no local callback server, no browser redirect to localhost, just a URL + code the user visits on any device.

View Source
const (
	// CopilotClientID is the VS Code GitHub Copilot extension's client ID.
	// This is required for access to GitHub's internal Copilot APIs (usage, token exchange).
	// Using the VS Code client ID is a common approach in the Copilot developer community.
	CopilotClientID = "Iv1.b507a08c87ecfe98"

	// CopilotScope is the OAuth scope required for Copilot API access
	CopilotScope = "read:user"
)
View Source
const (
	GrokClientID = "b1a00492-073a-47ea-816f-4c329264a828"
	// term-llm only calls the subscription Responses and model-catalog APIs, so
	// conversations/workspaces scopes from grok-build are intentionally omitted.
	GrokScopes = "openid profile email offline_access grok-cli:access api:access"

	GrokDeviceEndpoint   = "https://auth.x.ai/oauth2/device/code"
	GrokTokenEndpoint    = "https://auth.x.ai/oauth2/token"
	GrokUserInfoEndpoint = "https://auth.x.ai/oauth2/userinfo"
	GrokRevokeEndpoint   = "https://auth.x.ai/oauth2/revoke"
)

Variables

View Source
var (
	ErrGrokAccessDenied        = errors.New("Grok authorization was denied")
	ErrGrokDeviceCodeExpired   = errors.New("Grok device authorization expired")
	ErrGrokRefreshTokenInvalid = errors.New("Grok refresh token expired or revoked")
)
View Source
var ErrChatGPTDeviceCodeNotEnabled = errors.New("chatgpt device code login is not enabled")

ErrChatGPTDeviceCodeNotEnabled is returned when the backend does not advertise device-code login (HTTP 404). Callers should fall back to the interactive browser flow.

View Source
var ErrChatGPTRefreshTokenInvalid = errors.New("ChatGPT refresh token expired or revoked")

ErrChatGPTRefreshTokenInvalid indicates that the authorization server has definitively rejected a refresh token, rather than a transient refresh error.

Functions

func GrokExpiryUnix added in v0.0.404

func GrokExpiryUnix(now, expiresIn int64) (int64, error)

func OpenBrowser added in v0.9.11

func OpenBrowser(url string) error

OpenBrowser opens a URL in the user's default browser.

func ValidGrokAccountID added in v0.0.404

func ValidGrokAccountID(accountID string) bool

ValidGrokAccountID accepts only bounded visible ASCII so userinfo.sub is safe to copy into x-grok-user-id/x-userid headers.

func ValidateGrokDeviceCodeForDisplay added in v0.0.404

func ValidateGrokDeviceCodeForDisplay(device *GrokDeviceCode) error

ValidateGrokDeviceCodeForDisplay ensures device-flow values are safe to render in a terminal and that verification URLs remain on x.ai-owned HTTPS hosts.

Types

type ChatGPTCredentials

type ChatGPTCredentials struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	ExpiresAt    int64  `json:"expires_at"` // Unix timestamp in seconds
	AccountID    string `json:"account_id"` // ChatGPT account ID from JWT
}

ChatGPTCredentials holds the OAuth tokens

func AuthenticateChatGPT

func AuthenticateChatGPT(ctx context.Context) (*ChatGPTCredentials, error)

AuthenticateChatGPT runs the full OAuth flow and returns credentials

func AuthenticateChatGPTDevice added in v0.0.170

func AuthenticateChatGPTDevice(ctx context.Context, dc *ChatGPTDeviceCode) (*ChatGPTCredentials, error)

AuthenticateChatGPTDevice runs the full device-code OAuth flow. The caller is responsible for printing the verification URL + user code between RequestChatGPTDeviceCode and this call — taking a callback here keeps the prompt UX out of the oauth package.

func (*ChatGPTCredentials) IsExpired

func (c *ChatGPTCredentials) IsExpired() bool

IsExpired returns true if the access token is expired or will expire within 5 minutes

type ChatGPTDeviceCode added in v0.0.170

type ChatGPTDeviceCode struct {
	VerificationURL string
	UserCode        string
	// contains filtered or unexported fields
}

ChatGPTDeviceCode is the user-facing output of the usercode request.

func RequestChatGPTDeviceCode added in v0.0.170

func RequestChatGPTDeviceCode(ctx context.Context) (*ChatGPTDeviceCode, error)

RequestChatGPTDeviceCode asks OpenAI for a new device-auth pair. Returns ErrChatGPTDeviceCodeNotEnabled when the server returns 404.

type ChatGPTTokenResponse

type ChatGPTTokenResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	IDToken      string `json:"id_token"`
	ExpiresIn    int    `json:"expires_in"`
	TokenType    string `json:"token_type"`
}

func RefreshToken

func RefreshToken(refreshToken string) (*ChatGPTTokenResponse, error)

RefreshToken refreshes an expired access token

type CopilotCredentials added in v0.0.34

type CopilotCredentials struct {
	AccessToken string `json:"access_token"`
	ExpiresAt   int64  `json:"expires_at"` // 0 = no expiry tracking
}

CopilotCredentials holds the OAuth token for Copilot. Note: credentials.CopilotCredentials is the storage type with the same fields.

func AuthenticateCopilot added in v0.0.34

func AuthenticateCopilot(ctx context.Context) (*CopilotCredentials, error)

AuthenticateCopilot runs the full device code OAuth flow and returns credentials

type CopilotDeviceCodeResponse added in v0.0.34

type CopilotDeviceCodeResponse struct {
	DeviceCode      string `json:"device_code"`
	UserCode        string `json:"user_code"`
	VerificationURI string `json:"verification_uri"`
	ExpiresIn       int    `json:"expires_in"`
	Interval        int    `json:"interval"` // Polling interval in seconds
}

CopilotDeviceCodeResponse holds the device code response from GitHub

func RequestCopilotDeviceCode added in v0.0.34

func RequestCopilotDeviceCode() (*CopilotDeviceCodeResponse, error)

RequestCopilotDeviceCode initiates the device code flow

type CopilotTokenResponse added in v0.0.34

type CopilotTokenResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	Scope       string `json:"scope"`
	Error       string `json:"error,omitempty"`
}

CopilotTokenResponse holds the token response from GitHub

func PollForCopilotToken added in v0.0.34

func PollForCopilotToken(ctx context.Context, deviceCode string, interval int) (*CopilotTokenResponse, error)

PollForCopilotToken polls for the access token after the user has authorized

type GrokDeviceCode added in v0.0.404

type GrokDeviceCode struct {
	DeviceCode              string `json:"device_code"`
	UserCode                string `json:"user_code"`
	VerificationURI         string `json:"verification_uri"`
	VerificationURIComplete string `json:"verification_uri_complete"`
	ExpiresIn               int64  `json:"expires_in"`
	Interval                int64  `json:"interval"`
}

type GrokOAuthClient added in v0.0.404

type GrokOAuthClient struct {
	HTTPClient *http.Client
	// contains filtered or unexported fields
}

GrokOAuthClient implements xAI's RFC 8628 device flow. Endpoint replacement is intentionally private; tests inject a transport that rewrites production URLs.

func NewGrokOAuthClient added in v0.0.404

func NewGrokOAuthClient(httpClient *http.Client) *GrokOAuthClient

func (*GrokOAuthClient) PollDeviceToken added in v0.0.404

func (c *GrokOAuthClient) PollDeviceToken(ctx context.Context, device *GrokDeviceCode) (*GrokTokenResponse, error)

func (*GrokOAuthClient) RefreshToken added in v0.0.404

func (c *GrokOAuthClient) RefreshToken(ctx context.Context, refreshToken string) (*GrokTokenResponse, error)

func (*GrokOAuthClient) RequestDeviceCode added in v0.0.404

func (c *GrokOAuthClient) RequestDeviceCode(ctx context.Context) (*GrokDeviceCode, error)

func (*GrokOAuthClient) Revoke added in v0.0.404

func (c *GrokOAuthClient) Revoke(ctx context.Context, token string) error

func (*GrokOAuthClient) UserInfo added in v0.0.404

func (c *GrokOAuthClient) UserInfo(ctx context.Context, accessToken string) (string, error)

type GrokTokenResponse added in v0.0.404

type GrokTokenResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int64  `json:"expires_in"`
	TokenType    string `json:"token_type"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL