I'm using a server that authenticates through keycloak. In keycloak I have created a realm and am able to get an Access token as a response. This access token gets fed now into my Ktor application.
However, I'm not quite sure how to protect routes in an easy manner. I want to have some protected routes that have a authenticate("keycloakOAuth"){}
scope around it which handles validating the access token and refreshing using the refresh token if the access token is expired.
Currently I have keycloak inside Ktor configured as this:
authenticate("keycloakOAuth") {
get("login") {}
route("/callback") {
// This handler will be executed after making a request to a provider's token URL.
handle {
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
if (principal != null) {
val response = principal as OAuthAccessTokenResponse.OAuth2
call.respondText { "Access token: ${response.accessToken}" }
} else {
call.respondText { "NO principal" }
}
}
}
}
This works fine because when I go to login I'm getting sent to the Keycloak login page and I can login. When I logged in the callback executes and I get my Access Token back.
When I'm trying to protect routes however, some odd stuff happens. I know that I need to validate the incoming JWT token. But I have no clue how to given the Ktor capabilities. The examples are also of little help, since they are quite vague.
Currently I have something like this:
authenticate("keycloakOAuth") {
get("/testAuth") {
val principal = call.authentication.principal<OAuthAccessTokenResponse.OAuth2>()
if(principal != null) {
call.respondText("Authenticated!")
} else {
call.respondText("Unauthenticated...")
}
}
}
But my application will always send me to the login page and then callback page, even though I am sending the Bearer token when I'm testing this call.
My question is:
How do I protect routes in a manner that they need a valid token, with the same syntax that Ktor uses (like authenticate(){}). Do I need to configure JWT for this?