Authentication & Authorization in AngularJS - asp.net

I'm an ASP.NET MVC developer and I recently started to learn AngularJS as it seems like a more modern technology.
However, there's a few complications in my mind when it comes to authentication and authorization in AngularJS. In particular, AngularJS with ASP.NET Web API as the backend.
After authentication and getting the token from the api, I would imagine using Angularjs to store the token in the cookie. So any further requests will include the token. Say for some reason, the token expires, the next angularjs request to the api will fail with unauthorized. However, on the client side, angular thinks that it's authenticated (cookies) and will keep using that invalid token on all requests. I can think of a solution, which is to check for the "unauthorized" response on every request and redirect to login if that's the case. But I would probably be shot for such a practice.
In ASP.NET MVC, protecting a certain page/resource is as simple as adding [Authorize]. But in angular, it seems to be very complicated. How do I many protect many pages againsted the unauthenticated? Do I have to setup and interceptor for every route, etc?
Same goes for Authorization, what if the authenticated user attempts to access, say, the admin panel or parts of admin panel. How do I redirect to unauthorized page if they accessed by direct URL.

There can be many ways of solving your dilemma, but let me give you some tips that I generally use to authenticate and authorize.
Your app has to authenticate with the API (regardless of .NET or otherwise), which may happen by a login request that sets a cookie (during a server redirect), or perhaps a login endpoint the returns a token (like using oAuth). Either way, you have to store the authorization token so Angular can access it. I use cookies or localStorage myself. Then when a user is authenticated, I have a user service store that so I can use it anywhere in the app.
Once this happens, you can use a request http interceptors to attach the authorization header to your request. You can also use a response error interceptor to catch when the token no longer is accepted (usually a 401 status code, easy to check for), and force a login again. This should address issue #1 you raise.
Then for issue #2 and #3, if you are using uiRouter, you can listen for state change events (particularly $stateChangeStart). If I have an admin page, I'll name it admin.whatever and then have a change event that checks if the state has admin or not, and redirect users who are not admins. Likewise, I can do the same for all states to detect if there is no currently logged in user and force a login redirect.
Hope that gives you some ideas, it sounds like you're on the right track but need to hook into the Angular features.

This isn't really an answer but I'm in the same boat as you. I've built some basic Angular pages and small SPA app but now I'm trying to tie it all into an MVC app using .Net Identity. Surprisingly there isn't much out there about this topic. I did come across an good example but it was with .Net Core and MVC 6 which I'm not ready to jump into yet. It's worth watching and might give you some ideas.
http://stephenwalther.com/archive/2015/01/29/asp-net-5-and-angularjs-part-6-security
A couple days ago I came across this video and for the most part it seems to address the issue. It's the only thing that I've found so far with MVC 5, Angular and some .Net Authorization. Take a look and see if it gives you any ideas. I haven't had a chance to implement it yet but I'm hoping to get started doing that in the next couple of days. If you learn or find anything post it here.
https://www.youtube.com/watch?v=f67PFtrldGQ&nohtml5=False

Related

Authentication for SPA hosted on same domain as API leveraging SameSite cookies

I am thinking about how I will implement authentication in my react application and even after hours of reading I still have few questions. Please provide any information you think could benefit me I would like to really understand the problem it could be that my line of reasoning somewhere implies I don't fully understand something I would appreciate if you could point out where I am wrong.
Infrastructure:
SSR React app served behind reverse proxy on <domain_name>
.NET 5.0 api server using asp.net identity served behind reverse proxy on api.<domain_name>
Reverse proxy provides SSL so https:// on both
General information:
I need to support external logins (Google, Facebook etc)
Paying for Auth0, Okta etc is not an option
No 3rd party apps are going to authenticate against me
Client is web browser
I don't need to support outdated browsers
Questions:
Do I need IdentityServer4 at all? I am never going to act as an authentication authority for 3rd party apps.
I can still support external logins without using IS4 right? I just need to handle redirect callback I can see there are methods such as GetExternalLoginInfoAsync, ExternalLoginSignInAsync which should make the job easier.
The reason why every SPA authentication tutorial recommends Auth Code + PKCE is because they assume you want to be authentication authority, don't have API on the same domain, or were written before SameSite cookies existed?
My plan is to write a custom login route assigning SameSite cookie and that's it. This makes client-side code super simple no shenanigans with adding access tokens to headers before making calls.
Is it possible? I found few articles describing something very similar but I am not sure.
With a setup like that is there something that is just not going to be possible? Like remote logout, banning users, or whatever you can think of.
You don't have to implement IS4 if you don't want to (especially since IS4 will have its support shut down in November 2022). You can just read the OAUTH2 documentation and implement the routes you need and still be OAUTH2 compliant.
You will have only one client (your react app) so no dynamic client registration, just the 2 following routes:
the authorization endpoint to get an authorization code when the user successfully authenticated himself using an external provider. This authorization code has to be used ONLY ONCE in the next route.
the token endpoint to get an access token and a refresh token using the authorization code given above or a refresh token given before. If the same authorization code or refresh token is used twice, you have to revoke the tokens given in the first call because this should not happen.
With a setup like that is there something that is just not going to be possible? Like remote logout, banning users, or whatever you can think of.
Besides these 2 routes you are free to implement whatever you want. Like a route to allow user to revoke all of his sessions.
To answer more precisely to your questions:
Do I need IdentityServer4 at all? I am never going to act as an authentication authority for 3rd party apps.
No you don't need it if you don't know exactly why you need it. It does not have anything to do with the fact that you are not going to act as an authentication authority for others clients.
I can still support external logins without using IS4 right? I just need to handle redirect callback I can see there are methods such as GetExternalLoginInfoAsync, ExternalLoginSignInAsync which should make the job easier.
Yes you can, as long as you store the authorization code and the refresh token when the user successfully signed in using the external provider.
The reason why every SPA authentication tutorial recommends Auth Code + PKCE is because they assume you want to be authentication authority, don't have API on the same domain, or were written before SameSite cookies existed?
I would assume that they are oriented Oauth2 compliance. But if you don't need nor want to implement OAuth2 framework, then don't. But in my opinion you should, it is really easy to implement.

