WAAD, OAuth and Javascript

4 במרץ 2014

no comments

As you probably know Microsoft released AAL (Windows Azure AD Authentication Library for .NET) which is a great API for interacting with WAAD and implement the OAuth code flow. This API is extremely easy to use yet it works only for single threaded (STA) clients. It means that you can use it in a console application or windows store app but not in a browser.

The scenario in which a client wants to call a web api in a SPA (Single Page Application) looks very interesting so I searched for an JavaScript SDK for WAAD but I could not find any.

The OAuth 2.0 code flow is not that complicated to implement so I started to implement my own SDK …

I created two applications in WAAD and configured the redirect uris accordingly.
1. A web application (for my web api)
2. A native application for my client (that can be any sort of app)

The scenario is a SPA client so I created a simple Single Page Application.
I created a crafted link in one of the pages that looks something like this.

<a id="OAuth" href='https://login.windows.net/xxx.onmicrosoft.com/oauth2/authorize?response_type=code&resource=http://localhost:15770/&client_id=5ebcbed4-594f-4a20-94d7-07b9ca1bc4ff&redirect_uri=http://localhost:15770/aad/index'>login</a>

As you can see there is nothing special here. This is the first OAuth request in the code flow.
Now starts the fun part:
I created a JQuery script that will extract the authorization code that should return from WAAD and exchange it with an access token.

$(function () {
    var accessToken;
    var code = GetURLParameter("code");
    if (code != null) {
        tokenRequest = {
            grant_type: "authorization_code",
            code: code,
            client_id: "5ebcbed4-594f-4a20-94d7-07b9ca1bc4ff",
            redirect_uri: "http://localhost:15770/aad/tokenhandler"
        };

        $.ajax({
            url: "https://login.windows.net/xxx.onmicrosoft.com/oauth2/token",
            type: "POST",
            data: tokenRequest,
            dataType: "json",
            success: function (response, textStatus, jqXHR) {
                accessToken = response.access_token;
            },
            error: function (xhr, err) {
                alert('problem');
            }
        });
     }
});

but it did not work !!!

The reason is simple: WAAD does not support CORS !!! and there is no way I can override that.
So I created my own handler in my web site that will call WAAD and get the access token for me.

public class OAuthResquest
{
    public string grant_type { get; set; }
    public string code { get; set; }
    public string client_id { get; set; }
    public string redirect_uri { get; set; }
}  

public class AADController : Controller
{
    ...
    // GET: /AAD/GetAccessToken
    public ActionResult tokenhandler()
    {
        return View("tokenhandler");
    }

    // POST: /AAD/GetAccessToken
    [HttpPost]
    public string TokenHandler(OAuthResquest request)
    {
        string accessToken = string.Empty;
        HttpClient client = new HttpClient();      

        var postData = new List<KeyValuePair<string, string>>();
        postData.Add(new KeyValuePair<string, string>("grant_type", request.grant_type));
        postData.Add(new KeyValuePair<string, string>("code", request.code));
        postData.Add(new KeyValuePair<string, string>("client_id", request.client_id));
        postData.Add(new KeyValuePair<string, string>("redirect_uri", request.redirect_uri));
        HttpContent content = new FormUrlEncodedContent(postData); 

        var response = client.PostAsync(new Uri
("https://login.windows.net/xxx.onmicrosoft.com/oauth2/token"), content).Result; if (response.IsSuccessStatusCode) { if (response.Content != null) accessToken = response.Content.ReadAsStringAsync().Result; } Response.Cookies.Add(new HttpCookie("accessToken", accessToken)); return accessToken; } }

Now I will call my handler with the code and all the details required to get the access token.

$(function() {
    var accessToken;
    var code = GetURLParameter("code");
    if (code != null) {
        tokenRequest = {
            grant_type: "authorization_code",
            code: code,
            client_id: "5ebcbed4-594f-4a20-94d7-07b9ca1bc4ff",
            redirect_uri: "http://localhost:15770/aad/index"
        };

        $.ajax({
            url: "/aad/TokenHandler",
            type: "POST",
            data: tokenRequest,
            dataType: "json",
            success: function(response, textStatus, jqXHR) {
                accessToken = response.access_token;
                alert("Now you can call the web api !!!");
            },
            error: function(xhr, err) {
                 alert("problem !!!");
            }
        });
    }

Guess what, It works !!!

So to summarize:
WAAD had no Java Script SDK equivalent to AAL.
WAAD does not support CORS so you cannot implement the code flow (or any other flow) in the browser (in javascript).
The solution is to create an action on the server side that will execute the final call and return the token.

Hope this helps

Manu

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*