REST resources for a login/registration form - rest

I want to create REST login/registration URI in order to make a an existing user login or a new user to register. After a little search I found that most of such forms are designed using the following rules:
GET /login to get the login resource
POST /login to login and get back the user profile resource
GET /register to get the registration resource
POST /register to register and get back the new user profile resource
However, I think that this is not a 100% REST approach as one of the rules of REST is that resources should be nouns and not verbs (except from some special cases like a search api). What's the best solution for such a situation ?

There's no one right answer to this, so I'll attempt to give some ideas on a common ways to solve this.
Login
Login (aka Authentication) itself is typically handled in a non RESTful way, ourside, such as OAuth2. Should there really be a 'login' if HTTP is stateless? Every request should carry all the information to allow a server to authenticate the client. If you do want to really handle login as a RESTful endpoint, you could ask yourself: "What state am I changing? One way to answer this is that maybe you a creating a set of credentials". I'm assuming for now that you are looking for a best practice / common approach to this though, and not a very purist REST approach for this.
Current user information
Getting the current user is often handled via an endpoint such as /current-user or /whoami. Doing a GET request on this could either yield information about the user, or it could immediately redirect to a canonical user endpoint such as /users/1234. Executing a PUT request could again either update the user, or return a redirect to the actual user endpoint.
Registration
If you have a list of users on a resource like /users. It would kind of make sense to create a new user resource by doing a POST request on this collection.

Related

What is the best way to implement checking whether a username is already registered on the client side, if I want to keep my API RESTful?

As the title suggests, I am looking to have the client be able to check whether a username or email is already registered before the user submits the registration form. I had considered using an API endpoint that would return true or false for a given username, but this seems more RPC than RESTful. Is it bad practice to have such an endpoint if the rest of my API is RESTful? If so, what would a RESTful approach to this situation look like?
A key concept in REST is that anything that can be named can be a resource; this includes procedures. If you want to have an endpoint that accepts a username in the request body and returns true/false that's perfectly fine.
Alternatively, you can (or may already) treat a user as a resource. Take the GitHub API as an example: you can fetch a user by sending a GET request to https://api.github.com/users/{username}. If the user exists, and therefore the username is taken, you'll get back 200 OK. If the user does not exist you'll get 404 Not Found.
If you want to check if a username has been taken you can just issue a request for that username and then check the response. If you choose this approach HEAD is the more appropriate method. HEAD is essentially the same as GET except that the response body is empty. Since you don't need the body to determine if the user exists you can save a tiny bit of bandwidth with HEAD over GET.
You could do a POST /registrations and return a 400 with validation errors array and just have client side logic filter that array for invalid username. In other words, no reason you can't hit the endpoint multiple times. This should help decouple your UX from your API.

Creating user record / profile for first time sign in

I use an authentication service Auth0 to allow users to log into my application. The application is a Q&A platform much like stackoverflow. I store a user profile on my server with information such as: 'about me', votes, preferences, etc.
When new user signs in i need to do 1 of 2 things:
For an existing user - retrieve the user profile from my api server
For a new user - create a new profile on the database
After the user signs in, Auth0(the authentication service) will send me some details(unique id, name and email) about the user but it does not indicate whether this is a new user(a sign up) or a existing user(a sign in).
This is not a complex problem but it would be good to understand best practice. I can think of 2 less than ideal ways to deal with this:
**Solution 1 - GET request **
Send a get request to api server passing the unique id
If a record is found return it
Else create new profile on db and return the new profile
This seems incorrect because the GET request should not be writing to the server.
**Solution 2 - One GET and a conditional POST request **
Send a get request to api server passing the unique id
The server checks the db and returns the profile or an error message
If the api server returns an error message send a post request to create a new profile
Else redirect to the home page
This seems inefficient because we need 2 requests to achieve a simple result.
Can anyone shed some light on what's best practice?
There's an extra option. You can use a rule in Auth0 to send a POST to the /users/create endpoint in your API server when it's the first time the user is logging in, assuming both the user database in Auth0 and in your app are up-to-date.
It would look something like this:
[...]
var loginCount = context.stats.loginsCount;
if (loginCount == 1) {
// send POST to your API and create the user
// most likely you'll want to await for response before moving on with the login flow
}
[...]
If, on the other hand, you're referring to proper API design and how to implement a find-or-create endpoint that's RESTful, maybe this answer is useful.
There seems to be a bit of disagreement on the best approach and some interesting subtleties as discussed in this post: REST Lazy Reference Create GET or POST?
Please read the entire post but I lean towards #Cormac Mulhall and #Blake Mitchell answers:
The client wants the current state of the resource from the server. It is not aware this might mean creating a resource and it does not care one jolt that this is the first time anyone has attempted to get this resource before, nor that the server has to create the resource on its end.
The following quote from The RESTful cookbook provided by #Blake Mitchell makes a subtle distinction which also supports Mulhall's view:
What are idempotent and/or safe methods?
Safe methods are HTTP methods that do not modify resources. For instance, using GET or HEAD on a resource URL, should NEVER change the resource. However, this is not completely true. It means: it won't change the resource representation. It is still possible, that safe methods do change things on a server or resource, but this should not reflect in a different representation.
Finally this key distinction is made in Section 9.1.1 of the HTTP specification:
Naturally, it is not possible to ensure that the server does not
generate side-effects as a result of performing a GET request; in
fact, some dynamic resources consider that a feature. The important
distinction here is that the user did not request the side-effects,
so therefore cannot be held accountable for them.
Going back to the initial question, the above seems to support Solution 1 which is to create the profile on the server if it does not already exist.