Is this the correct way of using REST API + OAuth on top of the normal web page?

First of all, for the lack of words, I used "normal web page" on the title. Please let me explain that:
Recently, I have seen many websites such as shopify.com making the most out of the modern browsers support for html5 push-state and Ajax. Instead of submitting forms, requesting new pages I see them doing all that via their REST APIs. It seems to me like a very neat way to do things because it's faster (less page reload), and also allow greatly allows us to re-use the API code.
In these scenarios, the users access the service via the websites as they would normally do, however their interaction with the resources are powered by the REST APIs.
As I dive more into the documents, it seems like these API requests should be stateless yet should always have a mechanism to authorize/authenticate each request so I looked into OAuth2 for that purpose (Since I will need OAuth2 anyhow, to grant accesses to 3rd parties). Now, since in this particular circumstance the user's browser will act as the client to request the resources via REST, I want to know what is the recommended flow to do it.
Right now I plan to implement it as followed: (I'm using Symfony 2 with FOSRestBundle and FOSAuthServerBundle)
User should login via the web form as normal (Since we need to authenticate/authorize both for the normal web page as well as for the API Requests)
When the user logged in, immediately check if an OAuth client is already created for this user? If not then create it with GRANT_TYPE_IMPLICIT. If the client is already there, just retrieve it.
Proceed to normal OAuth authorize for Rest requests?
Edit 1:
Further research makes me think that I should not send back the refresh token to the JS app as this would be too dangerous if the browser is compromised. Perhaps I could store the refresh token for the user somewhere in the server backend once he/she is logged in, then can reserve a special link for the JS app to request for new access token when old one expires? This seems a bit messy to me tho.

Authentication and authorization related doubts with asp.net web api

I have to start a new project to be developed in MVC 4 and Web API. I have prior experience with MVC 4 but with Web API this will be my first project. I understand that web api is there to be consumed by different platforms.
I have a few concerns related to web api. I am presenting them to you guys as following:
1) My first concern is related to user authentication. I looked into this SO question and followed the link1 and link2 given in the selected answer. I still have a couple of questions:
a) When we do user authentication through Form Authentication we create a cookie, that track if the user is authenticated or not, but with web api we do not store cookie, instead user credentials are passed in content header. I didn't get how user's logged in status is tracked in this case ?
b) My another concern is related to restrict unauthorized access, which I think I can find find out in link 1 and link2 provided above, if I am not wrong.
c) I looked at the Edward Brey answer (in the same SO question) as well for authentication but I didn't get the idea completely.
2) My second doubt is about mixing Form authentication and Basic Http authentication. Is it possible that for login I use forms authentication and then for consuming web api I use basic http authentication? If yes then please guide me.
My questions may sound inappropriate but please bear with me
1.a) Restful APIs are stateless, so you are not keeping track of user's logged in status, rather you are sending credentials which are verified for each of the requests
1.b) Yes, if not there are number of articles on web for that. Authorization Filters can help you in achieving this.
1.c) In short, he has mentioned simple logic to authorize user before executing any of the methods in your API. Call EnsureAuthenticated before executing any of the methods in a controller, or put that logic in you Authorize filter.
2) Yes you can do it. In Restful API's each call can be a new instance and you can pass in credentials with api requests whichever you are making.
If you go in discussion of Link 1 that you have provided, you will see:
In our specific case, the server generates the auth token by encoding
the concatenated username and password as Base64 (the reverse of what
is described in the article) and sending it back to the client via a
HTTP header when it performs their ‘log in’ action. The clients then
store this auth token and send it with each subsequent request that
requires it.
If the format of the auth token is well known (as it is in my case),
you could also just generate this yourself on the client and send that
without having the server do this work.
You can use your login to generate an authentication token for client, which you can use to send attached to your web api requests.

