@@ -35,7 +35,7 @@ use std::{env, path::PathBuf};
3535use pyo3:: prelude:: * ;
3636
3737use self :: {
38- secrets:: { Credential , Secrets } ,
38+ secrets:: { Credential , Secrets , TokenPayload } ,
3939 settings:: Settings ,
4040} ;
4141
@@ -183,26 +183,38 @@ impl ClientConfiguration {
183183
184184 let secrets_path = secrets. file_path ;
185185 let credential = secrets. credentials . remove ( & profile. credentials_name ) ;
186- let ( access_token , refresh_token ) = match credential {
186+ let oauth_session = match credential {
187187 Some ( Credential {
188- token_payload : Some ( token_payload) ,
189- } ) => ( token_payload. access_token , token_payload. refresh_token ) ,
190- _ => ( None , None ) ,
188+ token_payload :
189+ Some ( TokenPayload {
190+ access_token,
191+ refresh_token,
192+ ..
193+ } ) ,
194+ } ) => {
195+ Some ( OAuthSession :: new (
196+ OAuthGrant :: RefreshToken ( RefreshToken :: new (
197+ // Some configurations do not populate or may use an
198+ // empty string for the `refresh_token`, but are still
199+ // valid sessions with a valid `access_token`.
200+ //
201+ // Because we found a `token_payload`, we must assume
202+ // the user wants to construct an `OAuthSession`.
203+ // Note that this is no guarantee of session validity.
204+ refresh_token. unwrap_or_default ( ) ,
205+ ) ) ,
206+ auth_server,
207+ access_token,
208+ ) )
209+ }
210+ _ => None ,
191211 } ;
192212
193213 let api_url = env:: var ( API_URL_VAR ) . unwrap_or ( profile. api_url ) ;
194214 let quilc_url = env:: var ( QUILC_URL_VAR ) . unwrap_or ( profile. applications . pyquil . quilc_url ) ;
195215 let qvm_url = env:: var ( QVM_URL_VAR ) . unwrap_or ( profile. applications . pyquil . qvm_url ) ;
196216 let grpc_api_url = env:: var ( GRPC_API_URL_VAR ) . unwrap_or ( profile. grpc_api_url ) ;
197217
198- let oauth_session = refresh_token. map ( |refresh_token| {
199- OAuthSession :: new (
200- OAuthGrant :: RefreshToken ( RefreshToken :: new ( refresh_token) ) ,
201- auth_server. clone ( ) ,
202- access_token,
203- )
204- } ) ;
205-
206218 #[ cfg( feature = "tracing-config" ) ]
207219 let tracing_configuration =
208220 TracingConfiguration :: from_env ( ) . map_err ( LoadError :: TracingFilterParseError ) ?;
@@ -756,4 +768,72 @@ token_type = "Bearer"
756768 ) ;
757769 assert ! ( tokens. validate( ) . is_err( ) ) ;
758770 }
771+
772+ #[ tokio:: test]
773+ async fn test_session_is_present_with_empty_refresh_token_and_valid_access_token ( ) {
774+ let access_token = Claims :: new_valid ( ) . to_encoded ( ) ;
775+ let mut config = ClientConfiguration :: builder ( ) . build ( ) . unwrap ( ) ;
776+ figment:: Jail :: expect_with ( |jail| {
777+ let directory = jail. directory ( ) ;
778+ let settings_file_name = "settings.toml" ;
779+ let settings_file_path = directory. join ( settings_file_name) ;
780+ let secrets_file_name = "secrets.toml" ;
781+ let secrets_file_path = directory. join ( secrets_file_name) ;
782+
783+ let settings_file_contents = r#"
784+ default_profile_name = "default"
785+
786+ [profiles]
787+ [profiles.default]
788+ api_url = ""
789+ auth_server_name = "default"
790+ credentials_name = "default"
791+
792+ [auth_servers]
793+ [auth_servers.default]
794+ client_id = ""
795+ issuer = ""
796+ "# ;
797+
798+ // note this has no `refresh_token` property
799+ let secrets_file_contents = format ! (
800+ r#"
801+ [credentials]
802+ [credentials.default]
803+ [credentials.default.token_payload]
804+ access_token = "{access_token}"
805+ expires_in = 3600
806+ id_token = "id_token"
807+ scope = "offline_access openid profile email"
808+ token_type = "Bearer"
809+ "#
810+ ) ;
811+
812+ jail. create_file ( settings_file_name, settings_file_contents)
813+ . expect ( "should create test settings.toml" ) ;
814+ jail. create_file ( secrets_file_name, & secrets_file_contents)
815+ . expect ( "should create test secrets.toml" ) ;
816+
817+ jail. set_env (
818+ "QCS_SETTINGS_FILE_PATH" ,
819+ settings_file_path
820+ . to_str ( )
821+ . expect ( "settings file path should be a string" ) ,
822+ ) ;
823+ jail. set_env (
824+ "QCS_SECRETS_FILE_PATH" ,
825+ secrets_file_path
826+ . to_str ( )
827+ . expect ( "secrets file path should be a string" ) ,
828+ ) ;
829+
830+ config = ClientConfiguration :: load_default ( ) . unwrap ( ) ;
831+ Ok ( ( ) )
832+ } ) ;
833+
834+ assert_eq ! (
835+ config. get_bearer_access_token( ) . await . unwrap( ) ,
836+ access_token. to_string( )
837+ ) ;
838+ }
759839}
0 commit comments