Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I protect controller actions in an MVC app that doesn't contain a db or user data?

I'm looking to understand the nitty gritty mechanics of authorization so I can devise a strategy for my situation.

My situation is that I am part of a distributed application. My part is an MVC5 application that basically just consists of a couple of controllers that return single page app views. So hit controller A and get back single page app A. Hit controller B and get single page app B. Etc. This application contains no database or user data. Some other application on a completely different website/server does. I want to ask that other application if a user is valid or have users ask the other application directly themselves and only allow access to my app views if the answer is yes. So, in essence, I want to protect my controllers based on the word of a remote application that contains an exposed api for login/user validation.

It has been suggested to me that token authentication is the way to go. It's a bit daunting with my lack of experience with it, but I've buried myself in some reading and video presentations. Here is my current, weak attempt at summarizing the task based on limited understanding. Please correct as needed:

  • An access token needs to be generated
  • Getting an access token is not part of the Account controller, it's part of OWIN middleware
  • The access token will be sent along with the requests for my contoller actions
  • My controller actions, decorated with the [Authorize] attribute, will parse the token and do the right thing

Questions:

  • Q1: Should I generate the token or should the other app - the one with the db and user data?
  • Q2: My controllers don't know anything about users. That data is in the other app. What specifically are the controllers parsing for under the hood in order to do the right thing? In essence, what specifically tells them, "yes, this request is OK. Return the view."
  • Q3: I started my project awhile back using a standard MVC5 project template that comes with VS2015 because I figured I'd be handling users/login etc. That turned out not to be the case. Am I going to have to go back and redo this project from scratch because that template doesn't fit this requirement or can I do some surgery on it and continue? For instance, I don't know if that template has all the OWIN stuff I need or maybe has too much extra junk (bloated Account controller, Entity Framework, etc.) to be easily transformed/maintained.
  • Q4: Is token authorization overkill here? Is there an easier way to keep unauthorized users from accessing my controller actions that makes more sense given the nature of the project?

Any insight would be appreciated.

Update: What I meant in Q2 was, at it's simplest, how does [Authorize] work? Details? I'm guessing I have to tell it how to work. For instance, a silly example to illustrate. If I wanted to tell a controller decorated with [Authorize] to let anyone in who has the username "fred", how and where would I do that? I'm not so much looking for code. I'm thinking conceptually. My app must know something about the tokens the other app (authenticating app) is genenerating. In general terms, what would I add to my MVC app to tell it how to decode those tokens? Where do I add it? Is there one standard place?

like image 541
Robert Avatar asked Jan 27 '17 04:01

Robert


People also ask

How do you restrict access to action in MVC?

To restrict the public action method in MVC, we can use the “NonAction” attribute. The “NonAction” attribute exists in the “System. Web.

Which method is used to prevent access of particular page from MVC application?

But, you can restrict or prevent access by just adding a one attribute above to that controller action method named as “[ChildActionOnly]”.


3 Answers

I think you are on the right track and are right about the steps you have mentioned. I will answer your questions based on what I understand:

Q1. The other application is the one that needs to authorize and generate a token (whatever be the authorization mechanism they use) and you should receive this token before showing your views. Since the data is coming from the other application , they have to give your controllers access to their data. This is why you need to ask the other application for the token/authorization. With a valid token got from the other application your application can send valid and authorized requests to their data.

Q2. What you can do from your side is to add a check as to whether the request for your action/view is coming from an authorized user. For this, you need to check if this request has a valid token.

Q3. I don't know what you mean by "template" here. But if you need to integrate your controllers to the other solution, you do need to know what the other solution does and what it offers in terns of authorization and of course the data. They should provide your application access to a public api for this purpose.

q4. THis is something the other application needs to do. From what I understand, I think you are only adding a web API to an existing system so I think you need to really know how you can integrate with the other application. They should have clear APIs that are public for you to do this to access their features and data.

Since you have not mentioned if this other application is something like a secure enterprise solution or a Google API (has public API ) it would be difficult to tell exactly what you can expect from the other application.

I think you would need to try JSON web tokens (JWT )
I have not used it myself though . stormpath.com/blog/token-auth-spa – It is useful for authenticating if a request to your controller. Here is a similar question as you have (I think) and how JWT could solve it How to use JWT in MVC application for authentication and authorization? and https://www.codeproject.com/Articles/876870/Implement-OAuth-JSON-Web-Tokens-Authentication-in


