Informing caller additional setup required before continuing - http

Need help to understand standard flow for handling additional-information-required scenario.
Context: We have a number of product implementations, all integrated with a central single sign-on server. A registered customer can opt to start using new products on-demand. But some of the products require the customer to carry out some one-off setup steps before they use the product - these steps are only needed the very first time of using the product.
Consider a customer is on the page https://product-abc.ourdomain.com. And now clicks on a link within that product something like 'do something (note, this will redirect you to product-xyz)'. At this point the customer is redirected to https://product-xyz.ourdomain.com. Here we want to detect whether the customer is using the product for the first time and if yes, redirect the user to a setup page wherein we can prompt them to supply the product-specific additional information. On the other hand, if the customer is already configured for the product, they will just navigate into the product page and continue using it.
I wanted to know if there is something similar to the 401 Unauthorized flow to handle this. With authentication flow,
A client tries accessing a protected resource.
The server checks the caller has requisite authentication and if not, returns 401 Unauthorized status code with additional details in the WWW-Authenticate header.
The client carries out authentication - say by integrating with the central single sign-on server - and then reattempts the original request, this time succeeding.
I'm wondering if there is a similar flow like,
A client tries accessing a protected resource.
The server checks whether the client is OK to use it. In our case, if its the first time a customer is accessing the product, this check will determine additional setup is required. For example, the client has to supply us with their correspondence address so that we can set up a data tenancy for the specific customer. Here I would like to return a HTTP status code, say, 4xx Setup Required with additional information in a header, say, WWW-SetupInfo.
Once the initial-setup flow is completed, the customer will be redirected to the main product and carry on using it.
The nearest status code that seems to match my usecase is 402 Payment Required, but product-xyz doesn't need any specific subscription or payment. We just need some product-specific additional information to do the initial configuration.
I can handle it by doing custom implementation using 3xx redirect but I was wondering if there is a better way of handling it.
Thanks for any pointers.

Unless you are using basic-authentication, you don't want to use a 401 Unauthorized" status code with a WWW-Authenticate` header. This built in mechanism in browsers has very limited functionality:
Always prompts for user name and password, with no mechanism to customize the process either with look and feel, or custom workflows. You say you want to use single-sign-on. 401 Unauthorized is not compatible with that.
Has no log-out mechanism
Has no session timeout mechanism
As a result, almost all websites use logins based on forms and cookies. If somebody isn't logged in, you should use a 302 Temporary redirect to the login page.
Similarly, if somebody doesn't have their initial setup completed to use a particular page, you would not use a special HTTP status. You would either present them with the a 200 OK page with the form asking for the data you need, or use a 302 Temporary redirect to take them to that form on another URL.

Related

Is it really necessary to update the subscription on every page load?

I'm currently working on a web app which will allow a user to subscribe to push notifications. We'll store the subscriptions in a database table mapped against the user's ID and when a notification needs to be sent, we'll look up the user's subscriptions and send the notifications.
I've been following this guide:
https://developers.google.com/web/fundamentals/codelabs/push-notifications/
All is going well, but something just doesn't feel "right".
On every page load, the service worker is registered, then it checks if they're already subscribed, then even if they are it calls updateSubscriptionOnServer() which contains the following comment:
// TODO: Send subscription to application server
This effectively means that every page load is going to be attempting to write the same subscription back to the database. Obviously we'll handle that in the application, but it doesn't seem ideal.
With the Web Push API, is this the expected approach?
Many thanks
Yes it can be useful to send the subscription to server on every page load:
The user may have changed permission from blocked to granted (or default) in the browser settings, so you want to create the subscription and send it to the server
The subscription endpoint may change for different reasons, so you need to make sure that the current endpoint is sent to the server (the previous endpoint will return 410 Gone)
A compromise between the points above and performance can be to send the subscription to the server only on given pages (e.g. homepage).

Request activation via HTTP GET

In my ASP.Net MVC website, whenever a user registers, the admin should activate his/her account. In my view, I'm creating simple links for this:
#Html.ActionLink("activate", "user", new { id = item.ID })"
I usually would create a form with a #Html.AntiForgeryToken() and POST it to the controller. However, I think it might be OK to do this via HTTP GET since we're doing this for users which are in admin role. Should I use the POST method or is it OK to continue with the HTTP GET and just an id field?
I think it might be OK to do this via HTTP GET since we're doing this for users which are in admin role.
Nope. If anyone sends the link to /user/activate/42 to your admin and he clicks it, he just activated a user.
Apart from the security, read When should I use GET or POST method? What's the difference between them? for the implications on HTTP level, which also regards browser implementations (caching, warning for re-post, and the list goes on).
A GET request should never change the state of the system. It should leave the system unchanged. You don't want anyone to be able to approve users by making a GET request as it leaves the system open to attack. A GET request should also never be used to pass data around.
You should use a PUT request for this ideally. If you can't use a PUT then a POST is ok.

Prevent misuse of ASP.net Handler

