DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • Web Development Checklist
  • Transactional Outbox Patterns Step by Step With Spring and Kotlin
  • Security Challenges for Microservice Applications in Multi-Cloud Environments
  • Micro Frontends on Monorepo With Remote State Management

Trending

  • Web Development Checklist
  • Transactional Outbox Patterns Step by Step With Spring and Kotlin
  • Security Challenges for Microservice Applications in Multi-Cloud Environments
  • Micro Frontends on Monorepo With Remote State Management
  1. DZone
  2. Data Engineering
  3. Databases
  4. ASP.NET MVC: Using ProfileRequiredAttribute to restrict access to pages

ASP.NET MVC: Using ProfileRequiredAttribute to restrict access to pages

Gunnar Peipman user avatar by
Gunnar Peipman
·
Dec. 25, 10 · News
Like (0)
Save
Tweet
Share
2.74K Views

Join the DZone community and get the full member experience.

Join For Free

If you are using AppFabric Access Control Services to authenticate users when they log in to your community site using Live ID, Google or some other popular identity provider, you need more than AuthorizeAttribute to make sure that users can access the content that is there for authenticated users only. In this posting I will show you hot to extend the AuthorizeAttribute so users must also have user profile filled.

Semi-authorized users

When user is authenticated through external identity provider then not all identity providers give us user name or other information we ask users when they join with our site. What all identity providers have in common is unique ID that helps you identify the user.

Example. Users authenticated through Windows Live ID by AppFabric ACS have no name specified. Google’s identity provider is able to provide you with user name and e-mail address if user agrees to publish this information to you. They both give you unique ID of user when user is successfully authenticated in their service.

There is logical shift between ASP.NET and my site when considering user as authorized.

For ASP.NET MVC user is authorized when user has identity. For my site user is authorized when user has profile and row in my users table. Having profile means that user has unique username in my system and he or she is always identified by this username by other users.

Community site & ASP.NET MVC: Is user authorized?

My solution is simple: I created my own action filter attribute that makes sure if user has profile to access given method and if user has no profile then browser is redirected to join page.

Illustrating the problem

Usually we restrict access to page using AuthorizeAttribute. Code is something like this.

[Authorize]
public ActionResult Details(string id)
{
var profile = _userRepository.GetUserByUserName(id);
return View(profile);
}
If this page is only for site users and we have user profiles then all users – the ones that have profile and all the others that are just authenticated – can access the information. It is okay because all these users have successfully logged in in some service that is supported by AppFabric ACS.

In my site the users with no profile are in grey spot. They are on half way to be users because they have no username and profile on my site yet. So looking at the image above again we need something that adds profile existence condition to user-only content.

[ProfileRequired]
public ActionResult Details(string id)
{
var profile = _userRepository.GetUserByUserName(id);
return View(profile);
}
Now, this attribute will solve our problem as soon as we implement it.

ProfileRequiredAttribute: Profiles are required to be fully authorized

Here is my implementation of ProfileRequiredAttribute. It is pretty new and right now it is more like working draft but you can already play with it.

public class ProfileRequiredAttribute : AuthorizeAttribute
{
private readonly string _redirectUrl;

public ProfileRequiredAttribute()
{
_redirectUrl = ConfigurationManager.AppSettings["JoinUrl"];
if (string.IsNullOrWhiteSpace(_redirectUrl))
_redirectUrl = "~/";
}

public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);

var httpContext = filterContext.HttpContext;
var identity = httpContext.User.Identity;

if (!identity.IsAuthenticated || identity.GetProfile() == null)
if(filterContext.Result == null)
httpContext.Response.Redirect(_redirectUrl);
}
}

All methods with this attribute work as follows:

  • if user is not authenticated then he or she is redirected to AppFabric ACS identity provider selection page,
  • if user is authenticated but has no profile then user is by default redirected to main page of site but if you have application setting with name JoinUrl then user is redirected to this URL.

First case is handled by AuthorizeAttribute and the second one is handled by custom logic in ProfileRequiredAttribute class.

GetProfile() extension method

To get user profile using less code in places where profiles are needed I wrote GetProfile() extension method for IIdentity interface. There are some more extension methods that read out user and identity provider identifier from claims and based on this information user profile is read from database. If you take this code with copy and paste I am sure it doesn’t work for you but you get the idea.

public static User GetProfile(this IIdentity identity)
{
if (identity == null)
return null;

var context = HttpContext.Current;
if (context.Items["UserProfile"] != null)

return context.Items["UserProfile"] as User;

var provider = identity.GetIdentityProvider();
var nameId = identity.GetNameIdentifier();

var rep = ObjectFactory.GetInstance<IUserRepository>();
var profile = rep.GetUserByProviderAndNameId(provider, nameId);

context.Items["UserProfile"] = profile;

return profile;
}
To avoid round trips to database I cache user profile to current request because the chance that profile gets changed meanwhile is very minimal. The other reason is maybe more tricky – profile objects are coming from Entity Framework context and context has also HTTP request as lifecycle.

Conclusion

This posting gave you some ideas how to finish user profiles stuff when you use AppFabric ACS as external authentication provider. Although there was little shift between us and ASP.NET MVC with interpretation of “authorized” we were easily able to solve the problem by extending AuthorizeAttribute to get all our requirements fulfilled. We also write extension method for IIdentity that returns as user profile based on username and caches the profile in HTTP request scope.

ASP.NET MVC ASP.NET Profile (engineering) Database

Published at DZone with permission of Gunnar Peipman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Web Development Checklist
  • Transactional Outbox Patterns Step by Step With Spring and Kotlin
  • Security Challenges for Microservice Applications in Multi-Cloud Environments
  • Micro Frontends on Monorepo With Remote State Management

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: