[{"data":1,"prerenderedAt":1216},["ShallowReactive",2],{"Categories":3,"NavIndexCategoriesCountFooter":203,"content-\u002F2023\u002F04\u002F18\u002Fktor-2-route-withrole-for-jwt\u002F":204},[4,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,70,71,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202],{"category":5},"System Administration",{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},"Software Development",{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":27},{"category":27},{"category":67},"Drones & RC",{"category":69},"DIY Projects",{"category":67},{"category":72},"Photography",{"category":69},{"category":69},{"category":69},{"category":67},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":67},{"category":69},{"category":69},{"category":67},{"category":67},{"category":72},{"category":72},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":5},{"category":5},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":5},{"category":67},{"category":67},{"category":72},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":72},{"category":67},{"category":138},"3D Printing - Laser Cutting - CNC",{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":5},{"category":138},{"category":27},{"category":27},{"category":138},{"category":138},{"category":72},{"category":158},"Photography,3D Printing - Laser Cutting - CNC",{"category":27},{"category":27},{"category":69},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":67},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":27},{"category":69},{"category":27},{"category":27},{"category":27},{"category":27},{"category":181},"Home Assistant",{"category":181},{"category":72},{"category":27},{"category":27},{"category":72},{"category":138},{"category":5},{"category":72},{"category":72},{"category":138},{"category":27},{"category":181},{"category":181},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},191,{"id":205,"title":206,"body":207,"category":27,"date":1202,"description":213,"embedImage":1203,"extension":1204,"image":1203,"intro":1205,"meta":1206,"navigation":333,"path":1207,"seo":1208,"series":1203,"sitemap":1209,"stem":1210,"tags":1211,"__hash__":1215},"content\u002F2023\u002F04\u002F18\u002Fktor-2-route-withrole-for-jwt.md","Ktor 2 route withRole for JWT",{"type":208,"value":209,"toc":1200},"minimark",[210,214,217,227,230,272,275,278,391,394,397,513,516,519,552,555,887,890,893,1193,1196],[211,212,213],"p",{},"In ktor 2 - authenticating with JWT is fairly simple.",[211,215,216],{},"In my case - the user will get a token with two claims that are of interest.",[218,219,220,224],"ul",{},[221,222,223],"li",{},"username - unsurprisingly the logged in user's username",[221,225,226],{},"roles - an array of role names",[211,228,229],{},"For this application the roles are very simply defined:",[231,232,237],"pre",{"className":233,"code":234,"language":235,"meta":236,"style":236},"language-kotlin shiki shiki-themes github-dark","enum class Role {\n    USER, ADMIN\n}\n","kotlin","",[238,239,240,260,266],"code",{"__ignoreMap":236},[241,242,245,249,252,256],"span",{"class":243,"line":244},"line",1,[241,246,248],{"class":247},"snl16","enum",[241,250,251],{"class":247}," class",[241,253,255],{"class":254},"svObZ"," Role",[241,257,259],{"class":258},"s95oV"," {\n",[241,261,263],{"class":243,"line":262},2,[241,264,265],{"class":258},"    USER, ADMIN\n",[241,267,269],{"class":243,"line":268},3,[241,270,271],{"class":258},"}\n",[211,273,274],{},"For the token it is a simple string representation.",[211,276,277],{},"However - while it is easy to mark routing blocks as requiring authentication:",[231,279,281],{"className":233,"code":280,"language":235,"meta":236,"style":236},"authenticate {\n    get(\"\u002Ffoo\") {\n        call.respond(HttpStatusCode.OK, service.getFoo()\n    }\n\n    route(\"\u002Fadmin\") {\n        get(\"\u002Fbar\") {\n            call.respond(HttpStatusCode.OK, service.getFoo()\n        }\n    }\n}\n",[238,282,283,290,305,322,328,335,348,361,375,381,386],{"__ignoreMap":236},[241,284,285,288],{"class":243,"line":244},[241,286,287],{"class":254},"authenticate",[241,289,259],{"class":258},[241,291,292,295,298,302],{"class":243,"line":262},[241,293,294],{"class":247},"    get",[241,296,297],{"class":258},"(",[241,299,301],{"class":300},"sU2Wk","\"\u002Ffoo\"",[241,303,304],{"class":258},") {\n",[241,306,307,310,313,316,319],{"class":243,"line":268},[241,308,309],{"class":258},"        call.",[241,311,312],{"class":254},"respond",[241,314,315],{"class":258},"(HttpStatusCode.OK, service.",[241,317,318],{"class":254},"getFoo",[241,320,321],{"class":258},"()\n",[241,323,325],{"class":243,"line":324},4,[241,326,327],{"class":258},"    }\n",[241,329,331],{"class":243,"line":330},5,[241,332,334],{"emptyLinePlaceholder":333},true,"\n",[241,336,338,341,343,346],{"class":243,"line":337},6,[241,339,340],{"class":254},"    route",[241,342,297],{"class":258},[241,344,345],{"class":300},"\"\u002Fadmin\"",[241,347,304],{"class":258},[241,349,351,354,356,359],{"class":243,"line":350},7,[241,352,353],{"class":247},"        get",[241,355,297],{"class":258},[241,357,358],{"class":300},"\"\u002Fbar\"",[241,360,304],{"class":258},[241,362,364,367,369,371,373],{"class":243,"line":363},8,[241,365,366],{"class":258},"            call.",[241,368,312],{"class":254},[241,370,315],{"class":258},[241,372,318],{"class":254},[241,374,321],{"class":258},[241,376,378],{"class":243,"line":377},9,[241,379,380],{"class":258},"        }\n",[241,382,384],{"class":243,"line":383},10,[241,385,327],{"class":258},[241,387,389],{"class":243,"line":388},11,[241,390,271],{"class":258},[211,392,393],{},"I wanted some nice clean way to be able to require a role for different routes. I only need the ability to specify a single role, and can rely on the fact that we are only working with a JWTPrincipal here.",[211,395,396],{},"Something like this:",[231,398,400],{"className":233,"code":399,"language":235,"meta":236,"style":236},"authenticate {\n    withRole(Role.USER) {\n        get(\"\u002Ffoo\") {\n            call.respond(HttpStatusCode.OK, service.getFoo()\n        }\n    }\n\n    withRole(Role.ADMIN) {\n        route(\"\u002Fadmin\") {\n            get(\"\u002Fbar\") {\n                call.respond(HttpStatusCode.OK, service.getFoo()\n            }\n        }\n    }\n}\n",[238,401,402,408,416,426,438,442,446,450,457,468,479,492,498,503,508],{"__ignoreMap":236},[241,403,404,406],{"class":243,"line":244},[241,405,287],{"class":254},[241,407,259],{"class":258},[241,409,410,413],{"class":243,"line":262},[241,411,412],{"class":254},"    withRole",[241,414,415],{"class":258},"(Role.USER) {\n",[241,417,418,420,422,424],{"class":243,"line":268},[241,419,353],{"class":247},[241,421,297],{"class":258},[241,423,301],{"class":300},[241,425,304],{"class":258},[241,427,428,430,432,434,436],{"class":243,"line":324},[241,429,366],{"class":258},[241,431,312],{"class":254},[241,433,315],{"class":258},[241,435,318],{"class":254},[241,437,321],{"class":258},[241,439,440],{"class":243,"line":330},[241,441,380],{"class":258},[241,443,444],{"class":243,"line":337},[241,445,327],{"class":258},[241,447,448],{"class":243,"line":350},[241,449,334],{"emptyLinePlaceholder":333},[241,451,452,454],{"class":243,"line":363},[241,453,412],{"class":254},[241,455,456],{"class":258},"(Role.ADMIN) {\n",[241,458,459,462,464,466],{"class":243,"line":377},[241,460,461],{"class":254},"        route",[241,463,297],{"class":258},[241,465,345],{"class":300},[241,467,304],{"class":258},[241,469,470,473,475,477],{"class":243,"line":383},[241,471,472],{"class":247},"            get",[241,474,297],{"class":258},[241,476,358],{"class":300},[241,478,304],{"class":258},[241,480,481,484,486,488,490],{"class":243,"line":388},[241,482,483],{"class":258},"                call.",[241,485,312],{"class":254},[241,487,315],{"class":258},[241,489,318],{"class":254},[241,491,321],{"class":258},[241,493,495],{"class":243,"line":494},12,[241,496,497],{"class":258},"            }\n",[241,499,501],{"class":243,"line":500},13,[241,502,380],{"class":258},[241,504,506],{"class":243,"line":505},14,[241,507,327],{"class":258},[241,509,511],{"class":243,"line":510},15,[241,512,271],{"class":258},[211,514,515],{},"So - implementing this using createRouteScopedPlugin",[211,517,518],{},"First - the configuration:",[231,520,522],{"className":233,"code":521,"language":235,"meta":236,"style":236},"class AuthConfig {\n    lateinit var role: Role\n}\n",[238,523,524,534,548],{"__ignoreMap":236},[241,525,526,529,532],{"class":243,"line":244},[241,527,528],{"class":247},"class",[241,530,531],{"class":254}," AuthConfig",[241,533,259],{"class":258},[241,535,536,539,542,545],{"class":243,"line":262},[241,537,538],{"class":247},"    lateinit",[241,540,541],{"class":247}," var",[241,543,544],{"class":258}," role: ",[241,546,547],{"class":254},"Role\n",[241,549,550],{"class":243,"line":268},[241,551,271],{"class":258},[211,553,554],{},"Then - use that in the plugin:",[231,556,558],{"className":233,"code":557,"language":235,"meta":236,"style":236},"class AuthorizationException(override val message: String? = null) : Throwable()\n\nclass AuthenticationException(override val message: String? = null) : Throwable()\n\nval RoleBasedAuthentication = createRouteScopedPlugin(\n    name = \"AuthorizationPlugin\",\n    createConfiguration = ::AuthConfig,\n) {\n    val requiredRole = pluginConfig.role\n\n    on(AuthenticationChecked) { call ->\n        val user = call.principal\u003CJWTPrincipal>() ?: throw AuthenticationException(message = \"Unauthenticated User\")\n\n        val userRoles = user.getListClaim(\"roles\", Role::class) ?: emptyList()\n        val username = user.get(\"username\")\n\n        if (!userRoles.contains(requiredRole)) {\n            throw AuthorizationException(message = \"User [$username] does not have required role [$requiredRole]: user: $userRoles\")\n        }\n    }\n}\n",[238,559,560,599,603,632,636,652,665,680,684,697,701,712,753,757,790,811,816,837,872,877,882],{"__ignoreMap":236},[241,561,562,564,567,569,572,575,578,581,584,587,591,594,597],{"class":243,"line":244},[241,563,528],{"class":247},[241,565,566],{"class":254}," AuthorizationException",[241,568,297],{"class":258},[241,570,571],{"class":247},"override",[241,573,574],{"class":247}," val",[241,576,577],{"class":258}," message: ",[241,579,580],{"class":254},"String",[241,582,583],{"class":258},"? ",[241,585,586],{"class":247},"=",[241,588,590],{"class":589},"sDLfK"," null",[241,592,593],{"class":258},") : ",[241,595,596],{"class":254},"Throwable",[241,598,321],{"class":258},[241,600,601],{"class":243,"line":262},[241,602,334],{"emptyLinePlaceholder":333},[241,604,605,607,610,612,614,616,618,620,622,624,626,628,630],{"class":243,"line":268},[241,606,528],{"class":247},[241,608,609],{"class":254}," AuthenticationException",[241,611,297],{"class":258},[241,613,571],{"class":247},[241,615,574],{"class":247},[241,617,577],{"class":258},[241,619,580],{"class":254},[241,621,583],{"class":258},[241,623,586],{"class":247},[241,625,590],{"class":589},[241,627,593],{"class":258},[241,629,596],{"class":254},[241,631,321],{"class":258},[241,633,634],{"class":243,"line":324},[241,635,334],{"emptyLinePlaceholder":333},[241,637,638,641,644,646,649],{"class":243,"line":330},[241,639,640],{"class":247},"val",[241,642,643],{"class":258}," RoleBasedAuthentication ",[241,645,586],{"class":247},[241,647,648],{"class":254}," createRouteScopedPlugin",[241,650,651],{"class":258},"(\n",[241,653,654,657,659,662],{"class":243,"line":337},[241,655,656],{"class":258},"    name ",[241,658,586],{"class":247},[241,660,661],{"class":300}," \"AuthorizationPlugin\"",[241,663,664],{"class":258},",\n",[241,666,667,670,672,675,678],{"class":243,"line":350},[241,668,669],{"class":258},"    createConfiguration ",[241,671,586],{"class":247},[241,673,674],{"class":258}," ::",[241,676,677],{"class":254},"AuthConfig",[241,679,664],{"class":258},[241,681,682],{"class":243,"line":363},[241,683,304],{"class":258},[241,685,686,689,692,694],{"class":243,"line":377},[241,687,688],{"class":247},"    val",[241,690,691],{"class":258}," requiredRole ",[241,693,586],{"class":247},[241,695,696],{"class":258}," pluginConfig.role\n",[241,698,699],{"class":243,"line":383},[241,700,334],{"emptyLinePlaceholder":333},[241,702,703,706,709],{"class":243,"line":388},[241,704,705],{"class":254},"    on",[241,707,708],{"class":258},"(AuthenticationChecked) { call ",[241,710,711],{"class":247},"->\n",[241,713,714,717,720,722,725,728,731,734,737,740,742,745,747,750],{"class":243,"line":494},[241,715,716],{"class":247},"        val",[241,718,719],{"class":258}," user ",[241,721,586],{"class":247},[241,723,724],{"class":258}," call.",[241,726,727],{"class":254},"principal",[241,729,730],{"class":258},"\u003C",[241,732,733],{"class":254},"JWTPrincipal",[241,735,736],{"class":258},">() ?: ",[241,738,739],{"class":247},"throw",[241,741,609],{"class":254},[241,743,744],{"class":258},"(message ",[241,746,586],{"class":247},[241,748,749],{"class":300}," \"Unauthenticated User\"",[241,751,752],{"class":258},")\n",[241,754,755],{"class":243,"line":500},[241,756,334],{"emptyLinePlaceholder":333},[241,758,759,761,764,766,769,772,774,777,780,782,785,788],{"class":243,"line":505},[241,760,716],{"class":247},[241,762,763],{"class":258}," userRoles ",[241,765,586],{"class":247},[241,767,768],{"class":258}," user.",[241,770,771],{"class":254},"getListClaim",[241,773,297],{"class":258},[241,775,776],{"class":300},"\"roles\"",[241,778,779],{"class":258},", Role::",[241,781,528],{"class":254},[241,783,784],{"class":258},") ?: ",[241,786,787],{"class":254},"emptyList",[241,789,321],{"class":258},[241,791,792,794,797,799,801,804,806,809],{"class":243,"line":510},[241,793,716],{"class":247},[241,795,796],{"class":258}," username ",[241,798,586],{"class":247},[241,800,768],{"class":258},[241,802,803],{"class":254},"get",[241,805,297],{"class":258},[241,807,808],{"class":300},"\"username\"",[241,810,752],{"class":258},[241,812,814],{"class":243,"line":813},16,[241,815,334],{"emptyLinePlaceholder":333},[241,817,819,822,825,828,831,834],{"class":243,"line":818},17,[241,820,821],{"class":247},"        if",[241,823,824],{"class":258}," (",[241,826,827],{"class":247},"!",[241,829,830],{"class":258},"userRoles.",[241,832,833],{"class":254},"contains",[241,835,836],{"class":258},"(requiredRole)) {\n",[241,838,840,843,845,847,849,852,855,858,861,864,867,870],{"class":243,"line":839},18,[241,841,842],{"class":247},"            throw",[241,844,566],{"class":254},[241,846,744],{"class":258},[241,848,586],{"class":247},[241,850,851],{"class":300}," \"User [",[241,853,854],{"class":589},"$username",[241,856,857],{"class":300},"] does not have required role [",[241,859,860],{"class":589},"$requiredRole",[241,862,863],{"class":300},"]: user: ",[241,865,866],{"class":589},"$userRoles",[241,868,869],{"class":300},"\"",[241,871,752],{"class":258},[241,873,875],{"class":243,"line":874},19,[241,876,380],{"class":258},[241,878,880],{"class":243,"line":879},20,[241,881,327],{"class":258},[241,883,885],{"class":243,"line":884},21,[241,886,271],{"class":258},[211,888,889],{},"Don't forget to handle AuthenticationException and AuthorizationException in statusPages - I log the message and return some vague 4xx error to the user :)",[211,891,892],{},"Finally - add some extensions on Route to make it easy to use:",[231,894,896],{"className":233,"code":895,"language":235,"meta":236,"style":236},"class AuthorizedRouteSelector(private val desc: String) : RouteSelector() {\n    override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation =\n        RouteSelectorEvaluation.Constant\n\n    override fun toString(): String = \"Authorize: $desc\"\n}\n\nfun Route.withRole(role: Role, build: Route.() -> Unit) =\n    authorizedRoute(requiredRole = role, build = build)\n\nprivate fun Route.authorizedRoute(\n    requiredRole: Role,\n    build: Route.() -> Unit,\n): Route {\n    val authorizedRoute = createChild(AuthorizedRouteSelector(requiredRole.toString()))\n\n    authorizedRoute.install(RoleBasedAuthentication) {\n        role = requiredRole\n    }\n\n    authorizedRoute.build()\n\n    return authorizedRoute\n}\n",[238,897,898,925,957,962,966,992,996,1000,1038,1056,1060,1075,1084,1098,1106,1132,1136,1147,1157,1161,1165,1174,1179,1188],{"__ignoreMap":236},[241,899,900,902,905,907,910,912,915,917,919,922],{"class":243,"line":244},[241,901,528],{"class":247},[241,903,904],{"class":254}," AuthorizedRouteSelector",[241,906,297],{"class":258},[241,908,909],{"class":247},"private",[241,911,574],{"class":247},[241,913,914],{"class":258}," desc: ",[241,916,580],{"class":254},[241,918,593],{"class":258},[241,920,921],{"class":254},"RouteSelector",[241,923,924],{"class":258},"() {\n",[241,926,927,930,933,936,939,942,945,948,951,954],{"class":243,"line":262},[241,928,929],{"class":247},"    override",[241,931,932],{"class":247}," fun",[241,934,935],{"class":254}," evaluate",[241,937,938],{"class":258},"(context: ",[241,940,941],{"class":254},"RoutingResolveContext",[241,943,944],{"class":258},", segmentIndex: ",[241,946,947],{"class":254},"Int",[241,949,950],{"class":258},"): ",[241,952,953],{"class":254},"RouteSelectorEvaluation",[241,955,956],{"class":247}," =\n",[241,958,959],{"class":243,"line":268},[241,960,961],{"class":258},"        RouteSelectorEvaluation.Constant\n",[241,963,964],{"class":243,"line":324},[241,965,334],{"emptyLinePlaceholder":333},[241,967,968,970,972,975,978,980,983,986,989],{"class":243,"line":330},[241,969,929],{"class":247},[241,971,932],{"class":247},[241,973,974],{"class":254}," toString",[241,976,977],{"class":258},"(): ",[241,979,580],{"class":254},[241,981,982],{"class":247}," =",[241,984,985],{"class":300}," \"Authorize: ",[241,987,988],{"class":589},"$desc",[241,990,991],{"class":300},"\"\n",[241,993,994],{"class":243,"line":337},[241,995,271],{"class":258},[241,997,998],{"class":243,"line":350},[241,999,334],{"emptyLinePlaceholder":333},[241,1001,1002,1005,1008,1011,1014,1017,1020,1023,1026,1029,1032,1035],{"class":243,"line":363},[241,1003,1004],{"class":247},"fun",[241,1006,1007],{"class":254}," Route",[241,1009,1010],{"class":258},".",[241,1012,1013],{"class":254},"withRole",[241,1015,1016],{"class":258},"(role: ",[241,1018,1019],{"class":254},"Role",[241,1021,1022],{"class":258},", build: ",[241,1024,1025],{"class":254},"Route",[241,1027,1028],{"class":258},".() ",[241,1030,1031],{"class":247},"->",[241,1033,1034],{"class":258}," Unit) ",[241,1036,1037],{"class":247},"=\n",[241,1039,1040,1043,1046,1048,1051,1053],{"class":243,"line":377},[241,1041,1042],{"class":254},"    authorizedRoute",[241,1044,1045],{"class":258},"(requiredRole ",[241,1047,586],{"class":247},[241,1049,1050],{"class":258}," role, build ",[241,1052,586],{"class":247},[241,1054,1055],{"class":258}," build)\n",[241,1057,1058],{"class":243,"line":383},[241,1059,334],{"emptyLinePlaceholder":333},[241,1061,1062,1064,1066,1068,1070,1073],{"class":243,"line":388},[241,1063,909],{"class":247},[241,1065,932],{"class":247},[241,1067,1007],{"class":254},[241,1069,1010],{"class":258},[241,1071,1072],{"class":254},"authorizedRoute",[241,1074,651],{"class":258},[241,1076,1077,1080,1082],{"class":243,"line":494},[241,1078,1079],{"class":258},"    requiredRole: ",[241,1081,1019],{"class":254},[241,1083,664],{"class":258},[241,1085,1086,1089,1091,1093,1095],{"class":243,"line":500},[241,1087,1088],{"class":258},"    build: ",[241,1090,1025],{"class":254},[241,1092,1028],{"class":258},[241,1094,1031],{"class":247},[241,1096,1097],{"class":258}," Unit,\n",[241,1099,1100,1102,1104],{"class":243,"line":505},[241,1101,950],{"class":258},[241,1103,1025],{"class":254},[241,1105,259],{"class":258},[241,1107,1108,1110,1113,1115,1118,1120,1123,1126,1129],{"class":243,"line":510},[241,1109,688],{"class":247},[241,1111,1112],{"class":258}," authorizedRoute ",[241,1114,586],{"class":247},[241,1116,1117],{"class":254}," createChild",[241,1119,297],{"class":258},[241,1121,1122],{"class":254},"AuthorizedRouteSelector",[241,1124,1125],{"class":258},"(requiredRole.",[241,1127,1128],{"class":254},"toString",[241,1130,1131],{"class":258},"()))\n",[241,1133,1134],{"class":243,"line":813},[241,1135,334],{"emptyLinePlaceholder":333},[241,1137,1138,1141,1144],{"class":243,"line":818},[241,1139,1140],{"class":258},"    authorizedRoute.",[241,1142,1143],{"class":254},"install",[241,1145,1146],{"class":258},"(RoleBasedAuthentication) {\n",[241,1148,1149,1152,1154],{"class":243,"line":839},[241,1150,1151],{"class":258},"        role ",[241,1153,586],{"class":247},[241,1155,1156],{"class":258}," requiredRole\n",[241,1158,1159],{"class":243,"line":874},[241,1160,327],{"class":258},[241,1162,1163],{"class":243,"line":879},[241,1164,334],{"emptyLinePlaceholder":333},[241,1166,1167,1169,1172],{"class":243,"line":884},[241,1168,1140],{"class":258},[241,1170,1171],{"class":254},"build",[241,1173,321],{"class":258},[241,1175,1177],{"class":243,"line":1176},22,[241,1178,334],{"emptyLinePlaceholder":333},[241,1180,1182,1185],{"class":243,"line":1181},23,[241,1183,1184],{"class":247},"    return",[241,1186,1187],{"class":258}," authorizedRoute\n",[241,1189,1191],{"class":243,"line":1190},24,[241,1192,271],{"class":258},[211,1194,1195],{},"At this point - the route block above using withRole() {} should now be working :)",[1197,1198,1199],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}",{"title":236,"searchDepth":262,"depth":262,"links":1201},[],"2023-04-18 22:49 +0200",null,"md","Adding support for withRole() {} to routing in ktor2",{},"\u002F2023\u002F04\u002F18\u002Fktor-2-route-withrole-for-jwt",{"title":206,"description":213},{"loc":1207},"2023\u002F04\u002F18\u002Fktor-2-route-withrole-for-jwt",[1212,1213,235,1214],"ktor","jwt","route","aHZFD_Yxl0_5EqHO7WpjVth9bsVFTEVIV-_qo4leWRU",1775293006576]