@@ -21,7 +21,7 @@ public class RawCredentials
2121[ JsonSerializable ( typeof ( RawCredentials ) ) ]
2222public partial class RawCredentialsJsonContext : JsonSerializerContext ;
2323
24- publicinterface ICredentialManager
24+ publicinterface ICredentialManager: ICoderApiClientCredentialProvider
2525{
2626public event EventHandler < CredentialModel > CredentialsChanged ;
2727
@@ -59,7 +59,8 @@ public interface ICredentialBackend
5959/// </summary>
6060public class CredentialManager : ICredentialManager
6161{
62- private const string CredentialsTargetName = "Coder.Desktop.App.Credentials" ;
62+ private readonly ICredentialBackend Backend ;
63+ private readonly ICoderApiClientFactory CoderApiClientFactory ;
6364
6465// _opLock is held for the full duration of SetCredentials, and partially
6566// during LoadCredentials. _opLock protects _inFlightLoad, _loadCts, and
@@ -79,14 +80,6 @@ public class CredentialManager : ICredentialManager
7980// immediate).
8081private volatile CredentialModel ? _latestCredentials ;
8182
82- private ICredentialBackend Backend { get ; } = new WindowsCredentialBackend ( CredentialsTargetName ) ;
83-
84- private ICoderApiClientFactory CoderApiClientFactory { get ; } = new CoderApiClientFactory ( ) ;
85-
86- public CredentialManager ( )
87- {
88- }
89-
9083public CredentialManager ( ICredentialBackend backend , ICoderApiClientFactory coderApiClientFactory )
9184{
9285Backend = backend ;
@@ -108,6 +101,20 @@ public CredentialModel GetCachedCredentials()
108101} ;
109102}
110103
104+ // Implements ICoderApiClientCredentialProvider
105+ public CoderApiClientCredential ? GetCoderApiClientCredential ( )
106+ {
107+ var latestCreds = _latestCredentials ;
108+ if ( latestCreds is not{ State : CredentialState . Valid } || latestCreds . CoderUrl is null )
109+ return null ;
110+
111+ return new CoderApiClientCredential
112+ {
113+ CoderUrl = latestCreds . CoderUrl ,
114+ ApiToken = latestCreds . ApiToken ?? "" ,
115+ } ;
116+ }
117+
111118public async Task < string ? > GetSignInUri ( )
112119{
113120try
@@ -253,6 +260,12 @@ private async Task<CredentialModel> PopulateModel(RawCredentials? credentials, C
253260State = CredentialState . Invalid ,
254261} ;
255262
263+ if ( ! Uri . TryCreate ( credentials . CoderUrl , UriKind . Absolute , out var uri ) )
264+ return new CredentialModel
265+ {
266+ State = CredentialState . Invalid ,
267+ } ;
268+
256269BuildInfo buildInfo ;
257270User me ;
258271try
@@ -279,7 +292,7 @@ private async Task<CredentialModel> PopulateModel(RawCredentials? credentials, C
279292return new CredentialModel
280293{
281294State = CredentialState . Valid ,
282- CoderUrl = credentials . CoderUrl ,
295+ CoderUrl = uri ,
283296ApiToken = credentials . ApiToken ,
284297Username = me . Username ,
285298} ;
@@ -298,6 +311,8 @@ private void UpdateState(CredentialModel newModel)
298311
299312public class WindowsCredentialBackend : ICredentialBackend
300313{
314+ public const string CoderCredentialsTargetName = "Coder.Desktop.App.Credentials" ;
315+
301316private readonly string _credentialsTargetName ;
302317
303318public WindowsCredentialBackend ( string credentialsTargetName )