ASP.NET Web Api (REST): Authentication using the users credentials or a token? Leave "Register new user" resource password free? - asp.net

I am trying to create a REST service using asp.net web api and everything is working fine but I have now come across what to do with authentication.
I am a little confused of where to start, here is what I have been thinking.
I have an REST api that consist of a number of resources, each resource will need the user to be registered, so what is the best action for doing this? Should I just send the username and password in the header on each call to the service so I can authenticate on the server using
AuthorizationFilterAttribute
I should at least encrypt it though? I would be interested to know what others are doing, I know there is a concept of creating a token (which I presume will be short-lived) so hence the user would authenticate and then would receive a token, this token would then be sent on further calls to the service. So how would I handle the problem when the token expires?
I also have a resource that is used to register a new user, actually the only things that will be calling this is my clients (Android, iPhone). SO should I leave it FREE of any authentication methods or put a hard coded password or something similar so that at least nobody else can register new users? Bearing in mind that the service will be public on the internet.
I just don't seem to be able to find the correct way of doing this, I certainly want to try and get it right the first time so I don't have to refactor the service completely.

The following link appears to cover some sensible DIY options http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/. The "Tokens based on Public/Private Keys" section covers an approach I have used effectively in the past and would maybe be of assistance to you.
At the moment though I am using http://identityserver.codeplex.com/ the Thinktecture IdentityServer with OAuth bearer tokens ("Resource Owner Password Credential" grant type)... I am finding this a very good set of code and examples to work from and have IOS clients obtaining tokens and calling the WebApi.
If you really must secure your registration screen you could maybe use client certificates installed on the devices to authenticate... again the Thinktecture service could help here https://identity.thinktecture.com/idsrv/docs/default.htm?RequestingatokenusingOAuth2.html. Although if you registration process is secure What are best practices for activation/registration/password-reset links in emails with nonce e.g. email confirmations and activations etc. it may be safe to leave publicly accessible - this all depends on your business requirements and desired sign up workflow.
You should at least use Transport Level security SSL but as you suggest message level security e.g. encrypting any tokens is very advisable - the OAuth spec has something to say about this http://self-issued.info/docs/draft-ietf-oauth-v2-bearer.html#mitigation.
Regarding expiring tokens - we tend to expire our tokens with the same frequency as our password changing policy; although keeping the validity time down is important (to minimise impact of token theft) and a consideration to balance against your requirements. OAuth has the concept of refresh tokens Why Does OAuth v2 Have Both Access and Refresh Tokens? some debate and links around this topic here, we are not currently using this approach as the ID server we are using doesn't currently support this.
Keeping your tokens safe is also a consideration e.g. we are using the KeyChain in IOS, but also think about Mobile Device Management policies if possible as if these tokens or passwords are one the device they could be stolen, perhaps look into jailbreak detection, lock screen enforcement etc.

Related

Authorization Code Grant: is it safe to send the tokens to the client?

