Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring boot security #494

Open
yash27 opened this issue Jun 20, 2018 · 15 comments
Open

Spring boot security #494

yash27 opened this issue Jun 20, 2018 · 15 comments

Comments

@yash27
Copy link

yash27 commented Jun 20, 2018

In my angular application whenever it is loaded for the first time. It redirects to the login.component where user logs in with email and password. Now login component is a child component of app.component. In login.component I use to send the email and password to the server and get back the authorization token for the session which is I am storingit in the sessionStorage and then it redirects to the dashboard.component where I actually want to use websocket connection. I have gone through your ng5 example of stomp-js where you have configured the sock and stomp in the app.module.ts. Now my question is, how to pass the authorization token with the headers while configuring the stomp.

import { Observable } from 'rxjs/Rx';
import { endponitConfig } from './../environments/endpoints';
import { KeysPipe } from './sharedmodules/grouping.pipe';
import { NgModule, ApplicationRef } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
/*
 * Platform and Environment providers/directives/pipes
 */
import { routing } from './app.routing'
// App is our top level component
import { AppComponent } from './app.component';
import { APP_RESOLVER_PROVIDERS } from './app.resolver';
import { AppState, InternalStateType } from './app.service';
// Core providers
import {CoreModule} from './core/core.module';
import {SmartadminLayoutModule} from './shared/layout/layout.module';
import { ModalModule } from 'ngx-bootstrap/modal';
import { AuthGuard } from './+auth/+guards/index';
import { userRoleGuard } from './+auth/+guards/userRole.guard';
import { ChartModule } from 'angular-highcharts';
import {} from 'jasmine';
import {StompConfig, StompService} from '@stomp/ng2-stompjs';
import * as SockJS from 'sockjs-client';

export function socketProvider() {
  return new SockJS(endponitConfig.WEBSOCKET_URL);
}

const stompConfig: StompConfig = {
  url: socketProvider,
  headers: {
     Auth : sessionStorage.getItem('Authentication')
  },
  heartbeat_in: 0,
  heartbeat_out: 20000,
  reconnect_delay:10000,
  debug: true
};

// Application wide providers
const APP_PROVIDERS = [
  ...APP_RESOLVER_PROVIDERS,
  AppState
];

interface StoreType {
  state: InternalStateType,
  restoreInputValues: () => void,
  disposeOldHosts: () => void
}

/**
 * `AppModule` is the main entry point into Angular2's bootstraping process
 */
@NgModule({
  bootstrap: [ AppComponent ],
  declarations: [
    AppComponent,
  ],
  imports: [ // import Angular's modules
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    HttpModule,
    ChartModule,
    ModalModule.forRoot(),
    CoreModule,
    SmartadminLayoutModule,
    routing
  ],
  exports: [
  ],
  providers: [ // expose our Services and Providers into Angular's dependency injection
    // ENV_PROVIDERS,
    AuthGuard,
    userRoleGuard,
    APP_PROVIDERS,
    StompService,
    {
      provide: StompConfig,
      useValue: stompConfig
    }
  ]
})
export class AppModule {
  constructor(public appRef: ApplicationRef, public appState: AppState) {}
}

Is there any way to set the headers when I receive the auth token in the login.component and then configure the stomp?

@yash27 yash27 changed the title sending authorization token with headers setting the headers in the child component of app.module.ts Jun 20, 2018
@kum-deepak
Copy link
Member

Please check https://github.com/stomp-js/ng2-stompjs#delayed-initialization - using StompRService might solve your issue.

@yash27
Copy link
Author

yash27 commented Jun 20, 2018

@kum-deepak Thank you sir, it worked for me :)

@yash27 yash27 closed this as completed Jun 20, 2018
@tofiqquadri
Copy link

@kum-deepak Thank you sir, it worked for me :)

What did you used for it? I am having same requirement.

@kum-deepak
Copy link
Member

If you are using newer API (v7), you can use the guidelines from #495

Below you can see example code from @Oddisey at #495

You can ignore the proxy part and follow the rest.

@kum-deepak kum-deepak reopened this Dec 3, 2018
@tofiqquadri
Copy link

I need to send something like this Authentication : 'Bearer ' + token with the headers

@Oddisey
Copy link

Oddisey commented Dec 3, 2018

Totally do-able. When configuring the connection do the following

const token = "Bearer" + yourCSRFToken;
const config: InjectableRxStompConfig = { ...MyStompConfig, connectHeaders: { "Authentication": token } };

@tofiqquadri
Copy link

tofiqquadri commented Dec 3, 2018

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';

import {AppComponent} from './app.component';
import {RawDataComponent} from './components/rawdata/rawdata.component';
import {StatusComponent} from './components/status/status.component';

import {StompConfig, StompService} from '@stomp/ng2-stompjs';

const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOiI4MTlkYzF' +
'kYi04OGM0LTQ4NzAtYmE3ZC0yOTRiOGM5MjBkZGYiLCJwZXJmaWwiOiJVU0VSIiwiaXNMaW1pdGVkQWNj' +
'ZXNzIjpmYWxzZSwiaWF0IjoxNTQxOTM4Njc3fQ.AXCEL05gDBNrfwlOsOrLh7gkWP8D2tOrHUnF0A2T-PY';

