[Kimchi-devel] [PATCH V5 0/5] Switch to a traditional login flow

Zhou Zheng Sheng zhshzhou at linux.vnet.ibm.com
Tue Jun 17 04:06:08 UTC 2014


on 2014/06/16 19:46, Yu Xin Huo wrote:
> On 6/16/2014 4:23 PM, Zhou Zheng Sheng wrote:
>> on 2014/06/16 15:53, Yu Xin Huo wrote:
>>> On 6/16/2014 11:33 AM, Zhou Zheng Sheng wrote:
>>>> on 2014/06/13 18:47, Yu Xin Huo wrote:
>>>>> On 6/13/2014 6:07 PM, Zhou Zheng Sheng wrote:
>>>>>> on 2014/06/13 17:57, Yu Xin Huo wrote:
>>>>>>> On 6/13/2014 5:45 PM, Zhou Zheng Sheng wrote:
>>>>>>>> So your point is the proposed alternatives is uglier than the current
>>>>>>>> one, and the current one can be improved.
>>>>>>>>
>>>>>>>> Firstly from the JS accessing browser history link you gave me, I
>>>>>>>> don't
>>>>>>>> see anywhere it says it's unreliable. The solution doesn't need to
>>>>>>>> inspect the history, it just back needs to go back.
>>>>>>>>
>>>>>>>> Secondly you think "refresh.html" is uglier than cookie. It's
>>>>>>>> actually
>>>>>>>> not. A "refresh.html" only affects the login process, but the current
>>>>>>>> cookie solution affects all requests and responses that is not
>>>>>>>> related
>>>>>>>> to login. The current solution works, but it is far from works well,
>>>>>>>> and
>>>>>>>> if you want to improve it by suppress sending the previous page
>>>>>>>> cookie
>>>>>>>> in AJAX requests and response, more hacks would be added in both
>>>>>>>> front-end and back-end. This is not improving step by step. To
>>>>>>>> improve
>>>>>>>> step by step, the original direction should be correct and effective,
>>>>>>>> but this is not.
>>>>>>> Again, there will always cookie back and forth between browser and web
>>>>>>> container. It is handled automatically by browser and web container.
>>>>>>> What make you uncomfortable is that piece of code at server side to
>>>>>>> get
>>>>>>> previousPage.
>>>>>> Yes, but the previousPage cookie is unnecessary regardless if it's
>>>>>> handled automatically or not. The alternative solutions we discussed
>>>>>> can
>>>>>> avoid this unnecessary handling, and restrict the login handling logic
>>>>>> only to a small region of code and runtime process.
>>>>> there are 2 alternative solutions you proposed:
>>>>>
>>>>> 1. brower history
>>>>>                   -- unreliable as I replied.
>>>> 1. You are correct
>>>>
>>>>> 2. internal redirect
>>>>>                   -- 1. make browser url mismatch its content, it is
>>>>> desirable to make browser url truly address it intended content.
>>>>>                      2. after login, server response back a refresh.html
>>>>> with javascript to reload browser, this refresh.html need to be pasted
>>>>> to browser to get that javascript to run.
>>>>>                           user will definitely perceive this page switch,
>>>>> make it a bad experience.
>>>>>                       3. Compare with a single cookie attribute, there
>>>>> are
>>>>> must more side effects.
>>>> 2. There are plenty of ways to improve internal redirect method and
>>>> eliminate the need for "refresh.html".
>>>>
>>>>    Option 2.1. Upon unauthenticated access, back-end internal redirects to
>>>> "login.html". The POST action of the form send the current page URI to
>>>> the back-end as well, then after the /login URI handler authenticates
>>>> the user, it fetches the "Referer" header of the request, and this
>>>> header contains the original page URL, then back-ends uses internal
>>>> redirect or HTTP 3xx redirect to present the original page content.
>>> "Referer" does not work. Please google search or try it yourself.
>> I tried it myself before I sent the previous mail, it works. The problem
>> is that intermediate proxy may change it, or the user can configure
>> firefox not sending it. It's not reliable, but it can served as the last
>> means to get the related page.
> 
> Checked all types of requests, "referer" is always below in my env.
> 
> 
> If "referer" can work, I truly like it very much, that will save us a lot of 
> complexity, can you paste a screen-shot of your env?
> 