Let's say I have a SPA with a back-end on the same domain. If I had to connect to an external OAuth provider (let's say Google), the Authorization Code Flow (without PKCE) is the safer option. This means that:
The SPA requests a code to the Authorization Server
Then, it sends that code to the back-end
The back-end exchanges the code (and a secret) with the AS in order to get the tokens
The back-end sets a Session Cookie with the SPA to keep the user logged in
This flow is the most secure because the SPA never sees a single token. It doesn't use them. If I have to make a request to the API with the Access Token, the SPA will make a request to the back-end which in turn will use the Access Token to get the resources. And the back-end is also responsible for using the Refresh Token. So far so good.
Now, what if the back-end, upon successful exchange (once it gets the tokens), sends the tokens back to the browser? That way, the client can hit the API's endpoints on its own.
In theory, this should be avoided if I'm not mistaken. Giving the tokens back to the front-end kinda defeats the purpose of the Authorization Code Grant, you might as well use the Authorization Code w/ PKCE in order to get the tokens on the front-end directly, right? With the Code Grant, it's the back-end that gets authenticated, not the SPA.
But I'm thinking: that's what Firebase does, isn't it? As far as I know, Firebase uses the Authorization Code (without PKCE), redirects to the Firebase App's back-end (__auth/handler) and then it still gives the tokens to the front-end (id token, access token, refresh token).
Am I missing something? Or is it ok to give the tokens to the front-end at the end of the Authorization Code Grant?
PS. Obviously, in the Firebase case, the back-end will not actually use those tokens, it relies on the browser ones that are sent in each request I imagine. In the case I mentioned though, the back-end stores those tokens so in theory I'll have 2 sets of tokens: the ones that the back-end received with the code exchange, and the ones that get sent to the browser (initially they're the same, but they're different after the first refresh). Should the back-end discard the tokens completely and rely on the browser ones? I assume it should, because if Refresh Token Rotation is enabled, the back-end would have an invalidated Refresh Token after the first refresh by the browser. This situation is driving me nuts. My opinion is that the tokens should remain on the back-end, but I'm trying to figure out how can the Firebase approach be safe.
Interesting isn't it? There are trade offs involved, and different technologies make different choices on how to use tokens.
SHORT ANSWER
If is not inherently unsafe to use access tokens in the browser. It is generally recommended to keep the tokens short lived, confidential and to store them only in memory.
Whether to use tokens like this may also depend on the data sensitivity and the opinions of your stakeholders.
BIG PICTURE
What we'd really like is for these two technologies to work in an equivalent technical way. After all, both typically need to do the same job, of calling APIs to access data and then presenting screens to users.
Web UIs
Mobile UIs
It is totally standard to use access tokens in a Mobile UI, but some people have concerns about doing so in a Web UI.
WEB UIs
One option is to keep tokens out of the browser and use a 'web back end', as you describe. Many people prefer this from a security viewpoint, but it has these downsides compared to a pure SPA architecture:
You have to double hop all calls to APIs via the web back end, which is less efficient
The need for a web back end that runs code to issue auth cookies can result in suboptimal hosting, where you are unable to deploy web resources using a Content Delivery Network
There are other complexities due to the two forms of back end credential: cookies for web and tokens for mobile
PROOF OF POSSESSION TOKENS IN 2021?
Hopefully these are not far away for public clients - where DPoP tokens can be sent between Web UIs and APIs. This will mean access tokens stolen from a browser cannot be replayed and will further reduce the need for web back ends:
DPoP Proposed Standard
BROWSER THREATS
Of course there is more to browser security than cookies v tokens, and security is about covering risks. It is worth thinking about threats that concern you and how to mitigate them - this blog post has some notes on how I reasoned this out for an online code sample of mine a while back:
Browser Threat Model

Is it possible to use an external Identity Provider in a Web API with ASP.NET 5?