Token authentication and authorisation for a self-hosted ASP.NET Web API 2 REST service

I'm using VS2013 and Web API 2 to create a self-hosted (using OWIN), RESTful service over SSL using token authentication. Although I'm not a novice developer, this is my first time looking at ASP.NET technologies, so please keep that in mind.
I've got everything more-or-less working except for the authentication and authorisation parts. I fully understand the difference of authenticating a user (who is this user?) and authorising an already authenticated user to access a resource (can this user access this particular resource?).
A very simple overview of my auth process is as follows (makes some assumptions for brevity):
An unknown client connects to the API, e.g. GET api/values.
The server responds with a 401 and this response header: "WWW-Authenticate: Token".
Upon seeing this, the unknown client knows to connect to a different API endpoint here: POST api/auth (routed to the Login function), supplying the username and password.
The server will try to figure out if this is a valid user and can accept or reject the user depending on the validity of the credentials.
(Rejected) The server returns an error status code (403?). End of process.
(Accepted) The server creates a random token (e.g. a GUID) and stores it against the user record. Then it sends the token to the client.
The now authenticated client reconnects to the API, GET api/values, and this time also supplies the token.
The user returns the resource data to the client.
...
The user can log out by connecting to the same API as he used to log in: POST api/auth (this time, his request will be routed to the Logout function). This will remove the token from the server and the client will also have to remove its own token.
As you can see, this is a relatively simple process, but I can't find any concrete and simple examples to understand how best to achieve this with a self-hosted Web API 2.
I don't need to register users or do any password/roles management, etc. and there is no external authentication. All valid users have the same rights to access the resources and they're already created in the system by a separate process over which I have no control (I can only read their credentials for validation). Most examples I found are talking about security frameworks that I don't need, so I've ruled out using any of the following: Basic Authentication, Windows Authentication, Forms Authentication, Individual Accounts, ASP.NET Membership/Identity, OAuth, Thinktecture or any other security framework.
I've read articles about authenticating in a message handler and others about authentication in a custom Authorize attribute filter, while others even suggest I should use the new (in Web API 2) IAuthenticateFilter attribute. This is very confusing. Can you please advise on a very simple way to achieve my auth objectives? Any specific code examples will be greatly appreciated, even if they're just skeleton implementation or pseudocode. I just need some ideas to get me started.
After a lot of googling, I found this article on CodeProject: http://www.codeproject.com/Articles/630986/Cross-Platform-Authentication-With-ASP-NET-Web-API. While this is not Web API 2 or self-hosted, it has given me a number of ideas on how to proceed.
Someone also posted a comment to that CodeProject article referencing a NuGet package that may interest anyone looking for something similar: https://www.nuget.org/packages/WebApiTokenAuth. In my case, it is a bit much.
Finally, in addition to the authentication options mentioned in the question, there's also the option to write an OWIN middleware to do authentication if self-hosting using OWIN (as per the official MS recommendation). However, I plan to implement this particular form of token authentication with a message handler, as there's more support for this method available than for writing OWIN middleware.

MVC 4 Web Api Security

I am very new in web api security. I have used form authentication technique. when user logs in, a token is created and stored as a cookie in user's web browser. On each request the token is varified and if user is authenticated and authorized user is given access to the service.
but I think this approach does nothing in web api security. cookies can easily be copied and pasted in other browser and anyone can get the service.
I am thinking to use App key and secret along with form authentication. I am not suggested to use third party service like Oauth for authentication. I am not Sure about the Implementation of app key and secret that how it exactly works.
Please provide better way to secure my web api wihtout using third party services and to prevent cookie hijacking etc. What actions are performed to build a strengthly secure web api.
The forms authentication is good enough. You can also do the following:
Use anti-forgery (antifrogery) tokens. Check this or this
It will also be great if on sensitive actions you check if the call to the function was made from the same site or not.You can implement your own action filter for this. (check if the referral site is your site, or the expected site)
Edited:
Thanks guys for your comments. I guess you are right. Well authentication cookies in ASP are created as httpOnly cookies which means even if the site had some XSS vulnerabilities it will still be safe and cant be stolen. I would also suggest to use https everywhere if the site is used for sensitive operations (like a bank) to make sure the cookies are perfectly safe.

Resources