What exactly environment do you want? Firefox about:config or the debug
screen?

>>
>>>>    Option 2.2. Upon unauthenticated access, back-end internal redirects to
>>>> "login.html". The form in the "login.html" contains a hidden input
>>>> indicating the current URI. Then the JS in "login.html" fills this
>>>> hidden input upon successfully loading the page. So the POST action of
>>>> the form send the current page URI to the back-end as well, then after
>>>> the /login URI handler authenticates the user, it uses internal or HTTP
>>>> 3xx redirect to lead the processing flow back to the original URI.
>>> If the first time I try to access kimchi with
>>> "https://xxx.xxx.xxx.xxx:8001/login.html", what will happen?
>> There is nohttps://xxx.xxx.xxx.xxx:8001/login.html, it is only served
>> through internal redirect. The user can not directly access it.
> For web resources at server side, static, dynamic, protected, unprotected, there 
> will always be a url addressable way to load it.
> For your design, it completely relies on browser url which is quite easy for 
> user to input anything.
> For fuzzing security testing or robustness testing, any malformed url maybe 
> tried to check server response.
> If user does input below, for your option 2.2, it will be a dead loop that user 
> will always see login page. Tester will be quite happy to found it.
> 
> "https://xxx.xxx.xxx.xxx:8001/login.html"
>

There are some possible methods to solve this problem.

Firstly, in the above method, there is a hidden input field
"PreviousPage", which is filled by JS with the current URI. Then in the
back-end, after successful /login handling, just before it redirects the
user back, it checks if "PreviousPage" is "login.html", if yes,
redirects to the front page, otherwise redirects to "PreviousPage".

Actually in back-end, it's also possible to restrict a page to be
accessed only fron internal redirection. There are two possible ways to
do this.
  a) Usually we use internal redirect as
internal_redirect("login.html"). Actually we can use
internal_redirect("login.html?from=internal"), then in login.html.tmpl,
it checks $data.from, if it is not from internal, it could hide the
content or uses JS to redirect the user to the front-page.
  b) A more elegant way is to configure "login.html" as follow.
  '/login.html':  {tools.kimchi_restrict_internal.on: True},
Then in the function kimchi_restrict_internal(), it checks if
kimchi.request.prev is empty. If it's empty, it is accessed directly,
and we can raise 404. If it's not empty, it is accessed from
InternalRedirect.

>>
>>>>    Option 2.3. Upon unauthenticated access, back-end internal redirects to
>>>> "login.html". "login.html" does not use traditional HTTP POST form,
>>>> instead, it uses /login API call to login using AJAX invocation, upon
>>>> successful login, "login.html" refreshes the page.
>>> how to differentiate first time login and session timeout?
>> Before internal redirection, back-end can check if it is first time
>> login or timeout, and sets an variable/title/label in the dynamic
>> rendered "login.html".
> I do not think there is a way to differentiate "user first time login" and 
> "session timeout" by internal redirect.
> Can you clarity?

If it's the first time user accesses Kimchi, back-end would create a new
session cookie. And Kimchi does not set cherrypy session timout,
instead, it expire the session by itself. This is because it needs to
differentiate robot requests from normal requests. So the back-end
actually knows if a session is created the first time or it's expired.

>>
>>>> Actually "softlayer.com" is using some means of internal redirection to
>>>> guide user to the previous page. You can try to open the following links.
>>>>     https://control.softlayer.com/account/invoices
>>>>     https://control.softlayer.com/account/orders
>>>> You'll notice it returns a plain login page, after login, it triggers a
>>>> refresh that the user doesn't notice at all.
>> What do you think of softlayer.com ?
> We have designed a complete, end to end "login/logout/user, pass wrong/session 
> timeout/preserve meaningful user context" experience.
> And figured out a technical solution to support it.
> If you do see any better user experience that softlayer delivered than our 
> current design. Feel free to point out.

If you really checked softlayer.com . It implements the things you
required. For example, if the user does not take action for some time,
it redirects the browser to the login page and says session timeout.

>>
>>>> The page switch only happens in login process. Though you state cookie
>>>> approach as "single cookie attribute", but it gets transferred in every
>>>> request and response even the AJAX ones. It's obvious which is more
>>>> evil. There is also an inevitable bug in cookie approach. Say the user
>>>> opens two firefox tabs, one is for VMs, the other is for StoragePool.
>>>> Once the session is expired, and the user login in VMs, it may lead the
>>>> user to StoragePools if StoragePools happens to be opened after VMs.
>>> Quite easy to be solved, I believe there will be an event notification
>>> when switching tab.
>> The event notification is in the front-end, how do you send it to back-end?
> front end can also set cookie.

