Angular2 How to get token by sending credentials

I am using Angular2 to access the token from an external Spring Java application. I can get the token through CURL, but not through the Angular form.

curl localhost:8085/uaa/oauth/token --data "grant_type=password&scope=write&username=MY-USERNAME&password=MY-PASSWORD" --user user:pwd 

I have included Cors in Java back-end as follows:

  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { final HttpServletResponse response = (HttpServletResponse) servletResponse; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE, GET, HEAD, OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, If-Modified-Since"); chain.doFilter(servletRequest, servletResponse); } 

My Angular code is as follows:

 import {Injectable, Component} from 'angular2/core'; import {Observable} from 'rxjs/Rx'; import {Http, HTTP_PROVIDERS, Headers} from 'angular2/http'; @Component({ viewProviders: [HTTP_PROVIDERS] }) @Injectable() export class Authentication { token:string; http:Http; constructor(http:Http) { this.token = localStorage.getItem('token'); this.http = http; } login(username:String, password:String) { var url = 'http://localhost:8085/uaa/oauth/token', body = JSON.stringify({ username: username, password: password }), options = { headers: new Headers({ 'credentials': 'true', 'grant_type': 'password', 'scope': 'write', 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }) }; return this.http.post(url, body, options) .map((res:any) => { let data = res.json(); this.token = data.token; localStorage.setItem('token', this.token); }); } } 

Server response:

 Request URL:http://localhost:8085/uaa/oauth/token Request Method:OPTIONS Status Code:401 Unauthorized Remote Address:[::1]:8085 
+8
source share
4 answers

You may have two problems:

  • The OPTIONS call is a preflight call. The CORS standard states that preflight calls should not include authentication. If your server is not configured to process it, you will receive a 401 response. If you have control over the server, you can add something to allow the OPTIONS call. With NGINX, you can add something like:

    if ($request_method = 'OPTIONS') {return 200;}

    Not sure if you are a specific server.

  • Are you sure you are sending credentials correctly? It looks like you are sending all this as separate headers, and not as data in a form, such as you with a curl request. This worked for me:

     var headers = new Headers(); headers.append('Content-Type', 'application/x-www-form-urlencoded'); var credentials = "grant_type=authorization_code + "&credentials=true" + "&scope=write" /* etc. */ this.http.post('http://some.url', credentials, { headers: headers }) .subscribe((res) => token = res.json()) 
+9
source

You must specify the username and password hints in the authorization header using the "General" scheme. The value must be base64 encoded using the btoa function:

 headers.append('Authorization', 'Basic ' + btoa('username:password'); 

Also, after you attached your curling request, it seems that what you put in the headers should be provided in the payload. This can be done using the UrlSearchParams class.

See the question about rice for more details:

+2
source

this is the following code for nginx default.config that works.

 upstream book_up { server localhost:3002; } server { location /login { proxy_pass http://book_up/book/user/login; } location /health { proxy_pass http://book_up/book/health; } location /book { auth_request /auth; proxy_pass http://book_up$request_uri; } location = /auth { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # # Custom headers and headers various browsers *should* be OK with but aren't # add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; # # Tell client that this pre-flight info is valid for 20 days # add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; } proxy_pass http://book_up/book/user/auth/; proxy_set_header Content-Length ""; proxy_set_header X-Original-URI $request_uri; } } 
+1
source

The problem is probably in your corner service. I think that you should not send the body as an object that contains the username and password, but you should send a string that contains "grant_type", "username" and "password". This is an example of my working maintenance method:

  postAuth(url: string, data?: LoginCredentials){ let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }); let options = new RequestOptions({ headers: headers }); //here I am setting username and password which I got from html form var body = "grant_type=password&username="+ data.Email + "&password=" + data.Password; return this.http.post(url, body, options); } 
0
source

All Articles