Waffle CORS JAVA Jersey Restful-api: No "Access-Control-Allow-Origin" authorization required

904 views
Skip to first unread message

Zak Guler

unread,
Jun 23, 2015, 12:14:47 PM6/23/15
to waffle...@googlegroups.com
Main purpose: Get logged in user name api. Can be called from any UI with CORS implementation.
Tech stack: Waffle,  CORS,  JAVA Jersey Restful-api,  AngularJS, Tomcat7

Description of the issue:
Added waffle1.5 to my Jersey tomcat app. when I call the api from 'advanced restful client' or 'Postman' it runs fine and gets me the principal user name from the server side "principaluser = request.getUserPrincipal().getName();". but, when I call it from my web app using AJAX. it gives me error: authorization required + HTTP status 401.

error messages:
on the browser console: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 401.
on tomcat log:
   DEBUG w.servlet.NegotiateSecurityFilter - GET /ServiceCloud/ldap/user, contentlength: -1
   DEBUG w.servlet.NegotiateSecurityFilter - authorization required

Can anyone help how to resolve this issue. 

I am not trying to authenticate. just want:
-with CORP 'Cross Platform domain access' implementation.

interesting fact:
-When I deploy the Jersey app and the UI app in the same tomcat server. it works well except on FireFox. it prompts me to sign-in again.
-CORS does not apply here because the api and the UI/ajax are on the same domain.

sample codes attached:
-ajax_angularJS.js
-JerseyRestfulApi.java
-web.xml
-CorsResponseFilter.java

thank you for your help
-Zak
web.xml
JerseyRestfulApi.java
CorsResponseFilter.java
ajax_angularJS.js.js

Daniel Doubrovkine

unread,
Jun 23, 2015, 2:10:19 PM6/23/15
to waffle...@googlegroups.com
Can you clarify what you mean by "you don't want to authenticate"? To get the username from the client on the server you need to authenticate or anyone can pretend to be anyone. Just curious what the use case is. 

With AJAX I think you need something like https://github.com/erlandranvinge/ntlm.js or maybe you just need the server to return the CORS headers to allow Ajax requests to authenticate:

Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: WWW-Authenticate


--
You received this message because you are subscribed to the Google Groups "waffle" group.
To unsubscribe from this group and stop receiving emails from it, send an email to waffle-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Zak Guler

unread,
Jun 23, 2015, 2:50:00 PM6/23/15
to waffle...@googlegroups.com
Daniel,
thank you for taking your time to look into this issue.
Can you clarify what you mean by "you don't want to authenticate"?:

Zak Guler

unread,
Jun 23, 2015, 3:17:22 PM6/23/15
to waffle...@googlegroups.com
sorry somehow I hit the send key before I finished typing my reply:

Daniel,
thank you for taking your time to look into this issue.
   -Can you clarify what you mean by "you don't want to authenticate"?:
    I meant that the user is already signed on and already authenticated when he logged into his computer.

   -Use case:
    >user logs into his/her machine.
    >starts the app at: www.AAA.com/myApp.html
    >the app will call jersey-restful api that is deployed on a different domain: http://ZZZ/ServiceCloud/ldap/user
    >Ajax will pass the request object with the api.
    >the '/user' api will call 'principaluser = request.getUserPrincipal().getName();' <==== [works great as long as the Jersey api and the UI app are deployed on the same server].
    >using the principal name, I get his/her credentials from LDAP and pass it back to the UI.

   -log from a working example (same domain):