Exactly, so why you have the back-end record the previous page? If you
are really staying with the cookie approach, we can create an common
html page to be included by other pages, sets the previous page cookie
whenever it gets loaded. It seems kimchi-ui.tmpl already serves as this
purpose. I'm not a front-end expert, you can correct me if I didn't
understand it right.

In fact the redirection can be done solely in the front-end. The
back-end has no interests in the previous page. The front-end can use
the HTM5 local storage feature. The front-end can record the current
page URI in the local storage (of cause except login.html), then in
login.html, it uses login API call to authenticate, then it fetches the
previous page from the local storage and go back to it. In this way we
avoid the complexity in back-end and avoid extra cookie in each AJAX
request and response.

>>
>>>> Moreover, I didn't see any investigation on how other WEB sites does
>>>> this. Though this is not my task, I just investigated softlayer to prove
>>>> my point. I suggest anyone who works on this firstly do some research on
>>>> the existing WEB sites and avoid re-inventing the wheel.
>>> Kimchi has its own problem and solution, others can be referenced, but
>>> not defined by them.
>> Yes. However I didn't said we should use the same mechanism as other
>> sites, but I said exactly we can refer them. The problem is that the
>> authors didn't referenced and analyzed other sites' solutions at all. At
>> least I didn't see them in the commit message, email, wiki or offline
>> discussion. Would you please tell me how many sites you referenced and
>> why none of the existing solutions can not be used? Or you can just send
>> me a link of you previous analysis.
> I do not believe all web sites use internal-redirect to do login, why you only 
> reference a website that use internal-redirect?
> If I do want to reference others, I will list the top 10 web sites in this world 
> and check how they implement it.
> 
> Now, only hotmail is available, checked that it is not internal-redirect
> 
> 
> In an enterprise environment, all applications, systems need to be integrated to 
> enable single access control, single sign on.
> The whole login process of all apps is delegated to a central access manager, 
> how can internal-redirect work in this case?
> 

Then you can state your investigation on how top 10 sites does login,
and checks if they uses the "previous page" cookie solution. I don't
believe top 10 sites uses "previous page" cookie solution for just a
login handling.

Furthermore, there is nothing prevent internal redirect solution to be
integrated with single sign on or ldap.

For example, whether or not the login.html is served by internal
redirect, the actual auth handling is in Kimchi back-end. The Kimchi
login API call or login POST handler can pass the auth to an LDAP server.

I also has done some work on single sign on before. Usually the single
sign on is on the different URI of the login.html. When the browser gets
a token from the central access manager, it can be redirected to
https://kimchi:8001/sso?token=XXXX. Then the sso handler of Kimchi can
check the token with the central manager or check the token in the
back-end which is sets by the central manager in other means.