How to design a restful url for login?

I did a research on this topic, but I still cannot find any answer.
I'm trying to use oauth2 and jwt to implement a web login function, then I need a rest style api between backend and frontend.
10 years ago, people just use ..../login to deal with it, but Restful api suggest that there is no verb in the url. So some people suggest that we can use ....../accesstoken, then POST username and password to get a token.
However, I think if we consider an accesstoken as resource, when we want to get the accesstoken, we should use GET method, isn't it?
So my question is: What is the best practice when designing a restful style url for login? Or just restful api is unable to achieve that?
Thanks!
===updated===
in spring oauth2, the default url it provide is post grant_type and relative info to the url /oauth/token. But shoud we use GET method to get resource?
I think "/login" should be ok. In the book, REST API Design Rulebook, here is a paragraph said "Like a traditional web application's use of HTML forms, a REST API relies on controller resources to perform application-specific actions that cannot be logically mapped to one of the standard method (CRUD)." which means the application-specific action, login can be seen as a controller resource. Since controllers are executed by POST method, the final resource can be presented as "POST foo.com/api/login".
The example given in the book is a controller resource that allows a client to resend an alert to a user: POST /alerts/245743/resend

Restful principles - sending user's identifier in HTTP headers

I'm creating restful api that is used by angular web page. I'm using token based authentication. Server side determines which user sent request based on token value, so I don't have to pass user id on URI. For example, request that returns all orders for logged (with token) user looks like this:
/api/orders
instead of:
/api/users/123/orders
Api is still stateless, but the same URI returns different data depending on headers. Is it consistent with Restful principles?
I think that this suggested API violates the address-ability feature of REST. The address of a resource should be in a form that is visible and readable (and some other things not related to your question...). One of the nice things of nice URIs is that one can link to it easily. Headers are actually hiding the real address of the resource hence making it impossible to link to it. So bottom line I would not go for such an API.

Representation of a User in REST

I'm slowly beginning to unerstand REST and theres one thing thats confusing me .
I understand that most of the things in REST is a "resource" . So i was wondering what kind of a resource would we be referring to in the case of a user signup / login ?
Is it users ? Then does it mean that a POST on users would signup for a new user . If that is the case , then how do i authenticate a user ? a GET on users with an encoded password / username pair?
I'm really confused with this.
I may be COMPLETELY wrong in my understanding given that i'm just starting to understand REST.
Any help is appreciated !
Thanks!
It's a bit of an unusual but common problem for REST. Keep thinking about resources.
When you login you're asking the server to create a session for you to access certain resources. So in this case the resource to create would be a session. So perhaps the url would be /api/sessions and a POST to that url with a session object (which could just be an object consisting of a username or password and perhaps the UUID) would create a session. In true REST you'd probably point to a new session at /api/sessions/{UUID} but in reality (and for security purposes) you'd probably just register a session cookie.
That's my own personal approach to login forms if I were to implement them myself but I always tend to use Spring security for that job so this requirement never really takes much consideration.
I am working on something similar and this is the solution I have taken so far. Any suggestions welcome :)
I have users exclusively for singup and account modifications.
GET /users/{id} gets a user for the profile page for instance
PUT /users creates a new user with username and password. In reality this should send an email with a link to somewhere that confirms the signup with a GET method.
POST /users/{id} modifies the user (for example change password)
DELETE /users/{id}
For authentication I tend to think that the resource I request is the token or the authentication. I have tried to avoid the word "session" because it is supposed to be anti-RESTful, but if you are just creating the illusion of an actual server-side session for your clients, I guess it is fine.
PUT /authentication/ with usename/password returns Set-Cookie with the pair user_id / hashed value. Maybe it should be POST. Not sure
DELETE /authentication/{user_id} just deletes the cookie and the user is signed out. Maybe instead of user_id it should be a unique token_id.
Resources can be created, read, update and deleted using a restful approach, see e.g.:
https://cwiki.apache.org/S2PLUGINS/restful-crud-for-html-methods.html
So if you'd like to administrate you users this would be the restful approach to do so.
If you'd like to authenticate the users which you have in your administration dataset you need
to design or select a restful authentication mechanism see e.g.
http://de.slideshare.net/sullis/oauth-and-rest-web-services
http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/
For a jumpstart on these issues you might want to check out dropwizard:
http://dropwizard.codahale.com/
A resource may have one URI or many
but One URI will have exactly one Resource
Therefore, When Authenticating a user, you are addressing a user who is already registered
While when registering, you are addressing the user (resource) which is yet to be registered.
All you need is a way to process it to your SERVER.
THIS is an example taken from SUGARCRM REST web services implementation.
REST is like http requests to your SERVER.
For eg, when implementing REST Web Services.
Every REST Request is going to same File say
www.your_domain.com/Rest.php?json={your_json_method:'method',params:'watever'}
Where in Json is the request you are sending as a parameters
Requesting to authenticate a user
{method:'SignUp', username:'abc', pass:'pass', confirm_pass:'pass'}
Requesting to register a user
{method:'Login', username:'abc', pass:'pass'}
by this way you can have as many params as you want
Remember JSON is not necessory to be used. you can use simple get params for your query