Platinum Partner
java,patterns

The Pedantic Guide for a RESTful Registration Use Case

Registration is one of most implemented use cases ever, but things get a bit different when you try to implement it in a RESTful Web-Service.

Before I start the discussion about the registration use case, a list of terms for disambiguation:

  • Application means a Java EE Application. (Arena-PUJ is the Java EE Application I am doing my REST experiments)
  • Service is a RESTful Web-Service. (back-end of a Java EE Application)
  • Client Application is any software that can communicate with the Service using the HTTP Protocol. (front-end of a Java EE Application)
  • End-user is a person interacting with an Application.

The Registration Use Case

The registration use case I am taking as example is the one I just implemented in the PUJ Project - a classical Registration User History adapted to the REST terminology:

  1. An end-user opens a client application and type some personal information like name, email and password in a form.
  2. When the customer presses a [submit button], the client application do a POST request to a RESTful web-service.
  3. The web-service handles the registration in three steps:
    1. Validates the customer information (form data)
    2. Creates a new account record in the database
    3. Sends a confirmation email to the new customer.
  4. The web-service responds OK (HTTP 200) to the client application. The client application informs the customer that he will receive a confirmation email and how to proceed from that.
  5. The customer receives an email containing a confirmation URL he needs to click to activate his account.
  6. The customer clicks on the confirmation URL to activate his new account.
  7. Once the web-service receives the HTTP GET request from the email URL, it changes the status of the account resource from NEW to ACTIVE and redirect the customer to a further instructions URI (HTTP 303).

The above use case has several variations, and I omitted the exceptions for the sake of clearness. The important points for our discussion are highlighted in bold font and explained below.

Confirmation e-mails are not REST

A Natural Born RESTtafarian would realize by a glance the issue here, but if you are not that updated with the HTTP Protocol and the HATEOAS constraints, here comes the problem:

An HTTP GET method is Idempotent, what means it should never change the state of a resource (URI) either by direct invocation or its side effects. As soon the customer receives the email and clicks on the confirmation URL, he is triggering a GET that will change the status of his account from 'NEW' to 'ACTIVE'. This status change should never be done through a GET method if you want your Service API to continue to be called REST.

You can take a rest now, a coffee, take a while to digest the idea that most of the confirmation emails out there are not REST. Doesn't matter how beautiful your Web-Service is, if an end user clicks on a GET URL to confirm his registration, your efforts were in vain - your API is not REST.

Flames aside, the simple fact is that e-mails containing a confirmation URL is the de facto standard solution for the registration use case on the web. Due to that reason I adopted the word pedantic in the title of this blog, because most of the developers just ignore that detail and go on with the widely adopted solution. I will keep the pedantic mood for now, and the rest of this post is to explain you the workaround I adopted to keep the chances to call my service as RESTful API. I will start enumerating the options you have once you realize the conflict between the REST constraints and the GET URL in a confirmation e-mail:

  1. Ignore the problem and just use the GET URL in the confirmation email. That was one of the most suggested solutions in the several mailing lists I discussed the conceptual problem. A lazy but yet very pragmatic solution since it works like a charm. If you can sleep at night knowing your API is abusing the HTTP Protocol, go for it (and then you can stop reading this blog). IMO: it is just irritating to know I am coding the wrong thing, and since I am producing a research-purpose-open-source-pet-project I will try something more elegant.

  2. Delegate the security responsibility to the client, leaving the Service API 100% REST compliant. You can secure the communication layer between the client and the server and then you don't need the security information on the service layer anymore. The client becomes the security master and every request done by the client is blindly attended by the server. It sounds a good alternative, but the problem is: sensitive resources should be protected in your service layer. To delegate the data encapsulation to an external layer seems just too risky - unless you produce the service and the client by yourself and you have some way of guaranteeing the information security. IMO: sooner or later this decision will cost some stress in terms of maintenance.

  3. Use the SMTP to handle the registration, asking the user to respond the email instead of clicking in the URL. IMO: it solves a problem creating many others because as soon you have an Inbox in your solution you also have SPAMs and your customers trying to send e-mails to ask something in that Inbox, etc. Also, the confirmation is asynchronous and dependent of external infra-structure. There is no guarantee of delivering of the customer e-mail - the SMTP server of the customer has a problem, and it becomes your application problem too. There is a delay between the moment your customer respond the email and the moment his account is actually activated. IMO: More configuration requirements, more maintenance issues, a potential mess. But no, I don't have a killer argument against that, just a strong feeling against that.

  4. Use a mediator between the service and the end user , forcing the registration operations to pass through a client-application first. When the user clicks on the URL in the confirmation email, he will access a client application (and not the service), and the client application is responsible to handle the request - eventually doing a POST to confirm the registration, what is the REST way of doing that. That little change in the registration workflow makes the API RESTful again and also add some extra security and usability features. It causes some impact in the user experience, but I believe the complexity added to the user is minimum and quite acceptable. IMO: that is the best solution, and after implementing that I also found other benefits of that decision, as I explain below.

