Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit23cab56

Browse files
authored
impl: support for certificate based authentication (#155)
We now skip token input screen if the user provided a public and aprivate key for mTLS authentication on both the usual welcome screen andin the URI handling.Attention: the official coder deployment supports only authenticationvia token, which is why I could not fully test an end to end scenario.
1 parent3a21b45 commit23cab56

File tree

9 files changed

+57
-18
lines changed

9 files changed

+57
-18
lines changed

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
##Unreleased
44

5+
###Added
6+
7+
- support for certificate based authentication
8+
59
##0.5.0 - 2025-07-17
610

711
###Added

‎gradle.properties‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
version=0.5.0
1+
version=0.5.1
22
group=com.coder.toolbox
33
name=coder-toolbox

‎src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ class CoderRemoteProvider(
245245
environments.value=LoadableState.Value(emptyList())
246246
isInitialized.update {false }
247247
client=null
248-
CoderCliSetupWizardState.resetSteps()
248+
CoderCliSetupWizardState.goToFirstStep()
249249
}
250250

251251
overrideval svgIcon:SvgIcon=

‎src/main/kotlin/com/coder/toolbox/sdk/CoderRestClient.kt‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ open class CoderRestClient(
9494
.build()
9595
}
9696

97-
if (token!=null) {
97+
if (context.settingsStore.requireTokenAuth) {
98+
if (token.isNullOrBlank()) {
99+
throwIllegalStateException("Token is required for$url deployment")
100+
}
98101
builder= builder.addInterceptor {
99102
it.proceed(
100103
it.request().newBuilder().addHeader("Coder-Session-Token", token).build()

‎src/main/kotlin/com/coder/toolbox/util/CoderProtocolHandler.kt‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ open class CoderProtocolHandler(
6464

6565
context.logger.info("Handling$uri...")
6666
val deploymentURL= resolveDeploymentUrl(params)?:return
67-
val token= resolveToken(params)?:return
67+
val token=if (!context.settingsStore.requireTokenAuth)nullelseresolveToken(params)?:return
6868
val workspaceName= resolveWorkspaceName(params)?:return
6969
val restClient= buildRestClient(deploymentURL, token)?:return
7070
val workspace= restClient.workspaces().matchName(workspaceName, deploymentURL)?:return
@@ -128,7 +128,7 @@ open class CoderProtocolHandler(
128128
return workspace
129129
}
130130

131-
privatesuspendfunbuildRestClient(deploymentURL:String,token:String):CoderRestClient? {
131+
privatesuspendfunbuildRestClient(deploymentURL:String,token:String?):CoderRestClient? {
132132
try {
133133
return authenticate(deploymentURL, token)
134134
}catch (ex:Exception) {
@@ -140,11 +140,11 @@ open class CoderProtocolHandler(
140140
/**
141141
* Returns an authenticated Coder CLI.
142142
*/
143-
privatesuspendfunauthenticate(deploymentURL:String,token:String):CoderRestClient {
143+
privatesuspendfunauthenticate(deploymentURL:String,token:String?):CoderRestClient {
144144
val client=CoderRestClient(
145145
context,
146146
deploymentURL.toURL(),
147-
if (settings.requireTokenAuth)tokenelsenull,
147+
token,
148148
PluginManager.pluginInfo.version
149149
)
150150
client.initializeSession()

‎src/main/kotlin/com/coder/toolbox/views/ConnectStep.kt‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class ConnectStep(
4747
context.i18n.pnotr("")
4848
}
4949

50-
if (CoderCliSetupContext.isNotReadyForAuth()) {
50+
if (context.settingsStore.requireTokenAuth&&CoderCliSetupContext.isNotReadyForAuth()) {
5151
errorField.textState.update {
5252
context.i18n.pnotr("URL and token were not properly configured. Please go back and provide a proper URL and token!")
5353
}
@@ -67,7 +67,7 @@ class ConnectStep(
6767
return
6868
}
6969

70-
if (!CoderCliSetupContext.hasToken()) {
70+
if (context.settingsStore.requireTokenAuth&&!CoderCliSetupContext.hasToken()) {
7171
errorField.textState.update { context.i18n.ptrl("Token is required") }
7272
return
7373
}
@@ -77,7 +77,7 @@ class ConnectStep(
7777
val client=CoderRestClient(
7878
context,
7979
CoderCliSetupContext.url!!,
80-
CoderCliSetupContext.token!!,
80+
if (context.settingsStore.requireTokenAuth)CoderCliSetupContext.tokenelsenull,
8181
PluginManager.pluginInfo.version,
8282
)
8383
// allows interleaving with the back/cancel action
@@ -91,17 +91,17 @@ class ConnectStep(
9191
statusField.textState.update { (context.i18n.pnotr(progress)) }
9292
}
9393
// We only need to log in if we are using token-based auth.
94-
if (client.token!=null) {
94+
if (context.settingsStore.requireTokenAuth) {
9595
statusField.textState.update { (context.i18n.ptrl("Configuring Coder CLI...")) }
9696
// allows interleaving with the back/cancel action
9797
yield()
98-
cli.login(client.token)
98+
cli.login(client.token!!)
9999
}
100100
statusField.textState.update { (context.i18n.ptrl("Successfully configured${CoderCliSetupContext.url!!.host}...")) }
101101
// allows interleaving with the back/cancel action
102102
yield()
103103
CoderCliSetupContext.reset()
104-
CoderCliSetupWizardState.resetSteps()
104+
CoderCliSetupWizardState.goToFirstStep()
105105
onConnect(client, cli)
106106
}catch (ex:CancellationException) {
107107
if (ex.message!=USER_HIT_THE_BACK_BUTTON) {
@@ -127,10 +127,14 @@ class ConnectStep(
127127
}finally {
128128
if (shouldAutoLogin.value) {
129129
CoderCliSetupContext.reset()
130-
CoderCliSetupWizardState.resetSteps()
130+
CoderCliSetupWizardState.goToFirstStep()
131131
context.secrets.rememberMe=false
132132
}else {
133-
CoderCliSetupWizardState.goToPreviousStep()
133+
if (context.settingsStore.requireTokenAuth) {
134+
CoderCliSetupWizardState.goToPreviousStep()
135+
}else {
136+
CoderCliSetupWizardState.goToFirstStep()
137+
}
134138
}
135139
}
136140
}

‎src/main/kotlin/com/coder/toolbox/views/DeploymentUrlStep.kt‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,11 @@ class DeploymentUrlStep(
8585
notify("URL is invalid", e)
8686
returnfalse
8787
}
88-
CoderCliSetupWizardState.goToNextStep()
88+
if (context.settingsStore.requireTokenAuth) {
89+
CoderCliSetupWizardState.goToNextStep()
90+
}else {
91+
CoderCliSetupWizardState.goToLastStep()
92+
}
8993
returntrue
9094
}
9195

‎src/main/kotlin/com/coder/toolbox/views/state/CoderCliSetupWizardState.kt‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ object CoderCliSetupWizardState {
2525
currentStep=WizardStep.entries.toTypedArray()[(currentStep.ordinal-1)%WizardStep.entries.size]
2626
}
2727

28-
funresetSteps() {
28+
fungoToLastStep() {
29+
currentStep=WizardStep.CONNECT
30+
}
31+
32+
fungoToFirstStep() {
2933
currentStep=WizardStep.URL_REQUEST
3034
}
3135
}

‎src/test/kotlin/com/coder/toolbox/sdk/CoderRestClientTest.kt‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ class CoderRestClientTest {
225225
val client=CoderRestClient(context,URL(url),"token")
226226
assertEquals(user.username, runBlocking { client.me() }.username)
227227

228-
val tests=listOf("invalid",null)
228+
val tests=listOf("invalid")
229229
tests.forEach { token->
230230
val ex=
231231
assertFailsWith(
@@ -238,6 +238,26 @@ class CoderRestClientTest {
238238
srv.stop(0)
239239
}
240240

241+
@Test
242+
fun`exception is raised when token is required for authentication and token value is null or empty`() {
243+
listOf("",null).forEach { token->
244+
val ex=
245+
assertFailsWith(
246+
exceptionClass=IllegalStateException::class,
247+
block= {
248+
runBlocking {
249+
CoderRestClient(
250+
context,
251+
URI.create("https://coder.com").toURL(),
252+
token
253+
).me()
254+
}
255+
},
256+
)
257+
assertEquals(ex.message,"Token is required for https://coder.com deployment")
258+
}
259+
}
260+
241261
@Test
242262
funtestGetsWorkspaces() {
243263
val tests=

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp