https://kotlinlang.org logo
#ktor
Title
# ktor
g

Grouvie

03/27/2022, 1:46 PM
Hi, I run my backend and frontend with ktor. The backend provides authorization routes and also serves my compose web page(s). Now I can not wrap my head around how to protect a page get request instead of a function.
Copy code
routing {
    route(LoginItem.path) {
        post {
            val request = call.receiveOrNull<LoginItem>() ?: kotlin.run {
                call.respond(HttpStatusCode.BadRequest)
                return@post
            }
            ...
        }
    }
    get("/login") {
        call.respondText(
            this::class.java.classLoader.getResource("index.html")!!.readText(),
            ContentType.Text.Html
        )
    }
}
For the frontend in my jsMain I have a HttpClient with the jwt module installed and functions to post/ get data. When I send a request with this functions I can see the jwt token and it works. Now I want to protect a route from unauthorized users. So I did this in my ktor backend.
Copy code
authenticate("auth-jwt") {
    get("/dashboard") {
        call.respondText(
            this::class.java.classLoader.getResource("index.html")!!.readText(),
            ContentType.Text.Html
        )
    }
}
This works fine and the /dashboard route is now protected. When I enter my jwt into postman I get the correct answer. But I want to access the /dashboard route in my browser. Do you have any idea what I am doing wrong in my structure or setup? Thanks for your help 🙂
a

Aleksei Tirman [JB]

03/27/2022, 2:13 PM
You can try to find some web browser extension that allows you to modify request headers.
g

Grouvie

03/27/2022, 3:31 PM
I want to achieve something different. My idea was to get the token from localStorage/cookie... in my jsMain and then provide it to my backend with every request. I just have to figure out how I can make all requests come from the jsMain without going to the backend jvmMain directly.
a

Aleksei Tirman [JB]

03/27/2022, 3:33 PM
how I can make all requests come from the jsMain without going to the backend jvmMain directly.
What do you mean?
g

Grouvie

03/27/2022, 3:55 PM
I use jwt stored in my browser for requests from my site to my api. And now I want to somehow get the jwt on a site and use it to decide whether a user is allowed to access a page.
But instead of using my jsonClient I want the page to somehow get it directly from the browser to authenticate me.
Copy code
suspend fun login(userData: LoginItem): BasicAuthResponse<AuthResponse> {
    val result = <http://jsonClient.post|jsonClient.post><BasicAuthResponse<AuthResponse>>(endpoint + LoginItem.path) {
        contentType(ContentType.Application.Json)
        body = userData
    }
    return result
}
I do not really know how else to explain my problem.
a

Aleksei Tirman [JB]

03/27/2022, 4:23 PM
So do you want to fetch an HTML from the restricted endpoint (
/dashboard
) and render it in a browser?
g

Grouvie

03/27/2022, 4:23 PM
Exactly.
a

Aleksei Tirman [JB]

03/27/2022, 4:26 PM
You can make a request to a restricted endpoint, as you do when requesting JSON, receive a body as String and using DOM API attach it to some HTML element.
Or to make it more consistent, you can render HTML on the client side using JSON data from your API, In other words responding for
/dashboard
with a JSON.
g

Grouvie

03/27/2022, 7:21 PM
Thanks a lot for the help. I think my approach might be a bit flawed there. Just to be sure I understood you correct. That would mean, that I create a route for example
/dashboard
. When I access it
/dashboard
sends a request to for example
/save/dashboard
and on successful authentication
/save/dashboard
answers with the content to display on
/dashboard
?
a

Aleksei Tirman [JB]

03/27/2022, 7:29 PM
Not really. Please clarify do you develop a single page application?
g

Grouvie

03/27/2022, 7:29 PM
Not a single page application. That is also one of the problems I had. It feels like I am doing things different than I should be.
a

Aleksei Tirman [JB]

03/27/2022, 7:43 PM
Then could you please describe what higher-level problem are you trying to solve?
g

Grouvie

03/27/2022, 7:48 PM
I am trying to serve a website made with compose web, protect some of its routes and combine it with a secured ktor backend.
a

Aleksei Tirman [JB]

03/27/2022, 8:23 PM
You can make a secured route for the login, e.g.
/login
, where you store a JWT token in a session if authentication is successful. In this case the
/dashboard
endpoint will be public but you will check there for a valid session before responding with a HTML.
g

Grouvie

03/27/2022, 8:28 PM
That looks good. Thanks a lot.
4 Views