12:36:41.706 [http-nio-8080-exec-8] DEBUG w.servlet.NegotiateSecurityFilter - GET /ServiceCloud/ldap/user, contentlength: -1
12:36:41.706 [http-nio-8080-exec-8] DEBUG w.s.s.NegotiateSecurityFilterProvider - authorization: <none>, ntlm post: false
12:36:41.706 [http-nio-8080-exec-8] DEBUG w.servlet.NegotiateSecurityFilter - previously authenticated Windows user: SOC\zguler
12:36:41.710 [http-nio-8080-exec-8] INFO  com.ssc.service.ServiceCloudResource - principaluser: SOC\zguler
12:36:41.710 [http-nio-8080-exec-8] INFO  com.ssc.service.ServiceCloudResource - accountName: zguler
I am in filter: CorsResponseFilter
12:37:21.353 [http-nio-8080-exec-3] DEBUG w.servlet.NegotiateSecurityFilter - GET /ServiceCloud/ldap/user, contentlength: -1
12:37:21.353 [http-nio-8080-exec-3] DEBUG w.servlet.NegotiateSecurityFilter - authorization required
12:38:37.132 [http-nio-8080-exec-2] DEBUG w.servlet.NegotiateSecurityFilter - GET /ServiceCloud/ldap/user, contentlength: -1
12:38:37.133 [http-nio-8080-exec-2] DEBUG w.s.s.NegotiateSecurityFilterProvider - authorization: <none>, ntlm post: false
12:38:37.133 [http-nio-8080-exec-2] DEBUG w.servlet.NegotiateSecurityFilter - previously authenticated Windows user: SOC\zguler
12:38:37.137 [http-nio-8080-exec-2] INFO  com.ssc.service.ServiceCloudResource - principaluser: SOC\zguler
12:38:37.137 [http-nio-8080-exec-2] INFO  com.ssc.service.ServiceCloudResource - accountName: zguler
I am in filter: CorsResponseFilter

   -log from a failed example (api in a defferent domain than the UI app):

13:06:20.927 [http-nio-8080-exec-4] DEBUG w.servlet.NegotiateSecurityFilter - GET /ServiceCloud/ldap/user, contentlength: -1
13:06:20.927 [http-nio-8080-exec-4] DEBUG w.servlet.NegotiateSecurityFilter - authorization required

    -regrading the use of NTLM.js:
     this may not work for my use case. it looks like I need to provide the user credentials again before I do the AJAX call:
         Ntlm.setCredentials('domain', 'username', 'password');
   the main reason I elected to use Waffle is to be able to get the principal name without having the user log in again.

I hope this makes sense. it seems that the issue is if Waffle can handle CORS !!! I hope there is a solution for this.
thanx,
-Zak

Daniel Doubrovkine

unread,
Jun 23, 2015, 4:02:47 PM6/23/15
to waffle...@googlegroups.com
I see, a user U logged in on client C talking to server S has to "authenticate". A client C can't just claim they are user U to server S without some kind of proof, that's authentication - Windows uses the Negotiate protocol (NTLM or Kerberos under the hood), which is what you see here. Even on the same machine when you use a browser to go to a local server it's as if you were doing this between two servers.

If the user and the app are in different domains it cannot work, you can't prove anything to the server, they know nothing about each-other.

If you provide credentials you're not doing Single-Sign-On (SSO), which defeats the whole purpose as you point out. It has to work without the username and password, and that can always work in the same domain on different machines.

 

Antony Lees

unread,
Nov 19, 2015, 9:59:28 AM11/19/15
to waffle
I have this exact same problem and have narrowed it down to waffle (or spring security, I'm not sure which) not negotiating correctly with the browser

The initial response contains the WWW-Authenticate header, but doesn't contain the token.  The browser then doesn't respond with the Authorize header, which I'm guessing (but could be wrong) is due to the malformed WWW-Authenticate

Anyone manage to come up with a solution to this?

Daniel Doubrovkine

unread,
Nov 20, 2015, 8:34:34 AM11/20/15
to waffle...@googlegroups.com
Antony, the browser shows a popup then, right? This isn't a malformed header, it means that the negotiation failed, aka the user doesn't have access or one of the other thousand things that could have gone wrong. Go through the usual troubleshooting, first - https://github.com/dblock/waffle/blob/master/Docs/Troubleshooting.md.
Reply all
Reply to author
Forward
0 new messages