>>
>>>>>>> Both client javascript and web container can set cookie.
>>>>>>> the previsousPage can also be set with javascript in client side,
>>>>>>> each time user go to a new tab, there is a callback, in the callback,
>>>>>>> previousPage can be set into cookie.
>>>>>> But the previousPage cookie is still carried forth and back in normal
>>>>>> requests, which is absolute redundant information, not to mention the
>>>>>> troubles it causes when the user opens two firefox tabs accessing
>>>>>> different page of Kimchi.
>>>>> Cookie will always be sent back and forth regardless of our previousPage
>>>>> url.
>>>>> What trouble you mean when multiple browser tabs, please clarify.
>>>>>
>>>>>>>> on 2014/06/13 17:24, Yu Xin Huo wrote:
>>>>>>>>> First of all, what you are complaining about is a pretty, pretty
>>>>>>>>> small
>>>>>>>>> fraction of the overall login solution.
>>>>>>>>> For that fraction, the design is to back to the original url after
>>>>>>>>> user
>>>>>>>>> login from a session timeout.
>>>>>>>>> Shaohe's current implementation works well. what zhengsheng means is
>>>>>>>>> about how to improve it.
>>>>>>>>>
>>>>>>>>> On 6/13/2014 3:12 PM, Zhou Zheng Sheng wrote:
>>>>>>>>>> If I remembered correctly, Shao He, Yu Xin and me had several long
>>>>>>>>>> talks
>>>>>>>>>> on the login design. This solution is not the solution we
>>>>>>>>>> agreed, and
>>>>>>>>>> all of us thought that this solution is ugly and obviously
>>>>>>>>>> should be
>>>>>>>>>> improved.
>>>>>>>>> We have ever discussed several options, but we have not converged
>>>>>>>>> to a
>>>>>>>>> certain one.
>>>>>>>>> Let me continue to read to see what the 'ugly' you mean.
>>>>>>>>>
>>>>>>>>> This solution works very well, it can always be improved.
>>>>>>>>>> The problem is on how it redirects the user back to the previous
>>>>>>>>>> page
>>>>>>>>>> after login. In this patch, the back-end has to intercepts each
>>>>>>>>>> access
>>>>>>>>>> to any of the ".html" page, and sets
>>>>>>>>>>        cookie['lastPage'] = current page URI,
>>>>>>>>>> and return it to front-end, then the front-end sends this cookie to
>>>>>>>>>> back-end in every query, including AJAX query. When the session
>>>>>>>>>> expires,
>>>>>>>>>> the back-end redirects the front-end to a login page, after login
>>>>>>>>>> successfully, the back-end gets cookie['lastPage'], at last,
>>>>>>>>>> redirect
>>>>>>>>>> the user to the last page.
>>>>>>>>>>
>>>>>>>>>> Just to implement returning to the previous page afte login, the
>>>>>>>>>> back-end has to intercept each '.html' access and sets cookie, and
>>>>>>>>>> the
>>>>>>>>>> front-end has to send the cookie in each request including AJAX
>>>>>>>>>> ones.
>>>>>>>>> Handling cookie back and forth is done by browser and web container.
>>>>>>>>> There will be always cookie, this is not an additional overhead.
>>>>>>>>> What shaohe does is only to get the current tab url. That is a quite
>>>>>>>>> small amount of code.
>>>>>>>>>> So in the last talk we agreed that a simpler and more effective
>>>>>>>>>> solution
>>>>>>>>>> should be used. We at least have two alternative solutions.
>>>>>>>>>>
>>>>>>>>>> 1. When session is expired, we redirect the user to login.html.
>>>>>>>>>> After
>>>>>>>>>> login successfully, the JS script in the front-end asks the
>>>>>>>>>> browser to
>>>>>>>>>> go back to the previous page. Since the browser keeps a stack of
>>>>>>>>>> page
>>>>>>>>>> histories, it should be easy to do this.
>>>>>>>>> This is server side redirect after form is submitted, at that time,
>>>>>>>>> client side has no code to run.
>>>>>>>>> Server side redirect browser directly to last page in login
>>>>>>>>> response,
>>>>>>>>> quite straight-forward.
>>>>>>>>>
>>>>>>>>> I do not think brower history will be a reliable solution.
>>>>>>>>> http://www.w3schools.com/js/js_window_history.asp
>>>>>>>>>> 2. When the back-end detects the session is expired or the user
>>>>>>>>>> hasn't
>>>>>>>>>> login yet, it uses internal redirect to present the "login.html".
>>>>>>>>>> From
>>>>>>>>>> the front-end point of view, an unauthenticated access to "GET
>>>>>>>>>> #tabs/vms.html" returns "login.html". After the user input his/her
>>>>>>>>>> password in the "login.html" and click "login", the back-end
>>>>>>>>>> receives
>>>>>>>>>> the request, if the password is correct, it returns a
>>>>>>>>>> "refresh.html". In
>>>>>>>>>> "refresh.html" there is actually a small JS code to ask the
>>>>>>>>>> browser to
>>>>>>>>>> refresh the page. Since we are using internal redirect all the
>>>>>>>>>> time,
>>>>>>>>>> the
>>>>>>>>>> page URI in the browser remains "#tabs/vms.html", so after the
>>>>>>>>>> login,
>>>>>>>>>> just refreshing the page would lead user to the real
>>>>>>>>>> "vms.html.tmpl".
>>>>>>>>>>
>>>>>>>>>> In the above two solutions, no ugly cookie is needed for each
>>>>>>>>>> request
>>>>>>>>>> and response, and the back-end doesn't have to intercept each
>>>>>>>>>> ".html"
>>>>>>>>>> access, but just has to intercept each unauthenticated access.
>>>>>>>>> internal redirect will make browser url mismatch with the content.
>>>>>>>>> the current design will always keep url address its intended
>>>>>>>>> content,
>>>>>>>>> this is a virtue over internal redirect we should pursue.
>>>>>>>>>
>>>>>>>>> The ugly cookie is removed, but introduced *a much uglier*
>>>>>>>>> "refresh.html" and code in that html.
>>>>>>>>> To me, it is much more complicated.
>>>>>>>>>> I don't know why Yu Xin and Shao He sent the to-be-abandoned
>>>>>>>>>> solution
>>>>>>>>>> again to the mailing list. Patches were sent on 20:00 Chinese local
>>>>>>>>>> time, the patches got merged in 05:00 Chinese local time in the
>>>>>>>>>> next
>>>>>>>>>> day. There is no other developer gets CCed. There is no
>>>>>>>>>> reviewed-by.
>>>>>>>>> This is not to-be-abandoned solution. Adam, Aline, Shao He and I
>>>>>>>>> have
>>>>>>>>> discussed this in a team meeting.
>>>>>>>>> It is sent to mail list. all people subscribed to mail list should
>>>>>>>>> get it.
>>>>>>>>> It is already V5, it is reviewed enough.
>>>>>>>>>> After talked to Shao He this morning, he told me that we
>>>>>>>>>> determined to
>>>>>>>>>> defer this feature/task to seek a better solution. Shao He told me
>>>>>>>>>> that
>>>>>>>>>> they sent the patch as RFC, not aim to be a final solution.
>>>>>>>>>> However it
>>>>>>>>>> is a big misleading to other developers because there is no RFC in
>>>>>>>>>> the
>>>>>>>>>> patch title. There is even no reviewed-by. Is there any reason to
>>>>>>>>>> merge
>>>>>>>>>> it so hurry?
>>>>>>>>> This is already V5, how can it be an RFC?
>>>>>>>>>> If there was any time and task pressure, I think as an open source
>>>>>>>>>> project, the progress should have some flexibility. We should not
>>>>>>>>>> write
>>>>>>>>>> code for a known broken solution, while there is obvious
>>>>>>>>>> alternative
>>>>>>>>>> solutions. This is very different from incremental development. In
>>>>>>>>>> incremental development, the direction and the solution is
>>>>>>>>>> correct, we
>>>>>>>>>> just completes the missing pieces step by step. In this case, the
>>>>>>>>>> solution and the framework itself is not so effective. Once it's
>>>>>>>>>> merged,
>>>>>>>>>> we started to rely on this, and changing and improving it would be
>>>>>>>>>> much
>>>>>>>>>> harder.
>>>>>>>>> Speed will always be most key to succeed for any organization.
>>>>>>>>> There is nothing broken, it works well.
>>>>>>>>> Improvement will never stop.
>>>>>>>>>
>>>>>>>>> Again, the overall solution is discussed across whole team in one
>>>>>>>>> of the
>>>>>>>>> Wed's team meeting.
>>>>>>>>> Cookie is the best way to store previousPage to reserve user
>>>>>>>>> context. If
>>>>>>>>> anyone see a better way than cookie for this issue, welcome to
>>>>>>>>> discuss
>>>>>>>>> with me.
>>>>>>>>>
>>>>>>>>> As zhengsheng point out, we need to try to improve that small bit of
>>>>>>>>> code to store previousPage into cookie. but again, it works well
>>>>>>>>> currently.
>>>>>>>>> But obviously, that is far from a justification to stop this patch
>>>>>>>>> from
>>>>>>>>> being merged.
>>>>>>>>>> on 2014/06/13 05:50, Aline Manera wrote:
>>>>>>>>>>> Applied. Thanks.
>>>>>>>>>>>
>>>>>>>>>>> Regards,
>>>>>>>>>>>
>>>>>>>>>>> Aline Manera
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Kimchi-devel mailing list
>>>>>>>>>>> Kimchi-devel at ovirt.org
>>>>>>>>>>> http://lists.ovirt.org/mailman/listinfo/kimchi-devel
>>>>>>>>>>>
>>>




More information about the Kimchi-devel mailing list