View authorization with angular and UI-Router considerations - c#

First, my client side code is pure HTML, JavaScript, and angular.js. My server side API uses the Asp.Net Web API controllers.
Working off this similar example I am weary about passing user role information to the client. I am also weary about storing permission for views in my route configurations. My server side controllers and methods are built to inspect the incoming requests and authorize the specific user.
Should I worry too much about the client permissions if my server side will only allow authorized calls to be made? For example, let's assume a user and any admin can view that specific user's profile. If someone other than the user or admin tries to navigate to that profile the data will not be presented. An error from the server will be generated. The client side code can redirect the user if they are unauthorized.
I am curious to know what other developers have done for this type of scenario.

It primarily depends on your application specification, or your own desires. Passing user role information to the client helps you enhance UX in numerous ways. In addition to that, due to role check on different part of the front end, in theory users will not be able to do any request to your API endpoint which will end with a server error due to unauthorized request.
Let's throw some examples:
You are having a link (in navigation bar let's say) to the administrative section of your app. You really don't want to expose that link to ordinary users, since they will eventually click on it. It will result with a unauthorized response from the server, and subsequently got redirected to the previous page. - In my oppinion that is completely unnecessary
You have some edit form which can be editable both by users and admins. However, admins have few more fields to edit which are not permitted to the users. You really want to hide those fields, to prevent uneccesary unauthorized response from the server if those field were edited by ordinary user.
You need to "fine grain" your permissions to the user's page. So you don't really don't want to show a link to details of that user if your role doesn't allow you.
If you have stored roles in your client app, as a end user you won't need to the a server roundtrip in order to find out that you really aren't authorized to see something. Of course, you still must have server side authorization.
Keep in mind those scenarios are purely to give you example of few scenarios in which you will have a great benefit of having roles on your client side as well.

Related

Authentication for local application using website

I am creating a .NET class library which will allow local applications to access the accounts of users registered on my website, using an API. I would like the library to handle all authentication of users, so that any app I create an simply call the library, and be returned a token for the API. I'm not sure how to do this authentication.
There are a couple of ways I have considered doing this, however they are not ideal. The first would be to simply create a login form within the library which asks users to enter their login then calls the API. The second method would be to have a webpage where the user logs in and is then given the token which they enter into the app.
The ideal scenario for this situation is that the user does not see their token, and the actual login process is delegated to the website if possible. Both of the above ways lose out on one of those conditions.
The ideal way I would like to do this is inspired from an app I use where if the user is not logged in, they must press a 'Sign In' button, which opens a webpage where they log in. Once they have done so successfully the app automatically detects this and they are signed into the app. The downfall of this solution is that I have no idea how I might do that myself.
Essentially what I'm asking is, is the third solution viable, and how could I do it, or if not are there any better solutions I've overlooked.
FYI the website and API run ASP.NET MVC and WebAPI respectively and the library will use .NET framework.
Edit:
From the comment below it seems likely that you'll want to implement an authentication provider using something like OAuth. The .NET reference libraries can be found here and there's a similar answer already on StackOverflow that may also shed some light.
Welcome to Stack Overflow!
Personally, I would keep the Web API as the authority on authenticating a user and just consume this HTTP endpoint on all platforms (web, desktop, mobile etc) whenever you want to validate a user's credentials.
At a high level the process would be along the lines of:
Have your "clients" (desktop, mobile, web applications) submit HTTP requests to an API route (something like /authenticate) when the user first logs in.
Run your authentication logic
If successful return a token (and cache this this for use in subsequent requests)
Otherwise return a 401 response
Every client will now get a standardised response they can use for determining if they should redirect the user to some protected area, or show them an error message.
This also allows you to design login screens that are native to the platform they're running on (which is a smoother user experience). I wouldn't recommend having a library return a pre-built login page to the user - you'll find that becomes a real pain to maintain!
The third solution you proposed is also a valid way of doing things - but it does have the side effect of redirecting the user's focus away from the application they're using - which you may not want depending on your use case. It's also a bit trickier to implement than just calling the API directly, so unless you have a specific requirement to do it this way I'd not recommend it.
Hopefully this makes some sense. If you are unsure on how to implement cross application authentication then I'd recommend taking a look at some existing answers on Stack Overflow such as:
Basic token checking
OAuth

Redirect only from certain website

I'm working on a .NET Framework website that is only opened from a redirect command. Is it possible to do that only if I redirect from a certain website?
For example, if I have a personal blog and I want to redirect users to a certain site, that site would only open if the previous website is one I can whitelist or something like that.
If possible, I'd like to do it server side (the redirecting application is built in .NET Core 2.1)
Thanks a lot!
Technically, no. While you can use the Referer (historically mispelled) header, that header is not guaranteed to be present and can also be spoofed. In other words, if the client simply doesn't send the header, there's no way to know whether the user was redirected from your other site or not. Even if it is present, the client could have simply sent the header manually and completely bypassed your other site.
If the two sites are on the same domain or subdomains of the same domain, you can set a cookie at your other site that is then checked on the redirected site. However, the sites need to be able share cookies, which again, means same domain and both have data protections providers configured to utilize the same distributed store.
If you want to limit access the best and most fool-proof way is always going to be auth. Make them login at both points and you can ensure that no one can do anything you don't want them to do.

How to store and maintain user access roles

We have an application (C# on the server, using AngularJS / Web Apis for a single page application) that assigns users different roles, which are stored in the database. When the user logs in, the user object (including RoleID's and RoleName) is transformed into a JWT and sent to the user, which is then used as authentication.
We're having trouble determining the best way to maintain and use these access roles however. Specifically, to use them in the current set up, it would seem that we have to hard code either the name of the role or the ID into the application.
For example, on the client side, if we want only users with a Manager role to be able to see and click a button, we would have to explicitly state that, ie if (UserService.HasRole('Manager')) { doStuff(); }.
Conversely, we'd have to do the same thing on the server side (because everyone knows relying on client-side security is bad). When the server gets a request on the API, it checks the JWT for validity and, if valid, checks the User's roll to see if they are allowed access to the specific web API endpoint.
This all seems prone to breaking if a role is renamed, or the ID changes. I generally hate hardcoding things like this. Is there a better methodology or approach that can be taken here?
In the past, when we've done RBAC (Role Based Access Control), we decouple the Role from the Permission e.g.
Role Permission
===============================
Manager Create Order
Manager Delete Order
Till Operative Create Order
Administrator Create User
Administrator Suspend User
etc.
This could be stored in a database and cached in something like Redis. Two tables, Role and Permission, where the Permissions need to match the ones built into the application (you could script this).
So your permissions grow with your application e.g. you add a new dining service, you can add a "seat diners" permission. The permissions for existing/mature bits of the software should rarely change (unless they were written incorrectly), whereas the roles are entirely fluid and can be renamed etc.
You can then use an annotation/security framework to ensure that the user making each API call on the server side has the correct role required.
You can even make it additive and allow a user to occupy multiple roles at once to blend things together.
You may maintain your user to role mapping in the database also in another table (using FK constraints) or you may use something like LDAP with the mapping being looked up from the DB/cache.
On the server side, Microsoft has built in management for roles. I would first look at
http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity
And then I'd also look at the the IdentityServer project for working with JSON Tokens on the server side.
https://brockallen.com/2013/04/14/getting-json-web-tokens-jwts-from-adfs-via-thinktecture-identityservers-adfs-integration/
On the client, I would suggest storing the tokens as either just in memory javascript or if you want them to persist, I would store them as cookies but make sure to set the cookies to not be accessible by JavaScript by using the httponly parameter when creating the cookie.
HTH's

Handling security in an ASP MVC application that uses JS to a REST API

I have an ASP MVC4 web site. Originally, most of the content was served via controllers as one would expect. I have moved the data storage from SQL Server to MongoDB. I have also added a lot of ajax to update data client side, without a full refresh. This is working fine, but my controllers now have lots of methods that take json and return json. I was able to build a Node.js server that hits the database and exposes exactly the same functionality, without lots of going to and from C#.
My javascript client-side is now calling a Node.js REST API, this works great. My 'secure' code (like adding a new user) hits the same REST API from the server side.
My question is this: How can I handle security properly with this? I have three scenarios:
GET api/messages: No need for security, I want to expose my site's messages to anyone who is interested via a Json REST API.
GET api/my/messages: I need to allow access to this only if the user is logged in (it gets the user's messages).
POST api/users: This is a function that should only be called from the server, and nothing else should be able to use it.
As the user is already logging in to my ASP website, how can I use their logged in credentials to authenticate them with my REST service? While the user is logged in, the pages client side will hit it regularly for updates.
Is there any sensible/standard way to do this? The core idea is that the client side code uses a REST API that is at least partially open to the public, and that in fact that API offers all of my business logic - only parts of it (like creating a user) are locked down to super-admins only.
Thanks in advance!
Create two authentication middleware handlers. One you add to all your "my" routes and another which you add to your POST routes.
The "my" authenticator takes the asp.net auth cookie that is present in the request and makes a http call to your asp.net mvc site with it.
You'll need an action which either returns a 401 if the cookie is invalid otherwise it returns some info about that user's permissions perhaps.
If the request into node doesn't have a cookie, return a 401 again.
In addition, to prevent excessive calls to your mvc site to check the cookie, you could use the cookiesession middleware to set a cookie on the client with a flag of authenticated. That will result in 2 cookies for your client, but that shouldn't be an issue. Just make the node one expire before the aspx one.
The POST authenticator middleware can use any shared secret you like between your node and mvc server. e.g. a special header in the request.
If the user is required to login you can use [Authorize] on your controller actions. Autorization will be handled like any other webrequest.
Furthermore you might consider to add a key to your api requests which you can provide in the initial page load. A autorized user will have a GUID which he will sent with the api call. You can check if this key was issued by your app to a valid user.
As you said all the secure calls already go through your MVC server code which in turn calls the Node.js code, am I right? Basically you need a way to block calls to this Node.js from other clients that are not your MVC code.
Thinking out loud, these are the ideas that pop into my mind:
Use SSL only between MVC and Node. You can set up client and server certificates so that the Node code will only respond after authentication (I don't know how Node handles SSL so you will need some documentation here
If you want, the Node server could also check the call origin and so you can filter based on IP and only allow IPs where your MVC code is sitting
Use an encrypted authentication token on the secure methods on the Node code. Again I'm not really a Node expert but I can imagine it has ways of decrypting a token, or you can simply base it on a random number with a common seed... If noone has access to your server code ideally noone should be able to guess this token. Again, SSL will help against traffic sniffing
I am quite sure that people will come up with other ideas. For me, the most basic thing is anyway ensure that the secure methods are only accessible through an SSL connection and on this connection you can exchange all the info (token, passwords, etc.) you desire.

Is it possible to have a personalized ASP.NET web app with only some SSL pages?

I have a web application that once signed in, personalizes almost all pages.
I want to be able to have some very specific pages locked down with SSL that may have sensitive information. From what I have been able to find, once you sign in via an SSL sign in page (area of the web site), the session information which I use to store a lot of personalization and user credentials is not available to the non SSL portion of the web site since they are considered 2 seperate applications.
This MSDN document pretty much says what I am talking about: MSDN Doc
Note: If you use this type of site structure, your application must not rely on the user's identity on the non-SSL pages. In the preceding configuration, no forms authentication ticket is sent for requests for non-SSL pages. As a result, the user is considered anonymous. This has implications for related features, such as personalization, that require the user name.
I am also not using forms authentication. When a user signs in a session object is made storing their credentials including their IP. If this session object exists for a particular user with the same IP then they are considered 'signed in' and the personalization features are enabled.
So my question is, are there any work arounds to this so that say my sign in page and some other page are using SSL, the reset of the site is not, and all pages have access to the same session variables?
If not can anyone suggest any other methods of accomplishing the same type of personalization features?
Since there are no comments, I thought I'd offer an inelegent but practical solution.
Leave the RequireHTTPS off in your forms authentication configuration block.
Next, you create a custom class that implements IHttpModule. This interface has an Init method that takes a HTTPApplication instance as an argument. You can then attach to the "AuthenticateRequest" event on this instance.
From here, you can 302-redirect any requests that come in without SSL when they should do. You'd probably want to drive which pages require SSL from a custom configuration section in your web.config.
To use this class for your requests, you have to add a line to the HttpModules section of the web.config.
For a start, have a look at this code project article: http://www.codeproject.com/KB/web-security/WebPageSecurity_v2.aspx - this will enable you to "step on" and "step off" of https for certain pages.
With regard to your session issues, I think you're a bit stuck. The standard forms authentication mechanism stores a cookie to identify the authenticated session which is available over http or https. My advice would be to switch to using forms authentication, and use the ProviderUserKey guid as the key for accessing your per-session data.
Hope this helps.
We have decided to not go with SSL in those few pages that required them. We looked at other web applications that did similar things and they do not use SSL. We are not really protecting anything that would be all that useful for a malicious user to go through the trouble of stealing anyways.
One option I did consider before the decision was made to remove the SSL was to store a user's session on the application's web service interface. Every page call would access the web service to access the session information. This would be enforced on every page call to ensure the session stayed active. I didn't do too much investigation into using this solution before the SSL decision was made so there could be many draw backs to this solution, especially having to make extra calls to the web service with every server hit.

Categories

Resources