Part 1 and part 2 of this post series got use started with an ASP.Net MVC 3 application using claim-based architecture for identity management needs. In this post we’ll implement finer authorization controls by using role-based security. In this post, we’ll add a new administrative page and permit only users with “Admin” role accessing it.
Part I: Extend STS and AuthenticateAndAuthorizeAttribute
- Modify CustomSecurityTokenService.cs in the STS project. We’ll put the user in “Admin” role if the user name is exactly “Admin”
protected override IClaimsIdentity GetOutputClaimsIdentity( IClaimsPrincipal principal, RequestSecurityToken request, Scope scope ) { ...... outputIdentity.Claims.Add( new Claim( System.IdentityModel.Claims.ClaimTypes.Name, principal.Identity.Name ) ); if (principal.Identity.Name == "Admin") outputIdentity.Claims.Add( new Claim( ClaimTypes.Role, "Admin" ) ); else outputIdentity.Claims.Add(new Claim(ClaimTypes.Role, "User")); return outputIdentity; }
- Modify AuthenticateAndAuthorizeAttribute.cs in the web project. We’ll add a new Roles attribute where we can specify which role (for now we only support one role in the string) is required to authorize a user. Then, we’ll change authenticateUser to handle multiple realms (Portal and Admin). At last, we’ll give an easy implementation of authorizeUser to check against specified roles:
public string Roles { get; set; } private void authenticateUser(AuthorizationContext context) { var fam = FederatedAuthentication.WSFederationAuthenticationModule; var signIn = new SignInRequestMessage(new Uri(fam.Issuer), fam.Realm + context.HttpContext.Request.FilePath); context.Result = new RedirectResult(signIn.WriteQueryString()); } private void authorizeUser(AuthorizationContext context) { if (!string.IsNullOrEmpty(Roles) && !context.HttpContext.User.IsInRole(Roles)) context.Result = new HttpUnauthorizedResult(); }
Part II: Add new Admin page.
- Add a new AdminController to web application’s Controllers folder. Note how the controller is decorated with additional role requirement:
[AuthenticateAndAuthorize(Roles = "Admin")] public class AdminController : Controller { public ActionResult Index() { return View(); } }
- Add a Admin folder to web app’s Views folder. Then add a new Index.cshtml as before:
<h1>Hi there, @this.Context.User.Identity.Name!</h1> <h2> @this.Context.User.IsInRole("Admin")</h2>
Part III: Modify web.config
Now we change the web.config file to add Admin path as allowed audience. We’ll also change the realm definiation because we’ll dynamically append page path in AuthenticateAndAuthorizeAttribute class:
<microsoft.identityModel> <service> <audienceUris> <add value="http://localhost:81/Portal" /> <add value="http://localhost:81/Admin" /> </audienceUris> <federatedAuthentication> <wsFederation passiveRedirectEnabled="false" issuer="http://localhost:4011/MyWebApp_STS/" realm="http://localhost:81" requireHttps="false" /> ...
Part IV: Test run
Launch the browser. You can go to Portal page as before. However, when you try to access Admin page, unless you entered “Admin” as user name, you’ll get 401 error:
HTTP Error 401.0 – Unauthorized
Only after you entered “Admin”, you’ll be greeted to the Admin page:
What’s next?
Next we’ll chain up our FP with Azure ACS to work with other IDPs over internet such as Windows Live ID, Google ID, etc.
0 comments:
Post a Comment