You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Ed Welch <ed...@edjusted.com> on 2015/03/21 15:32:26 UTC

Authorization with Camel REST DSL?

I hadn't really seen this covered anywhere, so I was curious how people are handling this?

I'm using camel's REST dsl within the java dsl, running in Karaf.

Java EE and Spring both have concepts of annotation based authorization to specific endpoints, and it seemed like it would be nice to incorporate this into the REST dsl.

Having found nothing off the shelf, I attempted to solve this myself by implementing my own RoutePolicy.  In the onExchangeBegin method I look for the Authorization header on the camel Mesage, if it exists, I jump through some hoops with LoginContext to validate the user/password and also the Role.  

If something is wrong, I set an exception on the exchange

In practice it works like this:

in the configure() block I setup a couple route policies, one for admins, one for viewers (these map to JAAS roles, karaf is the realm)

RoleAuthPolicy admin = new RoleAuthPolicy("karaf", "admin");
RoleAuthPolicy viewer = new RoleAuthPolicy("karaf", "viewer");


And then in use, you append the routePolicy in the builder:

rest("servers")
                .get().produces("application/json").route().routeId("get-servers").routePolicy(viewer).to("bean:serverManager?method=getServers()").endRest()
                .get("/{id}").produces("application/json").route().routeId("get-server").routePolicy(viewer).to("bean:serverManager?method=getServer(${headers.id})").endRest()
                .post().route().routeId("post-server").routePolicy(admin).to("bean:serverManager?method=postServer(${body})").endRest();


Pros of this method:

you can have very granular authorization
it fits nicely with the builder patterns

Cons:

I created custom exceptions to handle authentication, and authorization errors and those have to be defined on the route so the user is prompted with what to do:

        onException(UnauthenticatedException.class)
                .handled(true)
                .log(LoggingLevel.WARN, log, "${exception.message}")
                .process(exchange -> {
                    exchange.getIn().setHeader("WWW-Authenticate", "Basic");
                    exchange.getIn().setBody("Unauthenticated");
                    exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
                    exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, HttpServletResponse.SC_UNAUTHORIZED);
                });

        onException(UnauthorizedException.class)
                .handled(true)
                .log(LoggingLevel.WARN, log, "${exception.message}")
                .process(exchange -> {
                    exchange.getIn().setBody("Unauthorized");
                    exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
                    exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, HttpServletResponse.SC_FORBIDDEN);
                });

If someone forgets to do this, you get no authentication or authorization

I also didn't love working inside the onExchangeBegin method, because exceptions thrown in there are swallowed with a warning message.  So any kind of implementation mistake or unexpected situation that throws an exception in the onExchangeBegin method leads too open access!!! to defend against this I wrap the entire thing in a try catch Exception and then set this exception on the exchange.


So i'm curious, how are other people solving this problem?  

Thanks,
Ed

Re: Authorization with Camel REST DSL?

Posted by Willem Jiang <wi...@gmail.com>.
How about implementing the  AuthorizationPolicy instead of RoutePolicy?


--  
Willem Jiang

Red Hat, Inc.
Web: http://www.redhat.com
Blog: http://willemjiang.blogspot.com (English)
http://jnn.iteye.com (Chinese)
Twitter: willemjiang  
Weibo: 姜宁willem



On March 21, 2015 at 10:33:15 PM, Ed Welch (ed@edjusted.com) wrote:
> I hadn't really seen this covered anywhere, so I was curious how people are handling this?  
>  
> I'm using camel's REST dsl within the java dsl, running in Karaf.
>  
> Java EE and Spring both have concepts of annotation based authorization to specific  
> endpoints, and it seemed like it would be nice to incorporate this into the REST dsl.
>  
> Having found nothing off the shelf, I attempted to solve this myself by implementing  
> my own RoutePolicy. In the onExchangeBegin method I look for the Authorization header  
> on the camel Mesage, if it exists, I jump through some hoops with LoginContext to validate  
> the user/password and also the Role.
>  
> If something is wrong, I set an exception on the exchange
>  
> In practice it works like this:
>  
> in the configure() block I setup a couple route policies, one for admins, one for viewers  
> (these map to JAAS roles, karaf is the realm)
>  
> RoleAuthPolicy admin = new RoleAuthPolicy("karaf", "admin");
> RoleAuthPolicy viewer = new RoleAuthPolicy("karaf", "viewer");
>  
>  
> And then in use, you append the routePolicy in the builder:
>  
> rest("servers")
> .get().produces("application/json").route().routeId("get-servers").routePolicy(viewer).to("bean:serverManager?method=getServers()").endRest()  
> .get("/{id}").produces("application/json").route().routeId("get-server").routePolicy(viewer).to("bean:serverManager?method=getServer(${headers.id})").endRest()  
> .post().route().routeId("post-server").routePolicy(admin).to("bean:serverManager?method=postServer(${body})").endRest();  
>  
>  
> Pros of this method:
>  
> you can have very granular authorization
> it fits nicely with the builder patterns
>  
> Cons:
>  
> I created custom exceptions to handle authentication, and authorization errors and  
> those have to be defined on the route so the user is prompted with what to do:
>  
> onException(UnauthenticatedException.class)
> .handled(true)
> .log(LoggingLevel.WARN, log, "${exception.message}")
> .process(exchange -> {
> exchange.getIn().setHeader("WWW-Authenticate", "Basic");
> exchange.getIn().setBody("Unauthenticated");
> exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
> exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, HttpServletResponse.SC_UNAUTHORIZED);  
> });
>  
> onException(UnauthorizedException.class)
> .handled(true)
> .log(LoggingLevel.WARN, log, "${exception.message}")
> .process(exchange -> {
> exchange.getIn().setBody("Unauthorized");
> exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
> exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, HttpServletResponse.SC_FORBIDDEN);  
> });
>  
> If someone forgets to do this, you get no authentication or authorization
>  
> I also didn't love working inside the onExchangeBegin method, because exceptions thrown  
> in there are swallowed with a warning message. So any kind of implementation mistake  
> or unexpected situation that throws an exception in the onExchangeBegin method leads  
> too open access!!! to defend against this I wrap the entire thing in a try catch Exception  
> and then set this exception on the exchange.
>  
>  
> So i'm curious, how are other people solving this problem?
>  
> Thanks,
> Ed