Abzal Kalimbetov
Abzal Kalimbetov

Reputation: 505

Spring Session Basic Auth token passed as query parameter in Spring-Websocket

Currently we have Rest app with Spring Boot, Spring Session (Redis) and Spring Security. We use basic auth. Now I would like to add websocket support.

  1. When client logs in successfully to other part of application, he gets x-auth-token. It is passed later as header, and it works.

  2. Then websocket client sends this token as query parameter to connect to service.

We would like to make Spring Security and Spring Session accept token through query param in websocket connection. Is there any parameter that I can set? Or do we need to write custom authentication provider. If so, how do we integrate with Spring Session?

Upvotes: 1

Views: 3394

Answers (2)

Murali S
Murali S

Reputation: 9

Example for basic authentication using token servlet http request header before websocket connection:

****ws://localhost:8081/remoteservice/id?access_token=tokenValue****

verify your token return true if valid else return false

endpoint configuration:

@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer{

    @Autowired
    RemoteServiceHandler rsHandler;

public void registerWebSocketHandlers(WebSocketHandlerRegistry registry){
        registry.addHandler(rsHandler, "/remoteservice/{vin}").setAllowedOrigins("*").addInterceptors(new HttpHandshakeInterceptor());
    }   
}

validate the token before established websocket connectin:

public class HttpHandshakeInterceptor implements HandshakeInterceptor{

@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,  Map attributes) throws Exception 
{
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
String token = servletRequest.getServletRequest().getHeader("access_token");
try {
            Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();

            if (claims!=null) {
                return true;
            }
        } catch (Exception e) {

            return false;
        }
        return false;
}

skip the http security endpoint

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Override 
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().anyRequest(); 
    }

}

pom.xml

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>

add the request header in js file as you like

var request = URLRequest(url: URL(string: "ws://localhost:8081/remoteservice")!)
request.timeoutInterval = 5 // Sets the timeout for the connection
request.setValue("someother protocols", forHTTPHeaderField: "Sec-WebSocket-Protocol")
request.setValue("14", forHTTPHeaderField: "Sec-WebSocket-Version")
request.setValue("chat,superchat", forHTTPHeaderField: "Sec-WebSocket-Protocol")
request.setValue("Everything is Awesome!", forHTTPHeaderField: "My-Awesome-Header")
let socket = WebSocket(request: request)

Upvotes: 0

VendettaTurkey
VendettaTurkey

Reputation: 330

You can use queryString parameter for this, but I had the same issue, and my suggestion is to pass your token with headers at subscription time, or while sending messages from your JS client.

As you have a custom filter to handle your X-Auth-Token, Spring security doesn't support defining a custom-filter at websocket interceptors defined in Security.xml . All you need is to implement interceptor for inbound channel , and to handle token authentication through access of nativeHeader sent with messages at Presend method, through an injected instance of your token authentication service.

Upvotes: 0

Related Questions