const stompConfig: StompConfig = {
  // Which server?
  url: 'ws://34.247.106.82:8100/',

  // Headers
  // Typical keys: login, passcode, host
  headers: {
    // Authentication : 'Bearer ' + token
  },
  // How often to heartbeat?
  // Interval in milliseconds, set to 0 to disable
  heartbeat_in: 0, // Typical value 0 - disabled
  heartbeat_out: 20000, // Typical value 20000 - every 20 seconds

  // Wait in milliseconds before attempting auto reconnect
  // Set to 0 to disable
  // Typical value 5000 (5 seconds)
  reconnect_delay: 5000,

  // Will log diagnostics on console
  debug: true
};


@NgModule({
  declarations: [
    AppComponent,
    RawDataComponent,
    StatusComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [
    StompService,
    {
      provide: StompConfig,
      useValue: stompConfig
    }
  ],
  bootstrap: [AppComponent]
})

export class AppModule {
}

My application App module structure looks like this. How should I use the code you sent me over here?

@Oddisey
Copy link

Oddisey commented Dec 3, 2018

First export your config constant so that it's useable in this file. I would break it out into it's own file if I were you.

For a basic example, let's use it in a Component:

import { Component, OnInit } from "@angular/core";
import { RxStompService } from '@stomp/ng2-stompjs';
import { stompConfig } from './app.module';

@Component({
    selector: "app",
    template: "<div *ngIf="foo$ | async">{{bar}}</div>",
    style: ``,
})
export class AppComponent implements OnInit {

    const foo$;
    const bar;

    constructor(private rxStompService: RxStompService) {}

    ngOnInit() {
        // create an empty headers object
        const headers = {};

        // get the CSRF from the store
        const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOiI4MTlkYzF" +
                        "kYi04OGM0LTQ4NzAtYmE3ZC0yOTRiOGM5MjBkZGYiLCJwZXJmaWwiOiJVU0V"+
                        "SIiwiaXNMaW1pdGVkQWNjZXNzIjpmYWxzZSwiaWF0IjoxNTQxOTM4Njc"+
                         "3fQ.AXCEL05gDBNrfwlOsOrLh7gkWP8D2tOrHUnF0A2T-PY';

        // make that CSRF token look like a real header
        headers["Authentication"] = "Bearer" + token;

        // put the CSRF header into the connectHeaders on the config
        const config = { ... stompConfig, headers: headers };

        // configure the actual websocket service
        this.rxStompService.configure(config);

        // Activate the service
        this.rxStompService.activate();

        // start a websocket connection
        this.foo$ = this.rxStompService.watch("/topic/notify").pipe(
            tap((message: Message) => {
                this.bar = message.body;
            })
        );
    }
}

You can do the subscribing and unsubscribing in a couple of different ways. I used a variable that will have its subscription handled by the async pipe. But this should give you what you're looking for.

Edited to add call to activate the rxStompService

@tofiqquadri
Copy link

I did the exact same thing but it is still not sending the headers please see the image below:
headers

@kum-deepak
Copy link
Member

There is no way to add headers to the underlying HTTP request for the WebSocket. The WebSocket standards has no mechanism for that.

The code above will add the header to the STOMP CONNECT frame; which can be used by the broker.

@tofiqquadri
Copy link

Is there any way by which I can send the authentication token along with the it?

@Oddisey
Copy link

Oddisey commented Dec 4, 2018

One thing that confused the crap out of me when I was learning websocket communication is that. STOMP Headers are not the same a as HTTP headers. SOMP headers are sent in STOMP communication which happens post-handshake.

The way that Stomp-based communication works is that first there is an HTTP Get made with an "upgrade to 1.1" header which tells the server to upgrade this communication from HTTP to websocket. This is the "handshake" process. During this process you do not need CSRF tokens. CSRF is only used for state-altering calls (such as POST, PUT, DELETE....or in stomps case "outbound" communication like the .publish() function). So in the handshake call that you sent in that last image, you don't actually need to send the token in the header

After handshake is successfully completed, there is an open communication between the client and server. You should be sending the token in the STOMP headers. To view the STOMP headers (which should include the token) that you are sending I would use the other kind of config

I would advise using a InjectableRxStompConfig instead of a StompConfig. The reason is that ng2-stomps "debug" callback (which is only available when using a InjectableRxStompConfig) will show you what STOMP headers you are sending in the CONNECT frame.

@Oddisey
Copy link

Oddisey commented Dec 4, 2018

If you really would like to send an authentication token along with the Handshake call, then put it in a cookie. All cookies are sent as headers for all HTTP outbound traffic.

@tofiqquadri
Copy link

The server denies the Handshake itself without the Authentication token. I was too thinking about the cookie way as last thing but I believe that's the only option now.

Thank you for your support @Oddisey and @kum-deepak for your valuable time.

@Oddisey
Copy link

Oddisey commented Dec 4, 2018

Not a problem. Yeah in that case, when you're doing your authentication communication (like a login request) the response should send back a SET-COOKIE header with a value of the cookie that you would like to set. This is usually called a SESSION_ID or Session cookie as it is a persistent token that shows that you are who you say you are because you got that cookie after authentication.

@kum-deepak kum-deepak changed the title setting the headers in the child component of app.module.ts Spring boot security Dec 23, 2018
@kum-deepak kum-deepak transferred this issue from stomp-js/ng2-stompjs Jan 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants