Hello I am using the Ionic 2 framework with Angular and I want to make a http request with the authorization header but it appears it is not sending the header. What have I done wrong?
@Injectable()
export class UserServiceProvider {
private loginSuccess: any;
constructor(public http: Http) {
console.log('Hello UserServiceProvider Provider');
}
login(username, password)
{
var token = btoa(username + ':' + password);
alert(token);
this.loginSuccess = false;
let headers = new Headers();
headers.append('Authorization', 'Basic ' + token);
this.http.get('http://localhost:8080/HelloWorld/api/login/try', {
headers: headers
})
.subscribe(function success(response) {
this.loginSuccess = true;
}, function error(response) {
this.loginSuccess = false;
});
return this.loginSuccess;
}
}
Here is the response in the browser console
polyfills.js:3 OPTIONS http://localhost:8080/HelloWorld/api/login/try 401 ()
s @ polyfills.js:3
t.scheduleTask @ polyfills.js:3
onScheduleTask @ polyfills.js:3
t.scheduleTask @ polyfills.js:3
r.scheduleTask @ polyfills.js:3
r.scheduleMacroTask @ polyfills.js:3
(anonymous) @ polyfills.js:3
o.(anonymous function) @ polyfills.js:2
(anonymous) @ http.es5.js:1275
Observable._trySubscribe @ Observable.js:171
Observable.subscribe @ Observable.js:159
webpackJsonp.197.UserServiceProvider.login @ user-service.ts:29
webpackJsonp.196.AccountPage.login @ account.ts:21
(anonymous) @ AccountPage.html:25
handleEvent @ core.es5.js:12022
callWithDebugContext @ core.es5.js:13486
debugHandleEvent @ core.es5.js:13074
dispatchEvent @ core.es5.js:8615
(anonymous) @ core.es5.js:9226
(anonymous) @ platform-browser.es5.js:2651
t.invokeTask @ polyfills.js:3
onInvokeTask @ core.es5.js:3881
t.invokeTask @ polyfills.js:3
r.runTask @ polyfills.js:3
e.invokeTask @ polyfills.js:3
p @ polyfills.js:2
v @ polyfills.js:2
(index):1 Failed to load
http://localhost:8080/HelloWorld/api/login/try: Response for preflight
has invalid HTTP status code 401
Below is the sample code of my project which I am using for login. Please refer the same for login. please check whether the login function in web service is GET or POST.
public postOAuthRequest(login:Login):Promise<any> {
// Parameters obj-
let params:URLSearchParams = new URLSearchParams();
let headersvar = new Headers();
params.set('username', login.userId.toString());
params.set('password', login.password.toString());
params.set('grant_type', 'password');
params.set('scope', 'read write');
params.set('client_secret', '123456');
params.set('client_id', 'prithivi');
var authdata = 'Basic ' + btoa('clientapp' + ':' + '412589');
headersvar.append('accept', 'application/json');
headersvar.append('Authorization', authdata);
let requestOption:RequestOptionsArgs = {
search: params,
headers: headersvar,
body: JSON.stringify({clientapp: 412589})
};
return this.http
.post(OauthUrl, JSON.stringify({clientapp: 412589}), requestOption)
.toPromise()
.then(this.extractData)
}
Add a CORS filter method in web service to overcome CORS issue. Below code is in JAVA
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT,DELETE");
response.setHeader("Access-Control-Max-Age", "3628800");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-XSRF-TOKEN");
if (!"OPTIONS".equals(request.getMethod())) {
chain.doFilter(req, res);
} else {
response.setStatus(200);
}
}
Prithivi Raj helped solve my problem but it wasen't complete.
I used his code
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT,DELETE");
response.setHeader("Access-Control-Max-Age", "3628800");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-XSRF-TOKEN");
if (!"OPTIONS".equals(request.getMethod())) {
chain.doFilter(req, res);
} else {
response.setStatus(200);
}
}
You must create a filter that implements Filter and then in your web XML add
<filter>
<filter-name>FilterName</filter-name>
<filter-class>FilterPackage.FilterClass</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterName</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Finally I assume the basic security configuration is being used so in your WebSecurityConfigurerAdapter your configure method should look like the code below. Basically you add a filter before the BasicAuthenticationFilter is activated solving the issue. If you do not do this and your login page uses authentication then your filter will only be called after authentication and by that point its too late
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(new CorsFilter(), BasicAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/api/login/try").access("hasRole('ROLE_USER')")
.antMatchers("/api/vehicles/manage/update").access("hasRole('ROLE_USER')")
.antMatchers("/api/vehicles/manage/create").access("hasRole('ROLE_USER')")
.antMatchers("/api/proposals/create").access("hasRole('ROLE_USER')")
.antMatchers("/api/proposals/cancel").access("hasRole('ROLE_USER')")
.antMatchers("/api/proposals/update").access("hasRole('ROLE_USER')")
.antMatchers("/api/proposals/accept").access("hasRole('ROLE_USER')")
.antMatchers("/api/upload").access("hasRole('ROLE_USER')")
.anyRequest().permitAll()
.and()
.csrf().disable()
.httpBasic()
.and()
.logout()
.permitAll();
}
Thanks Prithivi Raj for your help!