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? - rest

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.

Related

REST API architecture

I just started to construct REST API refer to this guide.
It's my first time coustructing REST API architecture, so something ambiguous.
POST vs GET
Before learning about REST API, I choose POST when I don't want form-data being exposed(e.g. user's ID, password, phone number).
But in REST API, POST means 'create new resource' if what I learn is right.
If so, what is the proper method for following case :
'check user's ID is duplicate or not', 'find my id or password'
represent specific action
REST API guide says that use noun to represent.
I Usually named function or method by verb+noun combination(e,g, checkId, findPassword).
Then what is proper(or better) way to represent?
GET /user/check-id
GET /user/id/check
GET /user/id/duplicate
Take a look at the RESTful verbs. POST is definitely used to create something, and GET is a query. That being said, you are absolutely right that GET URL Parameters are often logged all over the place, and you should not use them in GET urls if they contain sensitive data.
To check if a user's ID is a duplicate, I'd do a POST with the user's ID, and return a HTTP 409 code if it already exists.
The find password is a different question. In short, don't do it. You should NEVER, EVER, EVER store a user's password in plain-text. Doing so is negligence in today's computing world. Resetting a password should involve creating a password reset request (A POST to a /user/id/reset), which results in a password request being sent via another channel, but never, ever return a password from a GET request.

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.

RESTful API design: Validity of username

I am designing a RESTful API which should return the validity of a username for registration. The invalid cases include:
duplicate username
too short or too long
invalid characters
My current design is:
GET /valid_username/{username}
returns 204 for valid username
returns 404 for invalid username with {err: 'DUPLICATE_USERNAME'}
Is this the preferred way in RESTful API?
Is this the preferred way in RESTful API?
I don't think so.
The guiding star for designing a REST API is a single question: How would you implement this as a web site?
As an integration protocol, when the client submits the username, you either want to advance them to the next form, or you send them back to the "previous" form with a bunch of error messages.
Technically, you could use 204 to do that in the happy path, with a Link in the meta data that the client could follow to go from the success page to the next. But it's a lot more likely that you would just send a representation of the next page at once; so 200 would be your most likely play.
For the unhappy path, instead of sending a representation of the next page, you'd probably send a representation of the current page with the data pre-filled in and the errors highlighted.
So key point: the human being is looking at the rendered representation, not at the meta-data in the headers. The browser is the audience for the metadata. The browser doesn't care anything about the semantics of the message, it just wants to know things like "can I cache this response?"
The most obvious choice of status codes for this case is: 200. Semantically, the representation of the integration resource change from one that would allow you to proceed (username Bob was available) to a representation that would force you to make another choice (username Bob is no longer available). The various headers in the meta data describe the appropriate caching policy to apply to this representation, and so on.
Technically, I think 404 "works", in so far that you can make it do what you want. The semantics are incorrect; from RFC 7231
The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists
My interpretation of that passage is that the server is claiming that the client submitted a bad request (all 4xx status codes share that meaning) , and more specifically that the spelling of the resource identifier is the root of the problem.
It's a bad fit because the server, in this case, isn't having any difficulty fulfilling the request -- it understands the request just fine; the "problem" is that the representation being returned isn't the one that the client is hoping for.
REST is about exposing, creating, and mutating resources. Each endpoint URI defines the location of that resource. In the case of a User resource, you would typically expose an endpoint to the collection of User resources with a URI like /users, and an endpoint for individual User resources of that collection with a URI like /users/{id}. Each endpoint is tied to a resource; not an operation. Endpoints that expose operations follow RPC architecture.
To do this RESTfully, your validations would be run when attempting to create a User resource using the user input. This could be done using an HTTP request line like POST /users. Upon invalid format of the username value, you would respond with a 400 status code, to indicate error on the user's part. Upon conflict with an existing username, you could return a 409 status to indicate a conflict between the request and internal API state. Your responses should also contain a body with further details of the issue. Upon a successful creation of a User resource, you should respond with a 201 status to indicate that the resource was created successfully.
Another way to go about this RESTfully, would be to key the individual User resource URI on the username, so that you would have something like /users/{username}. Then, to check if a username already exists, you would simply form a request like GET /users/{username}. If a User resource with that username does not exist, the API should respond with a 404 status, which would indicate to your client that the username is available. A response status of 200 would obviously indicate that the username is already in use.

Is leaving out the current user ID in a REST endpoint bad practice?

I'm currently writing my own REST API. One of my endpoints is named /api/profile, which takes either GET to retrieve or PUT to update this profile. I have been told that it's considered bad practice or plain wrong to not include any form of user ID, email or username in the URL, when calling PUT /api/profile. Every request has a Bearer token for authentication, which makes the server load the user in case and stores it in the request data. Upon updating information using PUT, I thought it'd be safe to assume that if no parameter has been supplied to the URL, the target is self, in this case, the authenticated user.
Am I wrong to make this assumption and/or is this a bad example of REST?
One of the architectural constraints of REST is to make your resources cacheable.
When you have some proxy or other cache between your client and server, the request line GET /api/profile cannot be cached, or another user would potentially retrieve the wrong profile.
You could use a Vary: Authorization header in your case to prevent this. But having an id in the URL will make unequivocally clear which resource you want to retrieve.
For PUT requests, this is not an issue as they won't be cached, but you should keep your URI design consistent.

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.