When a customer signs up for a site, we want to let them know whether a username/email is available for use.
We have a httphandler that serves the purpose of feeding a jquery script that showsthe customer whether or not their desired username/email is available.
The question is:
The service can clearly be seen being called when you view the request in fiddler.
It shows /emlhandler.asmx?name=xxxxxxxxxxx#yyy.com
From the handler, a simple 0 or 1 is returned to indicate whether or not the name/address is available.
My concern is that this seems like a major security issue that would be very easy for an inexperienced person to exploit to discover all the users on the site.
So friends, how do you protect your site info and still allow the ajax callback to provide a great user experience?
Thanks.
Heath
You are being slightly paranoid here. Every site that allows user registration has to do something similar. One thing you can reasonably do is add a slight delay (maybe 2 or 3 seconds) to the handler's processing in order to reduce the likelihood or ease of a brute-force attack. Frankly, I don't think anyone would bother.
Another option is just to ignore repeated emails and send a verification email before a user's registration actually becomes active. If a new user attempts to use an existing email, the original email owner receives the verification and can cancel or ignore it. But I don't recommend this.
I'd say the vast majority of the sites I've used will just immediately say "this email address is already registered... did you forget your password?" Just knowing an email address is already in use on a given site does not in itself represent a security breach.
One possible solution would be to only enable POST requests for that method.
And since you cannot invoke services from JavaScript from another domain (XSS - Cross-site Scripting) without your authorization, then you would be protected.
However this technique would prevent malicious users from calling your web service to discover user names but this wouldn't prevent the user to automate a process to simulate user entering data in a text box to force a call to the service, in that case, perhaps you could allow just a number of requests per user in an X amount of time.
You could keep track of the number of attempts using the Session object from your web service
Another approac would be to add a re Captcha to your site, however this would decrease the level of responsiveness if you used to allow your users to capture a user name and as soon as they write you call your service. Implementing would require your users to write the auto-generated captcha in order to submit your data

Persisting data cross domains?

I have 2 applications, each in different domains. When a user comes to the first application, clicks a link, the user is sent to the second application.
My problem is as follows: I need to persist a sessionId from the first application to the second application. Simple enough but here's the catch. I can't use query string and I can't use cookies(since in different domains). I was thinking, is there a way to insert custom values into HTTP Headers or set some form values on an intermediate page which would then POST to the second application? So the process would be as follows:
User clicks a link on the first page, this takes the user to an "intermediate" page, this "intermediate" page sets a sessionId value in the form or http Header, then the "intermediate" page sends the user to the second application via a POST where the app will have the sessionId.
I can't use a Server.Transfer since the app is not on the same server. Help?
This is how Microfot tried to do it Does Issuing Passports Make Microsoft a Country?.
You could try and make a secure SOAP or XML request with a secure token referencing a session id you stored for the user in a shared database. You could then load the user's session based on that session id stored in the db if a match is found.
One way that you could do it is to use webservices. Before the user is to switch sites, you could give the user an unique authentication token that has been agreed upon prior to leaving.
Another thing you could do (this is not a great solution, but it works) is to use frames, and to send the child frame information through javascript (login information). I really don't like this method, because it presents so many problems that its best avoided.
What I mean:
Web services: Communicate with the other site to say "this user is currently logged in here," you can do this at login (depends how much you trust the other domain), or you can do it when the user requests to leave
Giving the user an authentication token: You can post it as a form element. Or if you had an agreement with both domains you could send it to a URL that could later be interpreted as a rediection service+authentication token confirmation portion. I.E.: domain.com/page/token+pageid-mixture
Use OpenID. It's designed for this purpose (common authentication to web sites on multiple domains). The protocol's been under development for years and has probably encountered and solved a lot of the problems you'd be likely to run into if you roll your own solution.

Using asp.net, how do I redirect a user and change the POST data at the same time?

I have a single sign-on solution, meaning that the user will login to one site and be redirected to another. When I redirect the user I want to pass along a key that can be used to verify the user's authentication status.
Most of the examples of single sign-on I read show the login site passing the encrypted key has a query string value. I don't think this is a very good solution because it's not very REST-ful or whatever you want to call it. Instead I'd like to pass the encrypted key in the POST data. So when the user logins in, they are POSTing to another url.
Unfortunately I don't know (yet) how to do this with the Response.Redirect or Server.Transfer. I think Response.Redirect passes the same POST data along when it redirects.
Does someone know how to redirect a website user in asp.net, changing the POST data while redirecting?
(bonus question: can you change a GET to a POST while redirecting?)
Server.Transfer has the ability to maintain form data (POST values) in transition, because it is essentially transferring the same request sent by the user to a new endpoint.
Request.Redirect cannot persist POST data because a redirect is essentially sending a response back to the end-user which says "go here instead". The client then initiates a new request to that new endpoint. The client does not re-submit the POST data on the second, separate request.
However, neither POST nor GET alone are more or less RESTful - both are strings of data, just in slightly different parts of the request. Having clean, querystring-less URLs might "look REST-y", but it is cosmetic.
Here's a diagram of how the two different approaches work. As you can see, in the Redirect case, changing the POST data simply isn't possible because it's in the client's hands to form the new request to the target URL; and in the Transfer case, it makes no sense to (even if it was technically possible) because if you do need to pass additional data to the new handler, you can do so yourself:
alt text http://rexmorgan.net/rr_vs_st.jpg

Resources