@@ -32,6 +32,7 @@ import com.tesobe.oidc.config.{Config, OidcConfig, VerifyCredentialsMethod, Veri
3232import com .tesobe .oidc .endpoints ._
3333import com .tesobe .oidc .tokens .JwtService
3434import com .tesobe .oidc .stats .StatsService
35+ import com .tesobe .oidc .status .StatusService
3536import com .tesobe .oidc .ratelimit .{RateLimitConfig , InMemoryRateLimitService }
3637import com .tesobe .oidc .revocation .InMemoryTokenRevocationService
3738import org .http4s ._
@@ -169,7 +170,13 @@ object OidcServer extends IOApp {
169170 case _ => List .empty
170171 }) ++
171172 (config.verifyClientMethod match {
172- case VerifyClientMethod .ViaApiEndpoint => List (" CanGetOidcClient" , " CanGetConsumers" )
173+ case VerifyClientMethod .ViaApiEndpoint =>
174+ val base = List (" CanGetOidcClient" , " CanVerifyOidcClient" , " CanGetConsumers" )
175+ val createConsumer =
176+ if (config.enableDynamicClientRegistration || ! config.skipClientBootstrap)
177+ List (" CanCreateConsumer" )
178+ else Nil
179+ base ++ createConsumer
173180 case _ => List .empty
174181 })
175182
@@ -254,6 +261,10 @@ object OidcServer extends IOApp {
254261 codeService <- CodeService (config)
255262 jwtService <- JwtService (config)
256263 statsService <- StatsService ()
264+ statusService <- StatusService
265+ .create(config, jwtService)
266+ .allocated
267+ .map(_._1)
257268 rateLimitConfig = RateLimitConfig .fromEnv
258269 rateLimitService <- InMemoryRateLimitService (rateLimitConfig)
259270 revocationService <- InMemoryTokenRevocationService (
@@ -297,6 +308,7 @@ object OidcServer extends IOApp {
297308 )
298309 clientsEndpoint = ClientsEndpoint (authService)
299310 statsEndpoint = StatsEndpoint (statsService, config)
311+ statusEndpoint = StatusEndpoint (statusService)
300312 staticFilesEndpoint = StaticFilesEndpoint ()
301313 registrationEndpoint = if (config.enableDynamicClientRegistration) {
302314 Some (RegistrationEndpoint (
@@ -388,6 +400,19 @@ object OidcServer extends IOApp {
388400 )
389401 )
390402
403+ // Public status page - always available
404+ case req @ GET -> Root / " status" =>
405+ statusEndpoint.routes.run(req).value.flatMap {
406+ case Some (resp) => IO .pure(resp)
407+ case None => NotFound (" Status endpoint not found" )
408+ }
409+
410+ case req @ GET -> Root / " status.json" =>
411+ statusEndpoint.routes.run(req).value.flatMap {
412+ case Some (resp) => IO .pure(resp)
413+ case None => NotFound (" Status endpoint not found" )
414+ }
415+
391416 // Root page - simple landing with links - always available
392417 case GET -> Root =>
393418 val modeStatus =
@@ -458,6 +483,7 @@ object OidcServer extends IOApp {
458483 | <div class="links">
459484 | <a href="/info">Server Info</a>
460485 | <a href="/health">Health Check</a>
486+ | <a href="/status">Status</a>
461487 | </div>
462488 | <div class="version">
463489 | <strong>Version:</strong> v ${readVersion()} ( ${readGitCommit()})
@@ -728,6 +754,7 @@ object OidcServer extends IOApp {
728754 |<li><a href="/clients">OIDC Clients</a> - View registered clients</li>
729755 |<li><a href="/stats">Statistics</a> - Real-time usage statistics</li>
730756 |<li><a href="/health">Health Check</a> - Service status</li>
757+ |<li><a href="/status">Status</a> - Dependency health checks (OBP API, endpoints, databases)</li>
731758 |</ul>
732759 |<h2>Supported Grant Types</h2>
733760 |<ul>
@@ -956,6 +983,8 @@ object OidcServer extends IOApp {
956983 IO (println(s " JWKS: $baseUriString/obp-oidc/jwks " )) *>
957984 IO (println(s " Clients: $baseUriString/obp-oidc/clients " )) *>
958985 IO (println(s " Health Check: $baseUriString/health " )) *>
986+ IO (println(s " Status (HTML): $baseUriString/status " )) *>
987+ IO (println(s " Status (JSON): $baseUriString/status.json " )) *>
959988 config.obpApiUrl
960989 .fold(IO .unit)(url => IO (println(s " OBP-API: $url" ))) *>
961990 printOBPConfiguration(baseUriString, authService, config) *>
@@ -969,12 +998,18 @@ object OidcServer extends IOApp {
969998 IO (println(s " USE_VERIFY_ENDPOINTS: ${config.useVerifyEndpoints}" )) *>
970999 (if (config.useVerifyEndpoints) {
9711000 val username = config.obpApiUsername.getOrElse(" unknown" )
972- val roleEndpoints = List (
1001+ val baseRoleEndpoints = List (
9731002 (" CanVerifyUserCredentials" , " POST /obp/v6.0.0/users/verify-credentials" ),
9741003 (" CanGetAnyUser" , " GET /obp/v6.0.0/users/provider/PROVIDER/username/USERNAME" ),
9751004 (" CanGetOidcClient" , " GET /obp/v6.0.0/oidc/clients/CLIENT_ID" ),
1005+ (" CanVerifyOidcClient" , " POST /obp/v6.0.0/oidc/clients/verify" ),
9761006 (" CanGetConsumers" , " GET /obp/v6.0.0/management/consumers" )
9771007 )
1008+ val roleEndpoints =
1009+ if (config.enableDynamicClientRegistration || ! config.skipClientBootstrap)
1010+ baseRoleEndpoints :+
1011+ (" CanCreateConsumer" , " POST /obp/v5.1.0/management/consumers" )
1012+ else baseRoleEndpoints
9781013 IO (println(" All verification methods use OBP API endpoints" )) *>
9791014 IO (println(s " OBP API Username: $username" )) *>
9801015 IO (println(s " Required roles for OBP_API_USERNAME ' $username': " )) *>
0 commit comments