22
33from __future__ import annotations
44
5+ import os
6+
57from requests import Response , Session
68from typing_extensions import TYPE_CHECKING , overload
79
810from . import hooks , me
11+ from ._utils import is_local
912from .auth import Auth
1013from .config import Config
1114from .content import Content
@@ -174,16 +177,27 @@ def __init__(self, *args, **kwargs) -> None:
174177 self ._ctx = Context (self )
175178
176179 @requires ("2025.01.0-dev" )
177- def with_user_session_token (self , token : str ) -> Client :
180+ def with_user_session_token (
181+ self , token : str , fallback_api_key_env_var : str = "CONNECT_API_KEY"
182+ ) -> Client :
178183 """Create a new Client scoped to the user specified in the user session token.
179184
180185 Create a new Client instance from a user session token exchange for an api key scoped to the
181- user specified in the token.
186+ user specified in the token (the user viewing your app). If running your application locally,
187+ you will not have a user session token. In that case, this method will look for an API key in
188+ the environment variable specified in `fallback_api_key_env_var`. If that is not set, the API
189+ key of the original client will be used.
190+
191+ Environment Variables
192+ ---------------------
193+ CONNECT_API_KEY - The API key credential for client authentication.
182194
183195 Parameters
184196 ----------
185197 token : str
186198 The user session token.
199+ fallback_api_key_env_var: str
200+ Environment variable with a fallback API key for local development.
187201
188202 Returns
189203 -------
@@ -195,14 +209,27 @@ def with_user_session_token(self, token: str) -> Client:
195209 >>> from posit.connect import Client
196210 >>> client = Client().with_user_session_token("my-user-session-token")
197211 """
198- viewer_credentials = self .oauth .get_credentials (
212+ if is_local ():
213+ # if user session token is not available when running locally,
214+ # default to using API set in environment variable
215+ return Client (
216+ url = self .cfg .url ,
217+ api_key = os .getenv (fallback_api_key_env_var , self .cfg .api_key ),
218+ )
219+
220+ if token is None or token == "" :
221+ # if deployed to Connect, token must be set
222+ raise ValueError ("token must be set to non-empty string." )
223+
224+ visitor_credentials = self .oauth .get_credentials (
199225 token , requested_token_type = API_KEY_TOKEN_TYPE
200226 )
201- viewer_api_key = viewer_credentials .get ("access_token" )
202- if viewer_api_key is None :
203- raise ValueError ("Unable to retrieve viewer api key." )
204227
205- return Client (url = self .cfg .url , api_key = viewer_api_key )
228+ visitor_api_key = visitor_credentials .get ("access_token" , "" )
229+ if visitor_api_key == "" :
230+ raise ValueError ("Unable to retrieve visitor API key." )
231+
232+ return Client (url = self .cfg .url , api_key = visitor_api_key )
206233
207234 @property
208235 def content (self ) -> Content :
0 commit comments