Some interactions between an End-User and a RESTful Web-Service should be intermediated by a Client Application

The problem of our previous Use Case is a GET method changing the state of an account resource (URI) and it contradicts the idempotence property of the HTTP GET method. Due to that I rewrote the original use case to fits the REST constraints.

A RESTful version of the Registration Use Case

  1. An end-user opens a client application and type some personal information like name, email and password in a form.
  2. When he customer presses a [submit button], the client application do a POST request to a RESTful web-service, including the URL where the user should visit in order to confirm his registration.
  3. The web-service handles the registration in three steps:
    1. Validates the customer information (form data)
    2. Creates a new account record in the database
    3. Sends a confirmation email to the new customer.
  4. The web-service responds OK (HTTP 200) to the client application. The client application informs the customer that he will receive a confirmation email and how to proceed from that.
  5. The customer receives an email containing a confirmation URL he needs to click to activate his account.
  6. The customer clicks on the confirmation URL to activate his new account - and get redirected to the client application (not directly to the service)..
  7. The Client Application receives the HTTP GET Request and proceed the confirmation of the registration doing a HTTP POST to the Web-Service
  8. Once the web-service receives the HTTP POST request from the Client Application, it changes the status of the account resource from NEW to ACTIVE and responds OK (HTTP 200) to the client application.
  9. The Client Application notifies the end user that his account was activated.

Notice that only two things actually changed from the original use case:

  • The data sent from the client application in the step 2 contains now an URL to be used to compose the confirmation URL included in the confirmation email. The service no more build this URL based on its own domain. The hash included in the message remains the same, and the logic to validate the registration in the server also remains the same.

  • The navigation of the user in the step 6 changed from "a Service Resource" to "a Client Application resource". The Client application should handle that, asking the end user to click a button or even using some automatic feature to redirect the end user GET Request to the Web-Service POST Request. The Client Application is the mediator between the end user and the web-service.

Benefits of the mediator in the Registration Use Case

  • The confirmation is done through a GET Idempotent method, so the user can clicks several times in the email URL without unwanted side-effects. Who handles the confirmation operation is the Client Application and the back-end part of the Java EE application remains a pure REST API.
  • The end user doesn't need to know where the web service is hosted, right? Less exposed the RESTful Service is, more secure it is.
  • Several applications can share the same service, using different languages and technologies to interact with its end users. Your service don't need to know about how these applications communicate with their users.
  • The Client Application can handle the end users requests in a much more friendly way, including the localization of the messages and pages shown to the end-user. This would be a difficult thing to do in the server side, specially if the same server supports several Client Applications.
  • If the service has a temporary problem, the Client Application can give the user some explanation about that, much better than an HTTP Error code.
  • If the service change its host address, the Client Application can adapt its addresses mapping without bothering the end users. If a user receives a confirmation email and the service changed the host address, the user will never have any problem because that.

The idea of a mediator may be adopted in several other scenarios, just thing a few minutes about that.

Try it online

You can try the RESTful Registration Use Case on my online demo, just do that:

  1. curl -d "name=NAME&password=PASSWORD&login=LOGIN&email=EMAIL&url=http://fgaucho.dyndns.org:8080/arena-dwr/confirm" http://fgaucho.dyndns.org:8080/arena-http/user

    Where:

    • NAME: your name (max 20 characters)
    • PASSWORD: a password (max 32 characters)
    • LOGIN: your user name (max 20 characters)
    • EMAIL: your email (you should use a real email in order to receive the confirmation message.)

    An example:

    curl -d "name=Felipe&password=test&login=fgaucho&email=useless@gmail.not&url=http://fgaucho.dyndns.org:8080/arena-dwr/confirm" http://fgaucho.dyndns.org:8080/arena-http/user

Notice you are sending a POST Request to the address http://fgaucho.dyndns.org:8080/arena-http/user. After receiving the confirmation email, click on it to see that you are going to other address. You can try that without risk since it is my personal machine (lab) and all data will be erased in the next commit. Other point: the activation of accounts are not enabled, so the whole registration process should work, but you will not be able to do much with your new account anyway :). If you are just paranoid about your private data, use a temporary email for testing or do create a fake email account somewhere.

Are you using an Operational System without the CURL tool? Perhaps this link can can help you.

Summary

REST is a good architecture style, sometimes it imposes limitations on what you can do, specially if you consider that new protocols are coming to the game soon: SMS, SMTP, Digital TV ones, etc. The HTTP protocol should be preserved to keep the web clean and robust as we know it. if you abuse the HTTP Protocol due to commercial benefits, it is important to make it clear that you are doing that for a reason and more important: to accept that if you abuse any protocol you are not using the protocol anymore. It may sounds too pedantic, or not, and I leave a large space here for your considerations and eventually for proposing a better solution. We are all here to learn, in this times of flames it is good to spread this motto ;)

My self-education on the REST technologies are still in the beginning and I am thankful for all of those sharing their knowledge about that.

From http://weblogs.java.net/blog/felipegaucho

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}