Open EricDeng1001 opened 3 weeks ago
Hi! If you are using kRPC protocol with Ktor integration - they have a JWT plugin for this: https://ktor.io/docs/server-jwt.html#authenticate-route
Otherwise - no builtin solution is available
Hello! I am already using this, but encounter a problem: when user not logged in, trying to connect ws returns 401, and service creation is failed. But I must have init these service when my app start. Another problem is, it seems that rpc request is not carrtying bearer token like normal http call. I will post my config code below.
client:
object RPC {
private val client = HttpClient {
installRPC()
install(Auth) {
bearer {
loadTokens {
BearerTokens(UserContext.token, "")
}
refreshTokens {
BearerTokens(UserContext.token, "")
}
}
}
}
private lateinit var rpcClient: RPCClient
lateinit var authService: AuthService
lateinit var subscriptionManager: SubscriptionManager
lateinit var channelManager: ChannelManager
lateinit var purchaseService: PurchaseService
lateinit var accountManager: AccountManager
lateinit var pushManager: PushManager
suspend fun init() {
rpcClient = client.rpc {
url("ws://localhost:3000/api")
rpcConfig {
serialization {
json()
}
}
}
authService = client.rpc {
url("ws://localhost:3000/api/auth")
rpcConfig {
serialization {
json()
}
}
}.withService()
subscriptionManager = rpcClient.withService()
channelManager = rpcClient.withService()
purchaseService = rpcClient.withService()
accountManager = rpcClient.withService()
pushManager = rpcClient.withService()
}
}
And init is called when App start using LauchedEffect. server:
fun Application.module() {
install(CORS) {
allowOrigins { true }
}
install(RPC) {
}
install(Authentication) {
jwt {
verifier(
AuthContext.verifier
)
validate { credential ->
AuthContext.validate(credential)
}
challenge { defaultScheme, realm ->
call.respond(HttpStatusCode.Unauthorized, "Token is not valid or has expired")
}
realm = "Access to maotao"
}
}
install(DoubleReceive)
install(CallLogging) {
level = Level.INFO
format { call ->
runBlocking {
val status = call.response.status()
val httpMethod = call.request.httpMethod.value
val userAgent = call.request.headers["User-Agent"]
val body = call.receiveText()
val uri = call.request.uri
"$httpMethod $uri $status \n$userAgent \n$body"
}
}
}
routing {
pwaDispatch()
auth()
authenticate {
api()
}
}
}
And when app is started, server logged:
2024-08-21 21:12:50.065 [eventLoopGroupProxy-4-1] INFO Application - GET /api 401 Unauthorized
Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1 Edg/127.0.0.0
I was using REST before, and auth is 100% ok. I just switch from normal ktor to rpc.
@EricDeng1001 your auth service is under url("ws://localhost:3000/api/auth")
protected route:
authenticate {
api()
}
Hence the error. You can try to move auth service into another route, which is not protocted. At least that is what I understood from the Ktor docs
@EricDeng1001 were you able to resolve the issue?
I will try to add headers and see. Will report asap.
Need newest patch to test it in production env. Waiting for it.
I have a set of Service that must be used after login. I issue jwt to client so they can identify themselves. And I also got a AuthService which issue this token. So how do I setup my rpc server and client for this scenario? For example, how do I carry this jwt in client, and how do I verify this jwt in server? Besides, do I need to setup two paths, one for AuthService, because it does not require jwt, and another for rest of services, which requires jwt?