UPDATE: Read official announcement for role based auth in Ktor 2023 roadmap
Simplifying support for authorization and authentication. Providing end-to-end support for database authentication and session management, as well as role-based authorization
ktor-role-based-auth is an easy to use and intuitive role-based access control library for Ktor Server
It works with the official ktor-server-auth library and adds role based authorization on top of it
Supported methods
- HTTP authentication (Basic/Digest/Bearer)
- Form-based authentication
- JWT
- Session
- OAuth
- LDAP
- Custom authentication
Step 1. Add the JitPack repository in build.gradle.kts
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
Step 2. Add the dependency
dependencies {
implementation("com.github.omkar-tenkale:ktor-role-based-auth:0.2.0")
}
Initialize the plugin when configuring authentication
fun Application.configureSecurity(){
authentication {
jwt {
// Configure jwt authentication
}
roleBased {
extractRoles { principal ->
//Extract roles from JWT payload
(principal as JWTPrincipal).payload.claims?.get("roles")?.asList(String::class.java)?.toSet() ?: emptySet()
}
}
}
}
fun Application.routing() {
route("/") {
//No authentication required to access this route
get {
call.respondText("Welcome!")
}
authenticate {
//JWT authenticated route
route("/profile") {
get {
call.respondText("Joined: 2 years ago")
}
}
//JWT authenticated + role authorized route
route("/dashboard") {
withAnyRole("ADMIN", "SUPER_ADMIN") {
get {
call.respondText("Total users: 2443")
}
}
}
//JWT authenticated + role authorized route
route("/system-stats") {
withRole("SUPER_ADMIN") {
get {
call.respondText("CPU: 34%")
}
}
}
}
}
}
The plugin responds with 403 (Forbidden)
by default if roles don't match
Optionally, follow these steps to send a custom response
- Set
throwErrorOnUnauthorizedResponse
totrue
fun Application.configureSecurity(){
authentication {
jwt {
// Configure jwt authentication
}
roleBased {
extractRoles { principal ->
//Extract roles from JWT payload
(principal as JWTPrincipal).payload.claims?.get("roles")?.asList(String::class.java)?.toSet() ?: emptySet()
}
throwErrorOnUnauthorizedResponse = true
}
}
}
- Catch the
UnauthorizedAccessException
exception globally with help of StatusPages plugin
fun Application.configureSecurity() {
install(StatusPages) {
exception<Throwable> { call, cause ->
if (cause is UnauthorizedAccessException) {
call.respondText(text = "You don't have enough permissions to access this route", status = HttpStatusCode.Forbidden)
}
}
}
}
For complete example, Check out tests
- Joris Portegies Zwart - Original implementation with pipelines and phases for older ktor versions