You can override the AuthorizeAttribute like this : https://msdn.microsoft.com/en-us/library/ee707357(v=vs.91).aspx . Your authorization logic of checking for whichever tokens/auth mechanism you decide to can be added to this new action filter. Then add that new attribute to your actions. So if your custom authorization attribute when overriding looks like this:

public class RestrictAccessToAssignedManagers : AuthorizationAttribute

Then your action would have the attribute decoration like this:

[RestrictAccessToAssignedManagers]
public ActionResult ShowallAssignees(int id)

Found a good article which could also be of help - https://blogs.msdn.microsoft.com/martinkearn/2015/03/25/securing-and-securely-calling-web-api-and-authorize/

like image 70
Arathy T N Avatar answered Oct 13 '22 07:10

Arathy T N


My answer to your question will be based on:

I want to ask that other application if a user is valid or have users ask the other application directly themselves and only allow access to my app views if the answer is yes. So, in essence, I want to protect my controllers based on the word of a remote application that contains an exposed api for login/user validation.

Yes, to my humble opinion, oauth token-based approach is overkill for your need. Sometimes, keeping things simple (and stupid?) is best. Since you are part of a distributed application, I suppose you can (literally) talk to the team in charge of the "other application/website" where requests that hit your controllers will be coming from.

So, I will skip your questions 1, 2, 3 and 4, which are oriented towards the token-based oauth approach, and suggest a rather different, "simplistic" and faster approach, which is the following:

For clarity purpose, let's call the other application "RemoteApp", and your application "MyApp", or "The other team" and "You", respectively.

-Step 1: You (MyApp) exchange a symmetric secret key with the other team (RemoteApp);

-Step 2: MyApp and RemoteApp agree on the algorithm that will be used to hash data that will be posted to MyApp when a user from RemoteApp requests a page on MyApp. Here, you can, for instance, use MD5 or SHA256 algorithms, which are well documented in MSDN and pretty easy to implement in C#;

Step 3: MyApp tells RemoteApp what its needs to be part of the posted data to validate/authenticate the request.

Here is an example: Step 1: BSRabEhs54H12Czrq5Mn= (just a random secret key. You can choose/create your own);

Step 2: MD5 (this is the algorithm chosen by the 2 parties)

Step 3: The posted request data could include (at least 3 - 4 parameters or form fields, plus the checksum): - UserName+RemoteApp fully-qualified domain name + someOther blabla data1 + someOther blabla data2 + checksum

The above information will be concatenated, without space. For instance, let's assume:

UserName = fanthom
RemoteApp fully-qualified domain name = www.remote.com
someOther blabla data1 = myControllerName
someOther blabla data2 = myActionName

The checksum will be generated as follows (function prototype):

generateMD5(string input, string secretKey)

which will be called with the following arguments:

    string checkSum = generateMD5("fanthomwww.remote.commyControllerNamemyActionName", "BSRabEhs54H12Czrq5Mn=")

Notice that in the first argument the above 4 parameters have been concatenated, without space, and the second argument is the secret symmetric key.

the above will yield (actual md5 checksum):

checkSum = "ab84234a75430176cd6252d8e5d58137"

Then, RemoteApp will simply have to include the checkSum as an additional parameter or form field.

Finally, upon receiving a request, MyApp will simply have to do the same operation and verify the checkSum. That is, concatenate Request.Form["UserName"]+Request.Form["RemoteApp fully-qualified domain name"]+["someOther blabla data1"]+["someOther blabla data2"], then use the md5 function with the secret key to verify if the obtained checksum matches the one sent in the request coming from RemoteApp.

If the two match, then the request is authentic. Otherwise, reject the request!

That'all Folks!

like image 25
zinczinc Avatar answered Oct 13 '22 08:10

zinczinc


I seems you need to implement an OpenID/OAuth2 process.

This way, your apps will be able to utilise single-sign-on (SSO) for all your apps, and all you would have to do is set up your MVC5 app as an OpenID/OAuth2 client.

Take a look into Azure AD B2C which is perfectfor this (I am currently implementing this right now for 3 projects I am working on).

https://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on

https://azure.microsoft.com/en-us/services/active-directory-b2c/

https://identityserver.io/

like image 1
Martin Fletcher Avatar answered Oct 13 '22 07:10

Martin Fletcher