Bug 958874 - [REST-API] Support passing auth information without having to use HTTP Authorization header
Summary: [REST-API] Support passing auth information without having to use HTTP Author...
Keywords:
Status: CLOSED DEFERRED
Alias: None
Product: Red Hat Enterprise Virtualization Manager
Classification: Red Hat
Component: ovirt-engine-restapi
Version: 3.3.0
Hardware: Unspecified
OS: Unspecified
unspecified
medium
Target Milestone: ---
: 3.4.0
Assignee: Michael Pasternak
QA Contact: Elena
URL:
Whiteboard: infra
Depends On: 958861
Blocks:
TreeView+ depends on / blocked
 
Reported: 2013-05-02 14:59 UTC by Michael Pasternak
Modified: 2016-02-10 19:36 UTC (History)
13 users (show)

Fixed In Version:
Doc Type: Enhancement
Doc Text:
Clone Of: 958861
Environment:
Last Closed: 2013-10-07 08:20:15 UTC
oVirt Team: Infra
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)

Description Michael Pasternak 2013-05-02 14:59:33 UTC
+++ This bug was initially created as a clone of Bug #958861 +++

The purpose of this RFE is to improve REST API integration in web applications (running JavaScript in web browser).

Unlike traditional HTTP clients, web applications don't have full control over HTTP request/response processing. Instead, the web browser is the "proxy" between JavaScript trying to send/receive requests, and the actual web server that serves these requests. Web browsers typically implement some standard conventions and behaviors on top of request/response processing, one of them is HTTP Authorization header behavior described below.

Since REST API expects (HTTP Basic) auth information to be passed using HTTP Authorization header, web application trying to integrate with REST API must set this header. However, after setting HTTP Authorization header by web application (i.e. via XmlHttpRequest) for the first request, the browser *remembers* this header and always sends it for subsequent requests, until the browser window is closed. Because of this, implementing logout functionality in web application is really hard when using HTTP Authorization header.

Furthermore, web application cannot take advantage of REST API session mechanism [http://wiki.ovirt.org/Features/RESTSessionManagement] because this mechanism expects HTTP Authorization header to be sent by client only for the *first* (create session) request, which is impossible due to browser-specific HTTP Authorization header handling as mentioned above.

To summarize, web application doesn't have full control over HTTP Authorization header, so REST API should provide some alternative to pass auth information.

Proposed solution:
Client (web application) can use "Prefer: custom-auth-header" to indicate preference of using custom HTTP header instead of standard HTTP Authorization header.

For example:

    GET /api HTTP/1.1
    Host: ovirt-engine
    Prefer: custom-auth-header
    Custom-Authorization: xxx

Example that works with REST API session mechanism (create session):

    GET /api HTTP/1.1
    Host: ovirt-engine
    Prefer: persistent-auth,custom-auth-header
    Custom-Authorization: xxx

Comment 1 Einav Cohen 2013-05-02 15:10:40 UTC
adding reference to the first e-mail in the related engine-devel thread:
http://lists.ovirt.org/pipermail/engine-devel/2013-April/004235.html

Comment 2 Alon Bar-Lev 2013-05-05 08:14:32 UTC
BTW: I don't understand why we discussing this in downstream and not upstream (bug#958861)...

Regardless of this specific RFE I would like to write that I don't like the REST API session mechanism [http://wiki.ovirt.org/Features/RESTSessionManagement] solution, as it relays on cookies and not explicit API interaction. I would have expected a 'ticket' to be retrieved and that 'ticket' to be disconnected from the application server objects. Although we can refer the 'cookie' as a ticket, however the requirement to parse it should not be required, there be a conflict between two separate applications running on same server, and there may be a problem to transfer credentials between servers.

If we modify authentication we should support more authentication types, at least SPNEGO.

In order to allow SPNEGO and other authentication mechanisms, we better force people to use single URI to perform the login and return authenticated 'ticket' to continue interaction with application. This will be much simpler implementation at the api side and much more efficient, and as we are discussion application-to-application interaction there should be no user experience visible issues.

What I recommend is purely applicative rest login command...
---
Input: authentication type, authentication credentials
    authentication=http
    authentication=password
    credentials:
        user=user
        password=password
    [OPTIONALLY] HTTP authentication headers
Output:
    ticket
    ticket issue time (required to avoid clock sync)
    ticket expiration time
Logic:
if authentication is http, use http authentication headers to establish user authentication. This will allow future SSO.
if authentication is password, use embedded credentials.
---

For every other rest call add http header:
    oVirt-Authentication-Ticket: <ticket>

The backend side will attach the correct security context to the action if the header is received.

No need for the prefer mechanism nor multiple authentications. It should be easy for javascript implementation to perform the authentication via the designated URI, and then pass the ticket if not expired, when expired to perform re-authentication with or without involving the user.

Comment 3 Michael Pasternak 2013-05-06 06:46:31 UTC
this is doesn't have to be discussed at Bugzilla at all, here [1] is a upstream
thread.

[1] http://lists.ovirt.org/pipermail/engine-devel/2013-May/004489.html

Comment 4 Itamar Heim 2013-06-10 11:37:12 UTC
what will happen when we want to add things like kerberos authentication?

Comment 5 Michael Pasternak 2013-06-10 12:28:12 UTC
Vojtech,

You should be able accessing /api session cookie via "Cross-Origin Resource Sharing", from the javascript, please review spec [1] for this,

are there any other restrictions besides this one?
(assume omit of the auth. header can be easily solved)

[1] http://www.w3.org/TR/cors/

Comment 6 Vojtech Szocs 2013-06-10 16:31:32 UTC
(In reply to Michael Pasternak from comment #5)
> Vojtech,
> 
> You should be able accessing /api session cookie via "Cross-Origin Resource
> Sharing", from the javascript, please review spec [1] for this,
> 
> are there any other restrictions besides this one?
> (assume omit of the auth. header can be easily solved)
> 
> [1] http://www.w3.org/TR/cors/

Yes, CORS is indeed an option here, however I'm not sure if JBoss AS7 supports CORS spec [2]. In general, CORS implies that both browser and server support the spec. In addition, CORS is about sharing resources between different origins - in our case, WebAdmin and REST API are both on same origin, but browser enforces "same-cookie-path" restriction anyway, I'm not sure it would solve our problem, but it's worth a try.

Another approach is to simply introduce another (custom, non-Cookie) header and instruct AS7 to recognize this header, in addition to recognizing JSESSIONID cookie. Doing this by customizing bundled Tomcat's Manager seems to be quite problematic in AS7 [3]. However, [4] shows that if we somehow get a reference to default Manager, we can do "createSession(sessionId)" via some custom filter, unless I miss something.

[2] https://github.com/wildfly/wildfly/pull/4349
[3] https://community.jboss.org/thread/220840
[4] http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/Manager.html

Comment 7 Vojtech Szocs 2013-06-10 16:41:21 UTC
(In reply to Itamar Heim from comment #4)
> what will happen when we want to add things like kerberos authentication?

In that case we'll have to revisit current auth strategy (HTTP Basic Auth) and extend/modify it to support Kerberos auth.

Comment 9 Itamar Heim 2013-06-11 08:26:51 UTC
(In reply to vszocs from comment #6)
...
> Another approach is to simply introduce another (custom, non-Cookie) header
> and instruct AS7 to recognize this header, in addition to recognizing
> JSESSIONID cookie. Doing this by customizing bundled Tomcat's Manager seems
> to be quite problematic in AS7 [3]. However, [4] shows that if we somehow
> get a reference to default Manager, we can do "createSession(sessionId)" via
> some custom filter, unless I miss something.
> 

another approach is with the revamping of the URI's, to also map /api under /webadmin/api, so you won't have an issue with same-path policy issues.

Comment 10 Vojtech Szocs 2013-06-11 09:15:20 UTC
(In reply to Itamar Heim from comment #9)
> another approach is with the revamping of the URI's, to also map /api under
> /webadmin/api, so you won't have an issue with same-path policy issues.

Good idea, this is definitely worth a try, but we have to make sure that:
- /webadmin/api properly redirects to /api
- REST API sets its cookie according to current request path, i.e. /webadmin/api

I'd suggest to start with this one, putting this on my task list since /webadmin/* means GWT/Frontend part.

Comment 11 Itamar Heim 2013-06-11 09:18:21 UTC
since api has relative uri's, API may need to be adjusted to return entities based on relative URIs as well (not that code writers necessarily write their code correctly and probably make some assumptions on the URLs).

(while at it, reminder that part of the URI change is about making webadmin also relocateable to be under /ovirt-engine or something like that)

Comment 12 Vojtech Szocs 2013-06-11 10:02:38 UTC
(In reply to Itamar Heim from comment #11)
> since api has relative uri's, API may need to be adjusted to return entities
> based on relative URIs as well (not that code writers necessarily write
> their code correctly and probably make some assumptions on the URLs).
> 
> (while at it, reminder that part of the URI change is about making webadmin
> also relocateable to be under /ovirt-engine or something like that)

In general, web application code shouldn't rely on (or make any assumptions of) specific value of its own context root, i.e. /api

For example, if we decide to change context root of REST API from /api to /foo then REST API itself should still work properly at /foo. Of course, we'd still have to modify code that uses REST API to reflect new context root.

Comment 13 Juan Hernández 2013-06-11 11:31:47 UTC
I believe that the REST API application doesn't rely or makes assumptions about the value of the context root. If you deploy it to /foo it will start to generate paths starting with /foo, as it should.

The problem is that if you redirect requests from /api to /webadmin/api (with the application server or with the web server, doesn't matter) the application will still, rightfully, generate paths starting with /api instead of /webadmin/api, because the application doesn't have any knowledge that the requests are being re-directed.

If we want to support these re-directions then we need to modify the application so that it takes the /webadmin/api (or /foo, or whatever) from some place other than the request itself, we will probably need to put some logic in the configuration of the application server (or a valve in the application server) that in addition to re-direct adds a header to indicate what was the path of the original request. The REST API application will need then to generate paths from this header if available, or from the context path where the application is deployed if the header isn't provided.

Comment 14 Vojtech Szocs 2013-06-11 12:54:31 UTC
Thanks Juan, I agree that with redirects, REST API should contain logic to adjust resource paths accordingly.

[Our original motivation was to do /webadmin/api -> /api redirect in order for REST API's JSESSIONID cookie to be set for path=/webadmin/api which is readable by WebAdmin/JavaScript code, unlike path=/api]

It would be great if a custom header containing original request path would be added automatically via JBoss or Apache as part of the redirect. REST API could pick up this header and adjust resource paths accordingly, but more importantly, adjust JSESSIONID cookie path according to this header.

Comment 15 Jason Greene 2013-07-18 17:24:39 UTC
The XHR behavior you observed looks like a bug:
https://bugzilla.mozilla.org/show_bug.cgi?id=654348

Have you tested various browser combinations?

Comment 16 Alon Bar-Lev 2013-08-31 06:40:18 UTC
See discussion "[REST-API] Support passing auth information without having to use HTTP Authorization header #958874"[1]

[1] http://comments.gmane.org/gmane.comp.emulators.ovirt.engine.devel/4028

Comment 17 Barak 2013-10-07 08:20:15 UTC

*** This bug has been marked as a duplicate of bug 1009843 ***

Comment 18 Michael Pasternak 2013-10-16 11:53:39 UTC
fixing Bug 1007444 eliminated the need in this type of authentication,
for more details see [1].

[1] https://bugzilla.redhat.com/show_bug.cgi?id=958861#c3


Note You need to log in before you can comment on or make changes to this bug.