are there plans to add authentication support back...
# kotlinx-rpc
a
are there plans to add authentication support backed into krpc?
👀 3
d
Also keen to know - currently resigned to adding a
token
parameter to each 'authenticated' RPC function, even if this pollutes the API somewhat.
a
Yeah, that does pollute the api so much I have opted not to go with it
d
NGL while I respect the gRPC effort for long-term standardisation, I couldn't actually tell you what difference it's going to make to my life... As an enthusiastic kRPC adopter, more ergonomic Auth support is top on my list - and I think other user's lists too - it's not the first time this has come up.
a
Same here, I like kRPC because it clearly shows how it can improve my work flow. The performance part is not so crucial to me (I was very okay with REST's performance and there were no bottlenecks on my apps)
In regards to authentication, I have pass it in the headers but it is a one time thing, when the token expires the user has to log in again 😔 . That means at least for now, my access tokens live for 24hrs, which is highly insecure. But I am waiting for that auth support for the time being
d
It would be nice, however I'm somewhat at peace with having an
accessToken
parameter; it makes the data-layer contract explicit after all, and auth concerns can be 'stripped off' as we map to/from the Domain layer.
Auth isn't my strong suit though, so perhaps there are as aspects of it I haven't considered, that would be better handled with 1st class support than with parameters.
d
If I add the auth. configs to Ktor server and client, should not it automatically cover kRPC as well @Alexander Sysoev?
a
it doesn't because kRPC currently uses websockets and the client establishes the connection with the server on the first request and they maintain that connection throughout the lifetime of the client
Unless you are always creating a new connection from the client (which does defeat the purpose of using websockets in the first place), you can't use the current ktor's auth implementation which expects to have a token in the header whenever a connection is (re)established
d
I was about to make the same point @andylamax, but then it made me think again more broadly - is that actually a bad thing? The reason we use a pair of
access
and
refresh
tokens with HTTP, much of the time, is to send part of the 'indefinite authentication' less often - harder to intercept. With a persistent websocket, we're sending the auth details even less often, doesn't this theoretically make our authentication even more secure i.e. better? The server then acknowledges the web-socket as authenticated once. Only if it disconnects does it need re-authenticating. I guess I'd need to lean on a lower-level understanding of TCP/IP and WebSockets at this point - but isn't the standard pretty robust to hijacking against a continuously open socket, making 'auth once' preferable? Maybe not! Keen to get more inputs but it strikes me there's a nuanced balance between '_keep reassuring me you're who you say you are_' vs '_don't tell me too often lest others copy how_'.
2
Maybe all we need for a 'good enough' solution, is a way for our kRPC service implementations to inspect any tokens passed in the initial socket creation (since as I understand it, socket/service are decoupled - with many kRPC services able to be multiplexed over the first, lazily created websocket connection).
This does assume all your kRPC services to be authenticated under the same token; but for most use cases that probably stands up.
a
You might be onto something there @darkmoon_uk
d
@andylamax
kRPC currently uses websockets and the client establishes the connection with the server on the first request
So you want to say that the only problem at the moment is that the auth takes place only on first request, when the ktor client gets created for the first time and the first kRPC call is made, and not for every kRPC call separately ? Well, maybe this scenario suits me, with some additional changes maybe, it's interesting how people do it when dealing with plain websockets
a
That is exactly what I am saying, I am trying to see if it works for my situation too
d
In such cases I would do a costume loop (or better event based) check to see if the token/auth is still valid - if not then close all connections (to avoid doing it on every call and preserve traffic)
a
I don't think looping is a good idea. I am currently evaluating token validity on every call on the server side
👍🏻 1
n
If I add the auth. configs to Ktor server and client, should not it automatically cover kRPC as well @Alexander Sysoev?
I am also currently developing an authentication solution for Krpc, and I have just found that the JWT token auth works just fine, at least in the tests. I have some tests that deliberately don't use a bearer token, and they fail with
IllegalStateException
because the route was not found. Also, I am using an unproctored RPC connection for authentication, so my app is entirely RPC. For my case, it is OK if the WebSocket connection outlives the JWT Token.
a
@neworldlt what do you do when the access token expires?
n
I am doing nothing. I expect WebSocket will work even after expiration. If clients want to reconnect after the token expires, then I expect the client will refresh the token upon
unauthorized
response:
Copy code
private val authKtorClient = ktorClient.config {
        install(Auth) {
            bearer {
                loadTokens {
                    BearerTokens(session.jwtToken.value, session.jwtRefreshToken.value)
                }
                refreshTokens { 
                    val refreshToken = this.oldTokens!!.refreshToken
                    authentificationService.refresh(refreshToken)
                }
            }
        }
    }
But I don't have tests that test expiration behavior yet, so I am not sure. It is sufficient for my goal: users should not feel interruptions, and I can implement any future authentication model without redoing the API.
a
I doubt that this will work. When the token expires, krpc won't send back a 401 because by the time of the connection, it was valid. This means, the client won't know that the tokens are expired
n
Yes, sure. But it should refresh during reconnection.
a
Yes it should, but question is, how do you trigger a reconnection?
n
Unfortunatelly, seems WebSockets in web does not support custom headers including bearing token. All other options does not look trivial
Yes it should, but question is, how do you trigger a reconnection?
I don't. And I don't expect someone will be able keep connection forever, but if they do, server still restarts time to time due to updates.
I found some suggestion is SO, however, neither looks trivial to implement via kotlin-rpc. Just checking token is not enough, I also need to pass user details
So, I finally implemented passing the token via a URL parameter, which I am not proud of.
Smuggle access tokens
does not work, because the browser drops the connection if the subprotocol does not match. Another interesting approach would be sending a token as the very first RPC call. It could also update the token periodically. With my DI setup, it would be easy to support session state across services. It looks appealing; however, it opens the possibility for DoS attacks just by keeping the socket open.