RobVious
RobVious

Reputation: 12925

Windows phone 8 development & WebAPI - authenticating via forms auth?

I'm building an API with WebAPI that will accept authentication information over SSL via HTTPS from the web browser client. The web browser uses forms authentication and requires HTTPS so it can securely sent username/password to the API endpoint. My API uses Websecurity.Login() and Websecurity.Logout() to handle authentication for the web client.

How would this get handled in a WP8 application / Universal app built with WinJS? Can I do the same thing - send login / registration credentials over HTTPS and use Websecurity to handle forms auth?

Here's how my WebAPI is currently set up for auth:

public HttpResponseMessage LogIn(LoginModel model)
{
    if (ModelState.IsValid)
    {
        if (User.Identity.IsAuthenticated)
        {
            return Request.CreateResponse(HttpStatusCode.Conflict, "already logged in.");
        }

        if (WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            return Request.CreateResponse(HttpStatusCode.OK, "logged in successfully");
        }
        else
        {
            return new HttpResponseMessage(HttpStatusCode.Unauthorized);
        }
    }

    // If we got this far, something failed
    return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}

public HttpResponseMessage LogOut()
{
    if (User.Identity.IsAuthenticated)
    {
        WebSecurity.Logout();
        return Request.CreateResponse(HttpStatusCode.OK, "logged out successfully.");
    }

    return Request.CreateResponse(HttpStatusCode.Conflict, "already done.");
}

Is this approach compatible with WP8 or other native mobile app development authentication?

Upvotes: 7

Views: 931

Answers (2)

fuzzybear
fuzzybear

Reputation: 2405

I use WebApi via JS to do forms auth , this is how with CORS

decorate controller (if you need to use CORS) (think you may need a nuget package for this).

   [EnableCors(origins: "*", headers: "*", methods: "*")]

Once your happy with credentials set cookie

   FormsAuthentication.SetAuthCookie

This is the Ajax for the HTML page,

$.ajax({
    type: 'Post',

    url: 'http://' + api + '/?alloworigin=true',
    data: { Username: "test", Password: "test12" },
    dataType: 'json',
    xhrFields: {
        withCredentials: true
    },
    success: function(data) {
        var x = data;
    },
    error: function(msg) {
        alert( msg.responsetext);
    }
});

Then any auth, decorated controller can be accessed, the cookie is then sent with every request

[Authorize]

shout if you have any questions.

Microsoft_Press_eBook_Programming_Windows_8_Apps_HTML_CSS_JavaScript_2E_PDF.pdf

http://aka.ms/611111pdf has some details on passing XHR with WinJS

Upvotes: 0

Wiktor Zychla
Wiktor Zychla

Reputation: 48279

It would definitely work, assuming that consecutive requests carry the cookie that is appended to the very first request to the Login action.

In case of a browser app that uses ajax this works out of the box as consecutive ajax requests carry all cookies issued by the same domain and appended in the current browser session.

In case of a native application this could be tricker because it means that the same client proxy instance would have to be used or you find a way to have a temporary local storage for authentication cookies and append these cookies to every request.

However, there is a potential drawback of this request: you assume that the login method can use the login/password in an active scenario to produce forms cookie. And this isn't always as simple as that.

This is because your site can potentially be federated with an external identity provider (ADFS, Azure Active Directory, Google, Facebook, whatever) so that the actual authentication takes place in another website and your website only gets the response that conforms to the single sign on protocol used (OAuth2, WS-Federation).

In such case, there is really no easy way to use the pair login/password at the server side to get the identity of the user.

A workaround in such case, where the identity provider is unknown, is to host the webbrowser control (if possible) and let it perform the passive authentication scenario - which means that you navigate to the application page and let the web browser control automatically 302 to the login page, no matter how many redirects it takes. Then, user provides credentials at the provider page and the web browser redirects all the way back to your application and this is where you catch the identity at the server side, close the web browser control and somehow (depending on the actual web browser host) read the authentication cookie so that you can attach it to further requests.

Sounds tricky, but we have found some federation scenarios where actual SSO protocols between parties were not guaranteed and such simulation of the passive scenario from within the hosted web browser was the only reliable way.

Upvotes: 2

Related Questions