I want to share my solution. I did not find a way to authenticate the
"Upgrade" message and the websocket messages do not send headers. So
I add the basic authentication to my message payload. The code is:
*********************
package com.revinate.sifter.auth;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.Processor;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.codec.Base64;
import org.springframework.stereotype.Component;
import javax.security.auth.Subject;
import java.io.IOException;
import java.util.Map;
@Component
public class WebsocketAuthentication implements Processor {
@Autowired
private UserDetailsService userDetailsService;
@Override
public void process(Exchange exchange) throws IOException {
Message in = exchange.getIn();
String body = in.getBody(String.class);
Map<?, ?> payload = new ObjectMapper().readValue(body, Map.class);
if (payload.containsKey("basic")) {
String s = (String) payload.get("basic");
String[] t = extractAndDecodeHeader(s);
UserDetails userDetails =
userDetailsService.loadUserByUsername(t[0]);
if (userDetails.isAccountNonExpired() &&
userDetails.isAccountNonLocked() &&
userDetails.isCredentialsNonExpired() &&
userDetails.isEnabled() &&
t[1].equals(userDetails.getPassword())) {
Authentication userPrincipal = new
UsernamePasswordAuthenticationToken(userDetails.getUsername(),
userDetails.getPassword(), userDetails.getAuthorities());
Subject subject = new Subject();
subject.getPrincipals().add(userPrincipal);
in.setHeader(Exchange.AUTHENTICATION, subject);
in.setBody(payload.get("data"));
} else {
throw new AccessDeniedException("User do not have
access to this resource.");
}
}
}
private String[] extractAndDecodeHeader(String header) throws IOException {
byte[] base64Token = header.substring(6).getBytes("UTF-8");
byte[] decoded;
try {
decoded = Base64.decode(base64Token);
} catch (IllegalArgumentException e) {
throw new BadCredentialsException("Failed to decode basic
authentication token");
}
String token = new String(decoded);
int delim = token.indexOf(":");
if (delim == -1) {
throw new BadCredentialsException("Invalid basic
authentication token");
}
return new String[] {token.substring(0, delim),
token.substring(delim + 1)};
}
}
On Sat, Aug 17, 2013 at 7:56 AM, Christian Posta
<[email protected]> wrote:
> Spring Security does, iirc but might have a look at the underlying
> websocket connector and its configs. Its implemented with Jetty.
>
>
> On Fri, Aug 16, 2013 at 3:01 PM, Jose Espinosa <[email protected]> wrote:
>
>> Hey Christian,
>>
>> Thanks for the response, I have already have look and the sources you
>> point and they let me make some progress as I am using spring and I am
>> already using it for securing my http requests.
>>
>> If I understand correctly I need to add the authentication information
>> in the payload of my socket and I need to set that information to the
>> Exchange.AUTHENTICATION header right? I already hack a way to create
>> a mock authentication that let me access the websockets.
>>
>> I want to use Basic authentication but role my own security is always
>> a bad idea. Do you know if spring provide some helper classes for
>> Basic Authentication?
>>
>> Thank you very much,
>> Jose
>>
>> On Fri, Aug 16, 2013 at 1:05 PM, Christian Posta
>> <[email protected]> wrote:
>> > Jose,
>> > Depends on which security mechanism you use. For example, for
>> > spring-security, take a look here:
>> >
>> > http://camel.apache.org/spring-security.html
>> >
>> > You can set up the infrastructure for Spring Security to intercept and
>> > validate the authentication, but the Authentication object being on the
>> > exchange is your responsibility. You can add a processor that reads the
>> > websocket payload and extracts the un/pw from there. You can also set up
>> > the websocket connection to go over SSL to avoid sending plaintext.
>> >
>> > http://camel.apache.org/websocket.html
>> >
>> >
>> >
>> >
>> > On Fri, Aug 16, 2013 at 11:10 AM, Jose Espinosa <[email protected]>
>> wrote:
>> >
>> >> Hey all,
>> >>
>> >> I am using websockets to start on of my routes, now I am looking at
>> >> adding security to my websockets end points.
>> >>
>> >> I took a look at camel security as described here
>> >> http://camel.apache.org/camel-security.html and it works as
>> >> advertised, but now I cann't find how to make my websocket client to
>> >> authenticate.
>> >>
>> >> Any pointers on how to make my websocket client to authenticate with
>> camel?
>> >>
>> >> Thank you very much,
>> >> Jose
>> >>
>> >
>> >
>> >
>> > --
>> > *Christian Posta*
>> > http://www.christianposta.com/blog
>> > twitter: @christianposta
>>
>
>
>
> --
> *Christian Posta*
> http://www.christianposta.com/blog
> twitter: @christianposta