package com.restapi.config import com.fasterxml.jackson.module.kotlin.readValue import com.restapi.config.AppConfig.Companion.appConfig import com.restapi.domain.Session import com.restapi.domain.Session.objectMapper import io.javalin.http.Context import io.javalin.http.HandlerType import io.javalin.http.UnauthorizedResponse import org.jose4j.jwk.HttpsJwks import org.jose4j.jwt.consumer.ErrorCodes import org.jose4j.jwt.consumer.InvalidJwtException import org.jose4j.jwt.consumer.JwtConsumerBuilder import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver import org.slf4j.LoggerFactory import java.net.URI import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse import java.util.concurrent.ConcurrentHashMap import java.util.function.Function object Auth { private val authCache = ConcurrentHashMap() fun getAuthEndpoint(): AuthEndpoint { return authCache.computeIfAbsent("AUTH") { val wellKnown = "${appConfig.iamUrl()}/realms/${appConfig.iamRealm()}/.well-known/openid-configuration" val client = HttpClient.newHttpClient() val req = HttpRequest.newBuilder() .uri(URI.create(wellKnown)) .GET().build() objectMapper.readValue( client.send(req, HttpResponse.BodyHandlers.ofString()).body() ) } } private val jwtConsumer = JwtConsumerBuilder() .setRequireExpirationTime() .setAllowedClockSkewInSeconds(30) .setRequireSubject() .setExpectedIssuer(getAuthEndpoint().issuer) .setExpectedAudience("account") .setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri))) .build() fun parseAuthToken(authToken: String): AuthUser { // Validate the JWT and process it to the Claims val jwtClaims = jwtConsumer.process(authToken) val userId = jwtClaims.jwtClaims.claimsMap["preferred_username"] as String val tenant = jwtClaims.jwtClaims.claimsMap["tenant"] as String val roles = ((jwtClaims.jwtClaims.claimsMap["realm_access"] as Map)["roles"]) as List return AuthUser( userName = userId, tenant = tenant, roles = roles ) } } data class AuthUser(val userName: String, val tenant: String, val roles: List)