How do I get the return URL working properly again after downloading a login page from Azure ACS?

▼魔方 西西 提交于 2019-12-12 15:46:57

问题


The Azure Training Kit includes a lab titled "IntroToACS2". In it you create a WebRole and enable ACS so that you can login using your Google, Live, or Yahoo id. The second part of the lab takes you through the process of downloading an example login page from ACS so that you can use customize it to match the style of your site.

Before doing this last part, deep linking was working fine. Meaning: I could request a secure page such as http://localhost/acsdemo/securepage.aspx and ACS would intercept the request, redirect me to the login page and then return me to http://localhost/acsdemo/securepage.aspx, but now it just returns me to the default page http://localhost/acsdemo/default.aspx.

What needs to be done get deep links working again after downloading a login page from Azure ACS?


回答1:


The return URL for securepage.aspx is normally stored in a context parameter when you redirect for login. In both the ACS hosted login page, and the custom downloadable one, there is javascript that queries ACS for the identity provider list, and then generates the login links for each IP. The ACS hosted version is special in that it will also collect the wctx given to it and customize each IP login url to preserve this context. This way ACS knows where to redirect the user back to when authentication is complete.

The custom downloadable login page however doesn't preserve this context, which is why you get this behavior, ACS simply redirects you to the Return URL you specified in your ACS configuration, in this case default.aspx.

But you can change your custom login page to insert this missing parameter. The complication here is that this context is communicated differently depending on the protocol. For LiveID (WS-Federation) the incoming wctx can be re-transmitted in the outgoing wctx in the liveID login link, but in a boxed form "cx". Below is some javascript I added to the CreateIdentityProviderButton() function that achieves this.

    ...

    //Creates a stylized link to an identity provider's login page
    function CreateIdentityProviderButton(identityProvider) {

        // Some code I stole from fellow stackoverflow  member for extracting query parameters =)
        var urlParams = {};
        (function () {
                var e,
                    a = /\+/g,  // Regex for replacing addition symbol with a space
                    r = /([^&=]+)=?([^&]*)/g,
                    d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
                    q = window.location.search.substring(1);

                while (e = r.exec(q))
                    urlParams[d(e[1])] = d(e[2]);
            })();

        var cx = "&cx=" + encodeURIComponent(urlParams.wctx);
        var idpList = document.getElementById("IdentityProvidersList");
        var button = document.createElement("button");
        button.setAttribute("name", identityProvider.Name);
        button.setAttribute("id", identityProvider.LoginUrl + encodeURIComponent(cx));

        ...

For Yahoo or Google (OpenID) this context is returned in openid.return_to, as a "context" query parameter. So in your login page you could similarly edit the openid.return_to in your login link like so:

... openid.return_to=https://youracstenant.accesscontrol.windows.net:443/v2/openid?context=<value of the wctx extracted from javascript above> ...

You could write code to special case your login link based on what identity provider name you see in the ACS IdentityProvider.js json response.




回答2:


Here is how I got deeplinks working:

After downloading the sample login page from Azure, I copied its content into an aspx page called Login.aspx then added some C# code to update the reply_to address.

Find the script tag in Login.aspx and change '&reply_to=' to '&reply_to=<%=returnUrl%>' as shown below:

<script src="https://sample.accesscontrol.windows.net:443/v2/metadata/IdentityProviders.js?protocol=wsfederation&realm=http%3a%2f%2flocalhost%2fSample&reply_to=<%=returnUrl%>&context=&request_id=&version=1.0&callback=ShowSigninPage" type="text/javascript"></script>

Next, add the following code to Login.aspx.cs

using System;
using System.Web;

namespace Sample
{
    public partial class Login : System.Web.UI.Page
    {
        protected string returnUrl = "";
        protected void Page_Load(object sender, EventArgs e)
        {            
            var wctx = Request.QueryString["wctx"];
            var wreply = Request.QueryString["wreply"];
            if (wctx == null || wreply == null) return;
            var queryString = HttpUtility.ParseQueryString(wctx);
            var ru = queryString["ru"];
            if (ru == null) return;
            returnUrl = Server.UrlEncode(wreply + ru);
        }
    }
}

Now, here is how to create your login link/button:

Don't create a link like this because it won't work:

<a href="Login.aspx">Login</a>

Instead create a deep link to a page that can only be accessed after authentication like this:

<a href="SecurePage.aspx">Login</a>

I have only tested this with Google Id so far, but I expect it will work for the other identity providers.



来源:https://stackoverflow.com/questions/9927518/how-do-i-get-the-return-url-working-properly-again-after-downloading-a-login-pag

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!