ASP.NET WebAPI Security 5: JavaScript Clients
- by Your DisplayName here!
All samples I showed in my last post were in C#. Christian contributed
another client sample in some strange language that is supposed to work well in browsers
;)
JavaScript client scenarios
There are two fundamental scenarios when it comes to JavaScript clients.
The most common is probably that the JS code is originating from the same web application
that also contains the web APIs. Think a web page that does some AJAX style callbacks
to an API that belongs to that web app – Validation, data access etc. come to mind.
Single page apps often fall in that category.
The good news here is that this scenario just works. The typical course of events
is that the user first logs on to the web application – which will result in an authentication
cookie of some sort. That cookie will get round-tripped with your AJAX calls and ASP.NET
does its magic to establish a client identity context. Since WebAPI inherits the security
context from its (web) host, the client identity is also available here.
The other fundamental scenario is JavaScript code *not* running in the context of
the WebAPI hosting application. This is more or less just like a normal desktop client
– either running in the browser, or if you think of Windows 8 Metro style apps as
“real” desktop apps. In that scenario we do exactly the same as the samples did in
my last post – obtain a token, then use it to call the service.
Obtaining a token from IdentityServer’s resource
owner credential OAuth2 endpoint could look like this:
thinktectureIdentityModel.BrokeredAuthentication
= function (stsEndpointAddress,
scope) {
this.stsEndpointAddress
= stsEndpointAddress;
this.scope
= scope;
};
thinktectureIdentityModel.BrokeredAuthentication.prototype = function ()
{
getIdpToken = function (un,
pw, callback) {
$.ajax({
type: 'POST',
cache: false,
url: this.stsEndpointAddress,
data: { grant_type: "password",
username: un, password: pw, scope: this.scope
},
success: function (result)
{
callback(result.access_token);
},
error: function (error)
{
if (error.status
== 401) {
alert('Unauthorized');
}
else {
alert('Error calling STS: ' +
error.responseText);
}
}
});
};
createAuthenticationHeader = function (token)
{
var tok
= 'IdSrv ' +
token;
return tok;
};
return {
getIdpToken: getIdpToken,
createAuthenticationHeader: createAuthenticationHeader
};
} ();
Calling the service with the requested token could look like this:
function getIdentityClaimsFromService()
{
authHeader = authN.createAuthenticationHeader(token);
$.ajax({
type: 'GET',
cache: false,
url: serviceEndpoint,
beforeSend: function (req)
{
req.setRequestHeader('Authorization',
authHeader);
},
success: function (result)
{
$.each(result.Claims, function (key,
val) {
$('#claims').append($('<li>' +
val.Value + '</li>'))
});
},
error: function (error)
{
alert('Error:
' + error.responseText);
}
});
I updated the github repository,
you can can play around with the code yourself.