Reading this question, #Pinpoint's answer and the further discussion on comments, I'm well aware that natively we can't add an identity provider to our apps developed with ASP.NET 5. One possible replacement for the legacy OAuthAuthorizationServerMiddleware is then provided by the AspNet.Security.OpenIdConnect.Server as I've found in many places.
Now, there is one point that I'm still unsure about all this because I'm really not an expert in security, so my knowledge about OAuth is not very deep. My doubt is the following: is it possible to use an external identity provider when using OAuth to protect one RESTful API?
Notice that I'm not talking about adding social login to one website, I'm talking about using one external identity provider in one RESTful API.
My point is, this makes me a little confused yet, because I always thought this should be a concern of my app.
So my question here is: when using OAuth and ASP.NET 5, is it possible to use an external identity provider, other than implementing one? If it is possible, how this works in short? I mean, my app still needs to be able to manage the identities of users, in the sense that it needs to manage claims and so on.
In that case, if it is really possible, how the flow would be? The external identity provider should issue the tokens? But how my app would be able to verify those tokens and manage users identities?
EDIT: One of the reasons I feel unsure about that is that when we use the UseOAuthAuthentication extension method, we set up one callback path which is described as
The request path within the application's base path where the user-agent will be returned. The middleware will process this request when it arrives.
Now, if we are developing a site, then this really does make sense. The person goes there, click a button to login with a provider like Facebook. The user is redirected to Facebook's page and then after he logs in, he is redirected to some page of the site.
On the other hand, with a RESTful API this is meaningless. There is no notion of being redirected.
This makes it seems that the usage of external providers is only for sites and not for RESTful API's. This is the main point of my question.
My doubt is the following: is it possible to use an external identity provider when using OAuth to protect one RESTful API?
Yes, it's definitely possible. This is exactly what you do when you use Azure Active Directory to protect your API endpoints:
app.UseOAuthBearerAuthentication(options => {
options.AutomaticAuthenticate = true;
options.Authority = "https://login.windows.net/tushartest.onmicrosoft.com";
options.Audience = "https://TusharTest.onmicrosoft.com/TodoListService-ManualJwt";
});
The next legitimate question is: if you can use the tokens issued by AAD to protect your API, why couldn't you do the same thing with Facebook or Google tokens?
Unlike Facebook or Google, AAD issues completely standardized tokens named JWT tokens that the OAuth2 bearer middleware can "read" and "verify" to determine whether the token is still valid and was really issued for your API (i.e if the audience attached with the token corresponds to your API. You can control this value using the resource parameter when making your authorization request).
You can't do something similar with FB or Google tokens, since they are totally opaque. Actually, it's not really surprising since these tokens have only one objective: allowing you to query FB or Google APIs, not your own ones (these social providers don't allow to set the audience of the access token).
Since you can't read the token yourself, the only option is to ask FB or Google whether it is still valid to make sure your API doesn't accept invalid tokens. That's something you can (easily) do with Facebook as they offer a "token inspection endpoint" you can query for that: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow (see the Inspecting access tokens chapter). This way, you can ensure the token is not expired and determine the user corresponding to the token.
Sadly, this approach has two downsides:
You have to make an extra HTTP call to the Facebook endpoint to validate the access token, which implies caching received tokens to avoid flooding Facebook with too many requests.
As the access token is not issued for your own API, you MUST absolutely ensure that the access token was issued to a client application you fully trust, or it will allow any third party developer to use his own FB/Google tokens with your API without having to request user's consent. This is - obviously - a major security concern.
You can find more information in the last part of this SO answer (it's for Katana and about Dropbox, but you should get the idea): OWIN/OAuth2 3rd party login: Authentication from Client App, Authorization from Web API
So my question here is: when using OAuth and ASP.NET 5, is it possible to use an external identity provider, other than implementing one? If it is possible, how this works in short? I mean, my app still needs to be able to manage the identities of users, in the sense that it needs to manage claims and so on.
In that case, if it is really possible, how the flow would be? The external identity provider should issue the tokens? But how my app would be able to verify those tokens and manage users identities?
To work around the limitations mentioned in the previous part, the best option is - as you've already figured out - to create your own authorization/authentication server. This way, your API doesn't (directly) accept FB or Google tokens but the tokens issued by your own server, that can possibly redirect your users to FB or Google for authentication.
This is exactly what this sample does: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/vNext/samples/Mvc
The user is invited by the client application (Mvc.Client) to authenticate with your authorization server (Mvc.Server) so he can get an access token to later query the API (also in Mvc.Server). For that, the user is redirected to your authorization server, which itself offers you to authenticate with Google or Twitter.
When this external authentication step is done, the user is redirected back to your authorization server (Mvc.Server), where he's asked to give his consent for the client app (Mvc.Client) to access his personal data.
When the consent is given, the user is redirected back to the client application with the access token you can use to query the API endpoint.

Asp.NET WebAPI custom authorization

I want to create a authorization mechanism for an application based on WebAPI and AngularJs.
I've seen some articles, which use BasicHttpAuthentication, but i really don't like the whole idea of sending username, and password on every request. The more it doesn't fit for me is because i want to use OpenId authentication, where you don't have username/password pair.
I'm thinking about a solution, but I don't really know how to implement it. The concept is that user is authenticated as in an usual Web application - posts a form with user / password or selects an OpenId provider. If the user is authenticated succesfully, it is placed in a static object, which stores the User object for a certain ammount of time. Next a usertoken is generated and passed to the Client Application. The client passes the token on each request to the server, if the user exists in the above mentioned static object with the appropriate authentication token it is authorized to get the data.
Firstly - Do you think this is a good approach to the problem?
Secondly - How should I pass the authentication token, WITHOUT using cookies? I guess it should sit in the request headers, like in BasicHttpAuthentication but, I really dont' know how to handle it.
BasicHttpAuthentication
I'm with you on feeling dirty about caching the username and password on the client and forever transferring it with every request. Another aspect of Basic authentication that might work against you is the lack of sign-off. Other than changing the password, you can't "invalidate" a basic authentication session. Tokens on the other hand, will typically offer an expiration date, and if you want server-side invalidation you can check the issue date and say "any tokens older than issue date xyz are invalid".
Server State
You mention "If the user is authenticated successfully, it is placed in a static object". But this is independent of the token? This sounds like you're wanting to implement server state management of authentication sessions, but this isn't strictly necessary. The token itself should be sufficient for user authentication, managing server state is another potential obstacle. Server state can become difficult to manage when you factor app-pool recycles or web-farm environments (what if you want two services to share the same authentication token, but not require communication with a central "authentication server" for storing the state / session?)
Passing Authentication Token
Headers is definitely a good place for it. Really, where else is there? Cookies, Headers, Message. Other than a browser client, cookies don't make a lot of sense, and including it in the message can muddy your message formatting a bit, so headers is the only remaining option that makes much sense in my view.
Client Implementation
You've not specified, but I suspect you're interested in calling the service from .NET? In which case System.Net.Http.HttpClient could be your friend. In particular, the DefaultRequestHeaders collection. You can use this to add a custom header to store your authentication token.
Server Implementation
When researching ASP.NET authentication recently, I learned a lot about customisation by examining the Mixed Authentication Disposition ASP.NET Module (MADAM). I wasn't interested in using MADAM as-is, but learning about it from that article and examining the source code gave me a lot of ideas of how I could insert my own authentication module into the web stack.

Membership / Authorization over a REST service

I'm investigating creating a WCF REST service for an existing asp.net application to be consumed by various clients including Windows Phone 7, Android, iPhone apps etc.
Creating a simple WCF REST service and consuming it from the above platforms is not a problem and works really well. What I am struggling to get my head around is authorization.
The asp.net application uses the Membership provider to provide authentication and authorization and I'm comfortable in using that API from the REST service.
How do I secure my REST service so that the first call has to be to authenticate (passing the username and password) and following calls know who is 'logged in'. I'm guessing the authenticate method will have to pass back some sort of token to be used in subsequent calls identifying the caller. Is this secure enough as the whole site / service is over SSL?
Any suggestions welcome.
The more restful authentication scheme is to use HTTP Authentication, e.g. Basic or Digest. Since your service is over SSL, Basic should be sufficient. The authentification tokens (login/password) are sent with every request, so that the service can be stateless. Every client library that I'm aware of can deal with basic authentication.
In general the token approach is better then just sending username+password (Basic Authentication) in each request. The problem is to implement it correctly: while Basic Authentication is very easy to implement, and actually it's already implemented by most application and web servers, the token is something you'll need to implement yourself - it must be encrypted, so clients won't understand it, so you'll need some keys management, it also must have some expiration date and may be you'll want some revoke functionality.
In addition, it will make client's life harder: instead of just attaching basic authentication header to each request, client must first go to some authentication point, receive a valid taken and then use the token on the requests. If the token expires, the client will need to go to the authentication point again.
So if you have time and knowledge, and your clients are smart, it's better to use the token approach. Otherwise with SSL, basic authentication should be sufficient.
I've seen an example in the latest Windows Azure toolkit for WP7 that might be helpful for you. It basically uses the Membership Provider, logs in a person (the first time the person installs the app) and then generates a Ticket. It then Encrypts this ticket and sends it back as a TOKEN which is then stored on the phone in the isolated storage. The expiration of the ticket is set to int.MaxValue so that the token remains good for a long period of time.
Now, this token is passed over to the Web Services in the Authorization Header where it is decrypted, the identity of the user is verified and then the web service call is made.
Hoping this helps. I am trying to solve a similar scenario and trust me, there isn't much out there that points us in the right direction...which is a pretty sad state of affairs if you ask me.

Is basic access authentication secure?

Using Apache, it is quite simple to set up a page that uses basic access authentication to prompt a user for a name/password and use those credentials in some way to grant access to that user.
Is this secure, assuming the connection between the client and server is secure?
The worry about basic auth is that the credentials are sent as cleartext and are vulnerable to packet sniffing, if that connection is secured using TLS/SSL then it is as secure as other methods that use encryption.
This is an old thread, and I do not believe the highest voted/chosen answer is correct.
As noted by #Nateowami, the security stack exchange thread outlines a number of issues with basic authentication.
I'd like to point out another one: if you are doing your password verification correctly, then basic authentication makes your server more vulnerable to denial of service. Why? In the old days, it was common belief that salted hash was sufficient for password verification. That is no longer the case. Nowadays, we say that you need to have slow functions to prevent brute forcing passwords in the event that the database becomes exposed (which happens all too often). If you are using basic auth, then you are forcing your server to do these slow computations on every API call, which adds a heavy burden to your server. You are making it more vulnerable to DoS simply by using this dated authentication mechanism.
More generally, passwords are higher value than sessions: compromise of a user password allows hijacking the user's account indefinitely, not to mention the possibility of hijacking other systems that the user accesses due to password reuse; whereas a a user session is time-limited and confined to a single system. Therefore, as a matter of defense in depth, high value data like passwords should not be used repeatedly if not necessary. Basic authentication is a dated technology and should be deprecated.
The reason why most sites prefer OAuth over Basic Auth is that Basic Auth requires users to enter their password in a 3rd party app. This 3rd party app has to store the password in cleartext. The only way to revoke access is for the user to change their password. This, however, would revoke access for all 3rd party apps. So you can see what's the problem here.
On the other hand, OAuth requires a web frame. A user enters their login information at the login page of this particular site itself. The site then generates an access token which the app can use to authenticate itself in the future. Pros:
an access token can be revoked
the 3rd-party app can not see the user's password
an access token can be granted particular permissions (whereas basic auth treats every consumer equally).
if a 3rd-party app turns out to be insecure, the service provider can decide to revoke all access tokens generated for that particular app.
Basic auth over http in an environment that can be sniffed is like no auth, because the password can be easily reversed and then re-used. In response to the snarky comment above about credit cards over ssl being "a bit" more secure, the problem is that basic authentication is used over and over again over the same channel. If you compromise the password once, you compromise the security of every transaction over that channel, not just a single data attribute.
If you knew that you would be passing the same credit card number over a web session over and over, i'd hope that you'd come up with some other control besides just relying on SSL, because chances are that a credit card number used that frequently will be compromised... eventually.
If you are generating passwords with htpasswd consider switching to htdigest.
Digest authentication is secure even over unencrypted connections and its just as easy to set up. Sure, basic authentication is ok when you are going over ssl, but why take the chance when you could just as easily use digest authentication?
As the name itself implies, 'Basic Authentication' is just basic security mechanism. Don't rely on it to provide you with worry free security.
Using SSL on top of it does makes it bit more secure but there are better mechanisms.

Resources