I will be using the same web hosted Web API service for the sample. The service is very simple:
[Authorize]
public class IdentityController : ApiController
{
public ViewClaims Get()
{
return ViewClaims.GetAll();
}
}
…and the ViewClaims class simply returns the claims of the current user from a service point of view:
public class ViewClaims : List<ViewClaim>
{
public static ViewClaims GetAll()
{
var principal = ClaimsPrincipal.Current;
var claims = new List<ViewClaim>(
from c in principal.Claims
select new ViewClaim
{
Type = c.Type,
Value = c.Value
});
var vc = new ViewClaims();
vc.AddRange(claims);
return vc;
}
}
In addition there are two built-in “clients” for the service – an MVC controller that renders the client’s identity server-side:
[Authorize]
public ActionResult IdentityMvc()
{
return View(ViewClaims.GetAll());
}
…and the corresponding view:
@model Thinktecture.Samples.ViewClaims
@{
ViewBag.Title = "Client identity";
}
@section featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>Client identity.</h1>
</hgroup>
</div>
</section>
}
<br />
<table>
@foreach (var claim in Model)
{
<tr>
<td>
<strong>@claim.Type</strong>
</td>
<td>
<span>@claim.Value</span>
</td>
</tr>
}
</table>
As well as as an AJAX style client that uses the Web API service to fetch the data and render the claims on the client:
@{
ViewBag.Title = "Client identity";
}
@section featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>Client identity.</h1>
</hgroup>
</div>
</section>
}
<br />
<table data-bind="foreach: items">
<tr>
<td>
<strong data-bind="text: type"></strong>
</td>
<td>
<span data-bind="text: value"></span>
</td>
</tr>
</table>
@section scripts
{
<script src="~/Scripts/knockout-2.2.0.js"></script>
<script type="text/javascript">
$(function () {
var viewModel = new IdentityViewModel();
ko.applyBindings(viewModel);
$.get("../api/identity", function (items) {
$.each(items, function (idx, item) {
viewModel.add(item.Type, item.Value);
});
}, "json");
});
function IdentityViewModel() {
var self = this;
function Claim(root, type, value) {
var self = this;
self.type = ko.observable(type);
self.value = ko.observable(value);
};
self.items = ko.observableArray();
self.add = function (type, value) {
self.items.push(new Claim(self, type, value));
};
};
</script>
}
The output of both pages is identical (as expected):
The name claim comes from standard Forms Authentication and the localClaim from claims transformation:
public class ClaimsTransformer : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(
string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return base.Authenticate(resourceName, incomingPrincipal);
}
incomingPrincipal.Identities.First().AddClaim(
new Claim(“localClaim”, “someValue”));
return incomingPrincipal;
}
}
In the following posts we will write some clients against this service and host. stay tuned.
The source code so far can be found here.
Filed under: ASP.NET, IdentityModel, IdentityServer, WebAPI