Skip to content

Commit fd2d70d

Browse files
authored
Merge pull request #162 from simonredfern/develop
Debug pages say if env vars are set.
2 parents 96d929c + 052f00a commit fd2d70d

File tree

3 files changed

+122
-9
lines changed

3 files changed

+122
-9
lines changed

server/routes/status.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import type { Request, Response } from 'express'
3030
import { Container } from 'typedi'
3131
import OBPClientService from '../services/OBPClientService.js'
3232
import { OAuth2ProviderManager } from '../services/OAuth2ProviderManager.js'
33+
import { OAuth2ProviderFactory } from '../services/OAuth2ProviderFactory.js'
3334
import { commitId } from '../app.js'
3435
import {
3536
RESOURCE_DOCS_API_VERSION,
@@ -42,6 +43,42 @@ const router = Router()
4243
// Get services from container
4344
const obpClientService = Container.get(OBPClientService)
4445
const providerManager = Container.get(OAuth2ProviderManager)
46+
const providerFactory = Container.get(OAuth2ProviderFactory)
47+
48+
/**
49+
* Map provider name to the expected environment variable names
50+
*/
51+
function getProviderEnvVarNames(providerName: string): { clientId: string; clientSecret: string } {
52+
const mapping: Record<string, { clientId: string; clientSecret: string }> = {
53+
'obp-oidc': {
54+
clientId: 'VITE_OBP_OIDC_CLIENT_ID',
55+
clientSecret: 'VITE_OBP_OIDC_CLIENT_SECRET'
56+
},
57+
'keycloak': {
58+
clientId: 'VITE_KEYCLOAK_CLIENT_ID',
59+
clientSecret: 'VITE_KEYCLOAK_CLIENT_SECRET'
60+
},
61+
'google': {
62+
clientId: 'VITE_GOOGLE_CLIENT_ID',
63+
clientSecret: 'VITE_GOOGLE_CLIENT_SECRET'
64+
},
65+
'github': {
66+
clientId: 'VITE_GITHUB_CLIENT_ID',
67+
clientSecret: 'VITE_GITHUB_CLIENT_SECRET'
68+
}
69+
}
70+
71+
if (mapping[providerName]) {
72+
return mapping[providerName]
73+
}
74+
75+
// Generic fallback for custom/unknown providers
76+
const upperName = providerName.toUpperCase().replace(/-/g, '_')
77+
return {
78+
clientId: `VITE_${upperName}_CLIENT_ID`,
79+
clientSecret: `VITE_${upperName}_CLIENT_SECRET`
80+
}
81+
}
4582

4683
const connectors = [
4784
'akka_vDec2018',
@@ -199,14 +236,25 @@ router.get('/status/providers', (req: Request, res: Response) => {
199236
}
200237
}
201238

239+
// Get factory-configured strategies (env vars loaded) vs discovered providers
240+
const configuredStrategies = providerFactory.getConfiguredProviders()
241+
242+
// Build per-provider explorer readiness
243+
const explorerReadiness = allProviderStatus.map((status) => ({
244+
...status,
245+
explorerCredentialsConfigured: providerFactory.hasStrategy(status.name),
246+
explorerEnvVars: getProviderEnvVarNames(status.name)
247+
}))
248+
202249
res.json({
203250
summary: {
204251
totalConfigured: availableProviders.length,
205252
availableProviders: availableProviders,
206253
obpApiHost: process.env.VITE_OBP_API_HOST || 'not configured',
207-
sharedRedirectUrl: sharedRedirectUrl
254+
sharedRedirectUrl: sharedRedirectUrl,
255+
explorerConfiguredStrategies: configuredStrategies
208256
},
209-
providerStatus: allProviderStatus,
257+
providerStatus: explorerReadiness,
210258
environmentConfig: envConfig,
211259
note: 'Credentials are masked for security. Format: first2...last2'
212260
})
@@ -295,6 +343,8 @@ router.get('/status/oidc-debug', async (req: Request, res: Response) => {
295343
providerName: provider.provider,
296344
wellKnownUrl: provider.url,
297345
success: false,
346+
explorerCredentialsConfigured: providerFactory.hasStrategy(provider.provider),
347+
explorerEnvVars: getProviderEnvVarNames(provider.provider),
298348
oidcConfiguration: null as any,
299349
error: null as string | null,
300350
endpoints: {
@@ -398,6 +448,8 @@ router.get('/status/oidc-debug', async (req: Request, res: Response) => {
398448
}
399449

400450
// Compile summary
451+
const explorerConfiguredStrategies = providerFactory.getConfiguredProviders()
452+
401453
const summary = {
402454
timestamp: new Date().toISOString(),
403455
obpApiReachable: step1.success,
@@ -407,7 +459,8 @@ router.get('/status/oidc-debug', async (req: Request, res: Response) => {
407459
currentlyAvailable: availableProviders.length,
408460
configuredInEnvironment: Object.values(envConfig).filter(
409461
(c) => typeof c === 'object' && 'configured' in c && c.configured
410-
).length
462+
).length,
463+
explorerConfiguredStrategies
411464
}
412465

413466
res.json({

src/views/OIDCDebugView.vue

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,14 @@
9797
>
9898
<div class="provider-header">
9999
<h3>{{ provider.providerName }}</h3>
100-
<el-tag :type="provider.success ? 'success' : 'danger'" size="small">
101-
{{ provider.success ? 'Success' : 'Failed' }}
102-
</el-tag>
100+
<div class="provider-tags">
101+
<el-tag :type="provider.success ? 'success' : 'danger'" size="small">
102+
OIDC: {{ provider.success ? 'Reachable' : 'Failed' }}
103+
</el-tag>
104+
<el-tag :type="provider.explorerCredentialsConfigured ? 'success' : 'warning'" size="small">
105+
Explorer: {{ provider.explorerCredentialsConfigured ? 'Configured' : 'No Credentials' }}
106+
</el-tag>
107+
</div>
103108
</div>
104109

105110
<div class="provider-details">
@@ -118,6 +123,11 @@
118123
</div>
119124
</div>
120125

126+
<div v-if="provider.success && !provider.explorerCredentialsConfigured" class="warning-message">
127+
<strong>Warning:</strong> OIDC provider is reachable, but API Explorer has no credentials configured for '{{ provider.providerName }}'.
128+
Login via this provider will not work until <code>{{ provider.explorerEnvVars?.clientId }}</code> and <code>{{ provider.explorerEnvVars?.clientSecret }}</code> are set in your .env file.
129+
</div>
130+
121131
<div v-if="provider.error" class="error-message">
122132
<strong>Error:</strong> {{ provider.error }}
123133
</div>
@@ -181,6 +191,8 @@ interface DebugInfo {
181191
jwks: string | null
182192
}
183193
issuer: string | null
194+
explorerCredentialsConfigured?: boolean
195+
explorerEnvVars?: { clientId: string; clientSecret: string }
184196
}>
185197
}
186198
}
@@ -383,6 +395,11 @@ h1 {
383395
word-break: break-all;
384396
}
385397
398+
.provider-tags {
399+
display: flex;
400+
gap: 8px;
401+
}
402+
386403
.error-message {
387404
padding: 10px;
388405
background: #fef0f0;
@@ -392,6 +409,15 @@ h1 {
392409
font-size: 14px;
393410
}
394411
412+
.warning-message {
413+
padding: 10px;
414+
background: #fdf6ec;
415+
border-left: 4px solid #e6a23c;
416+
border-radius: 4px;
417+
color: #e6a23c;
418+
font-size: 14px;
419+
}
420+
395421
.endpoints-section {
396422
display: flex;
397423
flex-direction: column;

src/views/ProvidersStatusView.vue

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@
7676
<label>OBP API Host:</label>
7777
<span class="value">{{ status.summary.obpApiHost }}</span>
7878
</div>
79+
<div class="summary-item">
80+
<label>API Explorer Configured Strategies:</label>
81+
<span class="value">{{ (status.summary.explorerConfiguredStrategies || []).join(', ') || 'None' }}</span>
82+
</div>
7983
</div>
8084
</el-card>
8185

@@ -91,7 +95,7 @@
9195
v-for="provider in status.providerStatus"
9296
:key="provider.name"
9397
class="provider-card"
94-
:class="{ 'provider-healthy': provider.available, 'provider-unhealthy': !provider.available }"
98+
:class="{ 'provider-healthy': provider.available && provider.explorerCredentialsConfigured, 'provider-unhealthy': !provider.available || !provider.explorerCredentialsConfigured }"
9599
shadow="hover"
96100
>
97101
<template #header>
@@ -108,16 +112,43 @@
108112
<span>{{ provider.name }}</span>
109113
</div>
110114
<div class="provider-detail">
111-
<label>Status:</label>
115+
<label>OIDC Provider Reachable:</label>
112116
<span :class="provider.available ? 'status-ok' : 'status-error'">
113-
{{ provider.available ? 'Available' : 'Unavailable' }}
117+
{{ provider.available ? 'Yes' : 'No' }}
118+
</span>
119+
</div>
120+
<div class="provider-detail">
121+
<label>API Explorer Credentials:</label>
122+
<span :class="provider.explorerCredentialsConfigured ? 'status-ok' : 'status-error'">
123+
{{ provider.explorerCredentialsConfigured ? 'Configured' : 'Missing' }}
114124
</span>
115125
</div>
116126
<div class="provider-detail">
117127
<label>Last Checked:</label>
118128
<span>{{ formatDate(provider.lastChecked) }}</span>
119129
</div>
120130

131+
<!-- Warning if provider is reachable but Explorer has no credentials -->
132+
<div v-if="provider.available && !provider.explorerCredentialsConfigured" class="error-section">
133+
<div class="error-header">
134+
<el-icon class="error-icon"><WarningFilled /></el-icon>
135+
<span class="error-category">Configuration Error</span>
136+
</div>
137+
<div class="error-message">
138+
<strong>Warning:</strong> This OIDC provider is reachable, but API Explorer does not have credentials configured for it. Login will not work.
139+
</div>
140+
<div class="troubleshooting-hints">
141+
<div class="hint-title">
142+
<el-icon><InfoFilled /></el-icon>
143+
<strong>Fix:</strong>
144+
</div>
145+
<ul class="hint-list">
146+
<li>Set <code>{{ provider.explorerEnvVars?.clientId }}</code> and <code>{{ provider.explorerEnvVars?.clientSecret }}</code> in your .env file</li>
147+
<li>Restart the API Explorer server after updating .env</li>
148+
</ul>
149+
</div>
150+
</div>
151+
121152
<!-- Enhanced Error Display -->
122153
<div v-if="provider.error" class="error-section">
123154
<div class="error-header">
@@ -206,6 +237,8 @@ interface ProviderStatus {
206237
status: string
207238
lastChecked: Date
208239
error?: string
240+
explorerCredentialsConfigured?: boolean
241+
explorerEnvVars?: { clientId: string; clientSecret: string }
209242
}
210243
211244
interface EnvConfig {
@@ -219,6 +252,7 @@ interface StatusResponse {
219252
totalConfigured: number
220253
availableProviders: string[]
221254
obpApiHost: string
255+
explorerConfiguredStrategies?: string[]
222256
}
223257
providerStatus: ProviderStatus[]
224258
environmentConfig: EnvConfig

0 commit comments

Comments
 (0)