7

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?

Robert
  • 828
  • 2
  • 13
  • 28
  • 1
    It depends on your authentication scheme, but have a look at authentication tokens, generating, storing and passing them. – meganaut Jan 27 '17 at 04:56
  • Thank you for your response. I will look at that. Do you have specific answers to Q1, Q2, Q3, and Q4 above? Looking for more of the "why" than the how and what - a deeper understanding of the problem space. Thanks again. – Robert Jan 31 '17 at 15:15

5 Answers5

3

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/

Community
  • 1
  • 1
Arathy T N
  • 306
  • 3
  • 13
  • Thx for response. On Q2 you say "for this, you need to check if this request has a valid token". So my controller is not checking for a valid token, I am? How do I do that? And if I find a valid token, how, specifically, do I tell my controller "this guy is OK"? Right now it just rejects all requests when I decorate it with the [Authorize] attribute. On Q3, I mean as I say, a Visual Studio 2015 project template - a starter project. I want to know if I should scrap the project and start it over from scratch. – Robert Feb 05 '17 at 19:30
  • On Q4, I am not as interested in how to get my data from the other app. I am intersted in the details of how to keep the controller locked. Picture my controller has a large single page app with lots of javascript - like an online tax app or like GMail. Something really large with lots of functionality. I want to lock it well. But when the other guy tells me a user is good, I want to return the app. I see the [Authorize] attribute. It's working well. Keeping all requests out. How do I tell it someone is OK and you should give the app to them? – Robert Feb 05 '17 at 19:35
  • You say "you should receive this token before showing your views". But the details. How does my controller know the token passes the test? I must have to tell it somehow. How does one do that? Do I write a function? Do I configure something? Where do I configure it? I see JWT kind of does something in start up config. What if I wasn't using JWT. Is ther ea standard way to tell an MVC app "this is how to process that [Authorize] tag I've decorated my controllers with"? – Robert Feb 08 '17 at 03:05
  • I have updated my answer to show authorize attribute can be used to authorize. – Arathy T N Feb 08 '17 at 03:44
2

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!

zinczinc
  • 544
  • 5
  • 11
  • Pretty direct hit on Q4. Is there some threshold or circumstance that may indicate one or the other approach? I know simpler is better sometimes, but sometimes not, depending on some things. What's the essential sell for one vs the other approach? I'm guessing OAuth is more secure, but more difficult? It must be. I can't seem to get an answer to how, specifically, I unlock my controller if it is decorated with [Authorize] :) It's so secure that nobody can use my controller :) That's the ultimate in security :) – Robert Feb 05 '17 at 20:59
  • Well, if you really want to go the oauth way (with token authentication), then you must accept to embrace OWIN+ CORS. There is no way round it IMHO, unless you want to reinvent the wheel by trying to implement your own authentication mechanism. You will need OWIN for the external authentication and CORS since the requests will be coming from "external". The first step would be for you to read about OWIN and CORS. When creating a new MVC5 app from the default template, if you chose selected (or kept selected) the authentication option, you will have most of the code needed included already. – zinczinc Feb 06 '17 at 04:28
  • EDIT: Well, if you really want to go the oauth way (with token authentication), then you must accept to embrace OWIN + CORS. There is no way round it IMHO, unless you want to reinvent the wheel by trying to implement your own token-based authentication mechanism. OWIN will handle external authentication and CORS the requests coming from "external" origins. You will end up creating a DB with the aspnet tables (AspNetUsers, etc.). IMHO, the minimum prerequite if you want to go the oauth way is: you must have created, understood and played with an MVC app that uses authentication/Authorize. – zinczinc Feb 06 '17 at 04:50
  • Didn't really want to go the auth way. I'm not set on anything. Was looking for solid info on how to decide which way to go. Something like "use oauth if xyz is important to you. If xyz is not important to you, do something simpler". – Robert Feb 08 '17 at 03:02
1

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/

  • Thank you for your response. I will look at that. Do you have specific answers to Q1, Q2, Q3, and Q4 above? Looking for more of the "why" than the how and what - a deeper understanding of the problem space. Thanks again. – Robert Jan 31 '17 at 15:21
1

So your app is publicly addressable? I can't tell for sure from your description.

Well you only have these issues if a public client is requesting certain page views from you...

Now here's where i'm confused. If it's an external client accessing different parts of your distributed app, ALL the parts have this problem.

Generally the client authenticates itself at one place (say written by Team A), any other subsequent view requests would need to be checked as well (HTTP being connectionless/stateless), including others done by Team A? So your problem would already be solved (because it would be a problem for everyone, and they would have done something using an auth cookie + checking service, use the same checking service...)?

Which leads me to believe that the view requests are internal and not client facing, in which case... why is auth such a big deal?

If you could clarify your scenario around what requests you need to authenticate...

Vivek
  • 2,103
  • 17
  • 26
0

you are on right track. But instead of you implementing OAUTH and OpenIDConnect user third party which does the heavy lifting. One such tool is IdentityServer

https://identityserver.github.io/Documentation/docsv2/

Now answering your question from IdentityServer point of view

An access token needs to be generated -- true

Getting an access token is not part of the Account controller, it's part of OWIN middleware -- yes, for better design

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 -- Yes as a part of response header

Questions: Q1: Should I generate the token or should the other app - the one with the db and user data? The identity server will generate token that you requested.

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. - usually the token is sent back to the identtyServer to check for validity and to get access_token which will check if the user has access rights. if not [Authorize] attribute will throw error message and return

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. - Yes u can delete the extra stuffs

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? -- It is not an over kill. It is the right thing to do for your scenario

Boopathy T
  • 537
  • 3
  • 8
  • What I was looking for here were the details of "check for validity". How does my controller know what a valid token is? It must be told obviously. What is the general procedure for doing that. Is it a config option? Do I write a function called "Valid"? What tells my controller how to decide if something is valid? – Robert Feb 08 '17 at 02:58
  • Silly example to illustrate. How and where would I tell my controller decorated with [Authorize] to let all users with username "fred" in? – Robert Feb 08 '17 at 03:35