java - Setting Authorization header in Angular 2 -
i working on restful services in spring , have implemented json web token (jwt) authentication , authorization. after login proper authentication token returned requesting user. on every request checking token in request header , validating token. code filter below.
@override protected void dofilterinternal(httpservletrequest request, httpservletresponse response, filterchain chain) throws servletexception, ioexception { string authtoken = request.getheader(this.tokenheader); system.out.println(authtoken + " ##########################"); string username = fltokenutil.getusernamefromtoken(authtoken); if (username != null && securitycontextholder.getcontext().getauthentication() == null) { userdetails userdetails = this.userdetailsservice.loaduserbyusername(username); if (fltokenutil.validatetoken(authtoken, userdetails)) { usernamepasswordauthenticationtoken authentication = new usernamepasswordauthenticationtoken( userdetails, null, userdetails.getauthorities()); authentication.setdetails(new webauthenticationdetailssource().builddetails(request)); securitycontextholder.getcontext().setauthentication(authentication); } } chain.dofilter(request, response); }
and using angular 2 frontend framework. when after getting authentication token request secured resource using "postman" works , token received in filter , goes well. setting token in "authorization" header. problem when same thing using angular 2 token going null in filter firebug shows "authorization" header set , send successfully. doing this
let token = ""; if (undefined != this._tokenservice.gettoken()) { token = this._tokenservice.gettoken().gettoken() } let header: headers = new headers(); header.append('content-type', 'application/json'); header.append('authorization', token); let options = new requestoptions({headers: header}); return this.http.get(url, options) .map(res => { console.log(res.status) if (res.status == 200) { return res.json(); } else if (res.status == 401) { return null; } else { throw new error('this request has failed ' + res.status); } });
what doing wrong? proper way set header in angular 2. how can solve issue?
if want more permanent solution i've got 1 you.
by subclassing angular's http service can inject subclassed version , headers added.
import { http, connectionbackend, headers, request, requestoptions, requestoptionsargs, response, requestmethod, } '@angular/http'; import { observable } 'rxjs/observable'; import { errorobservable } 'rxjs/observable/errorobservable'; // service can logged in users jwt token observable import { securityservice } './security.service'; // service handles cookies (angular2-cookie) import { cookieservice } '../cookie'; /** * custom http client handles conversions json, adds csrf token, , jwt token , redirects signin if token missing */ export class securehttp extends http { constructor( backend: connectionbackend, defaultoptions: requestoptions, private securityservice: securityservice, private cookieservice: cookieservice ) { super(backend, defaultoptions); } request(url: string | request, options?: requestoptionsargs): observable<any> { if (typeof url === 'string') { return this.get(url, options); // recursion: transform url string request } return this.sendrequest(url, options); } get(url: string, options?: requestoptionsargs): observable<any> { return this.sendrequest({ method: requestmethod.get, url: url, body: '' }, options); } post(url: string, body: string, options?: requestoptionsargs): observable<any> { return this.sendrequest({ method: requestmethod.post, url: url, body: body }, options); } put(url: string, body: string, options?: requestoptionsargs): observable<any> { return this.sendrequest({ method: requestmethod.put, url: url, body: body }, options); } delete(url: string, options?: requestoptionsargs): observable<any> { return this.sendrequest({ method: requestmethod.delete, url: url, body: '' }, options); } patch(url: string, body: string, options?: requestoptionsargs): observable<any> { return this.sendrequest({ method: requestmethod.patch, url: url, body: body }, options); } head(url: string, options?: requestoptionsargs): observable<any> { return this.sendrequest({ method: requestmethod.head, url: url, body: '' }, options); } private sendrequest(requestoptionsargs: requestoptionsargs, options?: requestoptionsargs): observable<any> { let requestoptions = new requestoptions(requestoptionsargs); // convert body stringified json if it's not string if (typeof requestoptions.body !== 'string') { requestoptions.body = json.stringify(requestoptions.body); } // xsrf token spring security cookie // adding .csrf().csrftokenrepository(cookiecsrftokenrepository.withhttponlyfalse()) const csrftoken: string = this.cookieservice.get('xsrf-token'); let baseoptions: requestoptions = new requestoptions({ headers: new headers({ 'content-type': 'application/json', 'x-requested-with': 'xmlhttprequest', 'x-xsrf-token': csrftoken }) }); return this.securityservice.accesstoken$.mergemap(token => { // if there token add baseoptions if (token) { baseoptions.headers.set('authorization', 'bearer ' + token); } // create request passed in method, url, body , merge our base options in there let request = new request(baseoptions.merge(requestoptions)); return super.request(request, options) .map(res => res.json()) .catch(this.errorhandler); }); } private errorhandler(errorresponse: response): observable<any> | errorobservable { if (errorresponse.status === 401) { console.log('redirecting login'); window.location.href = '/login'; return observable.empty(); } // if it's serious problem can log service if want if (errorresponse.status === 500) { // this.errorreporter.logerror(errorresponse); } console.error(errorresponse); return observable.throw(errorresponse.text().length > 0 ? errorresponse.json() : { status: 'error' }); } }
then in module
export function securehttpfactory(backend: xhrbackend, defaultoptions: requestoptions, securityservice: securityservice, cookieservice: cookieservice) { return new securehttp(backend, defaultoptions, securityservice, cookieservice); } @ngmodule({ imports: [ httpmodule, cookiemodule, storagemodule, ], declarations: [ ...directives, ...components, ], exports: [ ...directives, ] }) export class securitymodule { // create on instance of these static forroot(): modulewithproviders { return { ngmodule: securitymodule, providers: [ securityservice, { provide: securehttp, usefactory: securehttpfactory, deps: [xhrbackend, requestoptions, securityservice, cookieservice] } ] }; } }
Comments
Post a Comment