During registration I am asking for username, email, and password. I am checking if the username and email is unique via the following end points
HEAD /auth/:email
HEAD /users/:username
Uniqueness of emails and usernames is split into auth and users resource because I thought when logging in I am asking for email so that should be in the auth and checking if the username is unique or not can go in users.
Login happens at the following endpoint
POST /auth/login
A new user is created at the following endpoint
POST /users
This is a stateless API and I am wondering if my routes look RESTful?
I am wondering if my routes look RESTful?
REST doesn't care what spelling conventions you use for your resource identifiers, so long as they conform to the production rules described in RFC 3986.
See, for instance: Tilkov 2014.
Instead, you should choose your identifier spelling conventions to make things easier for your human beings: what spellings are easy to document? what spellings are easy to recognize in the access logs? and so on.
You might be better off with a single resource that reports the status of the email address and username together, rather than using two different reports to do that.
Similarly, using HEAD requests is a bit weird; you are apparently using metadata in the transfer of documents over a network domain to communicate your business semantics, which (a) is what the documents are for and (b) is an example of "accidental complexity" -- I won't go so far as to guarantee problems down the road, but you are certainly inviting them, and it's not obvious that the current benefits outweigh that risk.
Related
When an authenticated user wishes to access a resource which he exclusively owns, it seems redundant to specify the user id in the URL path.
Thus, in the following examples, which is the more appropriate way to name my API endpoint?
Example 1
User wants to change profile pic
PUT /users/{id}/profile-pic
or
PUT /profile/profile-pic
Example 2
User wants to add a hobby to his profile
POST /users/{id}/hobbies
or
POST /profile/hobbies
It's a joy to see people paying attention to their API design in terms of URI and responses. An API that is not well designed is going to quickly die since people will avoid using them.
Even if it's not going to be public and no one will use it aside from yourself or your team, think of your colleagues and your future self and take some time to think about how your URIs will look like.
Back to your question my friend, according to the hands-on restful API design patterns and best practices book, that I invite you to read,the REST API is composed of four unique archetypes, as
follows:
Document: The document is the base for a resource representation with a field and link-based structure.
https://api-test.lufthansa.com/v1/profiles
https://api-test.lufthansa.com/v1/profiles/customers
Collection: A collection is also a resource, and it is a directory of resources managed by the API providers or servers.
https://api-test.lufthansa.com/v1/profiles/customers/accountbalance
https://api-test.lufthansa.com/v1/profiles/customers/memberstatus
Stores: A store is a resource repository managed by the client. The store allows the API client to put resources in, choose URIs for the resources that get added, get them out, and delete them when it decides.
http://api.example.com/cart-management/users/{id}/carts
http://api.example.com/song-management/users/{id}/playlists
Controller: Controller resources are similar to executable methods, with parameters and return values. REST API relies on controller resources to perform application-specific actions that do not come under any of the CRUD methods.
POST /alerts/245245/resend
So, in your case, you can follow the API design of GitHub API. Look how they are retrieving the projects of an organisation. Yours would look this way:
PUT /users/{id}/profile-pic
POST /users/{id}/hobbies
I'm sorry for making it long, I wanted to base my perspective on something concrete.
When an authenticated user wishes to access a resource which he exclusively owns, it seems redundant to specify the user id in the URL path.
It shouldn't; the semantics of a resource identifier and the semantics of an Authorization header are different.
The fact that only Bob can get a copy of /profile/Bob is a matter of access policy, not message semantics.
Review Fielding's definition of resource. "Bob's profile" and "Alice's profile" are distinct nameable information (assuming for the moment that Bob and Alice are themselves distinct) and therefore should have different identifiers.
That's the "RESTful" answer.
In practice, HTTP has special rules about authentication, and the handling of authenticated requests means that you'll probably "get away with" treating the Authorization header as part of the identifier of the resource (particularly in the case where an authorized user is only allowed to access their own resource hierarchy).
I have an application backed by RESTFul API. The application have user management section through which an admin user can manage other users. One sample URI for one of the API operation endpoint is below.
Update User : POST https://example.com/api/users/user1
Here user1 is the Username of the user being edited by the admin.
Suggestion from the security side is to remove the username from the URI since it is sensitive info and since it is part of url it will be recorded in network logs. Solution suggested is to pass the username data in POST Request Body .
Moving the data to request body is fine. But if I remove the username from URI ,the URI will be like "**POST https://example.com/api/users**" . This clearly doesn't look like a valid REST URI. And my USER entity doesn't have any other unique property which can be used in the URI.
Is there any recommended way to form a proper REST URI in such a scenario ?
POST /api/users
This clearly doesn't look like a valid REST URI.
Sure it does.
REST doesn't care what spelling you use for your resource identifiers, so long as the spelling is consistent with the production rules in RFC 3986.
That said, there's no particular reason that the identifier for a document needs to include sensitive information.
There are a couple of possible solutions - if the client and the server both know the sensitive data, then you can use a hashed value, rather than a raw value, as part of your identifier.
That's not ideal: we have mechanical ways of communicating URI that accept parameters, but no standard that I know of for communicating that some value should be hashed first.
If code-on-demand is an option, you might be able to manage to instruct the general purpose client to hash the data before sending it.
Otherwise, I think you are reduced to communicating the hashing out of band -- imagine a web form that instructs the human being to type in the hashed value of the sensitive information.
REST is optimized for the use cases that it was optimized for, and that means that some other use cases are more clumsy than we might like. Hooray for trade offs.
One way is to use an "id" instead of "username":
https://example.com/api/users/{id}
where "id" is usually a UUID https://en.wikipedia.org/wiki/Universally_unique_identifier
I'm kinda surprised I don't see this in more REST discussions, but I'm debating how to best provide a list of things to a user, based on who the user is, or what they have authorization to see.
For example, let's say that we have an API for a bookstore. I might have a resource URL of /books which would list all books. But if my application logic is such that some books are viewable to users who are anonymous, but others are only viewable to those who are logged in, I'm a bit more uncertain the best way to go.
Obviously, programmatically I could filter based on the identity of the user (gleaned from their API key or whatever creds I'm using) but I feel like that's a bit 'off' from the standpoint of REST design.
Feels more right to have two endpoints; let's say one for /books/public and one for /books/restricted and we can say that the latter returns a 401 if the user isn't logged in. Easy enough.
But that pattern breaks a bit if the books in question are just a list of books that the user has read or has bought or have some other relation to the user. I've seen some API's that would do something like /my/books in that case, but that (again) feels off since the /my/books isn't a unique URL per se, it changes based (again) on a header value (API key, etc).
This leaves me to think that maybe the "best" approach is to do something like /books/users/1235 or /users/1234/books to get the books that 'belong' to user 1234, and then return a 401 if someone not authenticated tries to hit that URL, or a 403 if they're authenticated but not authorized to view that resource.
I guess that's a lot of background to my main question: What's the best practice for REST API URL design when the resource data is dependent on user identity?
Rest is not a standard so there is technically no right or wrong way to accomplish what you're after. Having said that, I'll give you my opinion.
I propose you simply use /books unless there is a very specific need for a service or user to see which are unique to them and those that are public. In which case I suggest doing all three. The fact that there could be more or less content at the /books endpoint based on the user's privileges doesn't alter the intent, it enhances it.
But that pattern breaks a bit if the books in question are just a list of books that the user has read or has bought or have some other relation to the user. I've seen some API's that would do something like /my/books in that case, but that (again) feels off since the /my/books isn't a unique URL per se, it changes based (again) on a header value (API key, etc).
I believe providing a /my/books endpoint is ideal if the content is intended to be private. If your reading list IS private and specific to your account then having an endpoint without that is masked significantly dramatically reduces the risk of having user-identifying information leak via the url.
In the event that reading lists can be shared then you would want there to be a a discrete action. If a user wishes to share their reading list or a subset therein they would compose the list and a new endpoint would be created specifically for it like /book-lists/xxxx-xxxx-xxxx. If your user's reading list is public by nature then /my/books would simply redirect to /booklists/xxxx-xxxx-xxxx
This leaves me to think that maybe the "best" approach is to do something like /books/users/1235 or /users/1234/books to get the books that 'belong' to user 1234, and then return a 401 if someone not authenticated tries to hit that URL, or a 403 if they're authenticated but not authorized to view that resource.
I'm not sure if you are referring to the reading list or the first concept of filtered results by some form of credentials.
/books/users/1234 would suggest a correlation to users from the book's perspective. This would be more applicable for authors or publishers, people that are actually affiliated to books in some deeper connection other than your examples above elude to. The same logical connection, for me at least, applies to /users/3493/books but to a lesser extent.
I think as a general approach, you should scratch both of these out if you have any desire for the public links to be shared. You are potentially making a very convoluted structure that could ultimately result in people getting really confused why their friend can't see a list of novels because she sent her search results with a url had been "personalized" and thus secured.
Obviously, programmatically I could filter based on the identity of
the user (gleaned from their API key or whatever creds I'm using) but
I feel like that's a bit 'off' from the standpoint of REST design.
No, it is not off, because the credentials are part of every request and the response can be dependent on request parameters...
The url depends on whether you want to share personal data with others:
if you want to share the url
/users/{userId}/favouriteBooks/
/books/favouriteOf:{userId}/
if you don't want to share the url
/books/favourite/
Keep in mind that you always can change the url structure as long as your service applies the HATEOAS principle...
I have an API that provides an Account resource based on the authentication (login) that is supplied. As a user can only have one account, and can only see it's own account and not those of others, this API will basically be a single resource API in all cases.
So to keep things simple, I have this resource under the url accounts/ and when you access accounts/?username=dude&password=veryhard you'll get your account data (if you dohn't supply authentication you'll get a 403).
Now I wonder if this is RESTful. Also, you should be able to update your account info, and I wonder if PUT would be appropriate. In my knowledge, PUT should be done on a unique URI for the resource. Well, is this a unique URI for the resource? Generally a URI for an account would look like accounts/3515/ where 3515 is the account id. However, users don't know their account id. Also, there should be more ways to log in, instead of a username + password you should also be able to use a token (like accounts/?token=d3r90jfhda139hg). So then we got 2 URL's that point to the same resource, which also isn't really beautiful for a RESTful URI, is it?
So, what would be the most RESTful solution? Or should I not do this RESTful?
REST purists will consider that use of /accounts/ to obtain a single account is bad practice as it should specify a collection. Instead consider a key which cannot be mistaken for an ID, for example if your IDs are UUIDs then use a token such as 'me' so your URL is /accounts/me. This has the advantage that if later on you wish to obtain different account information, say for example you need to list users or you have an administration system using the same API, then you can expand it easily.
Putting username and password in the URL is also not pure REST. The query parameters should be directly related to the resource you are obtaining; commonly filtering and limiting the resources returned. Instead you should seriously consider using something like HTTP Basic authentication over an encrypted (HTTPS) connection so that you separate out your authentication/authorisation and resource systems. If you prefer to use a token system then take a look at oauth or hawk.
Finally, yes if you use PUT you should supply a full resource identifier. Given that it is very common for systems to read data before updating it the lack of ID won't be a problem as that will come back as part of the prior GET.
Yes accounts/?username=dude&password=veryhard is a correct REST URL.
PUT is used with an id if it used to update a resource, if you use it to create you must supply an ID. otherwise you use post to create a resource without id
We are in the early design stages of a major rewrite of our product. Right now our customers are mostly businesses. We manage accounts. User names for an account are each on their own namespace but it means that we can't move assets between servers.
We want to move to a single namespace. But that brings the problem of unique user names.
So what's the best idea?
Email address (w/verification) ?
Unique alpha-numeric string ("johnsmith9234")?
Should we look at OpenID?
EMAIL ADDRESS
Rational
Users don't change emails very often
Removes the step of asking for username and email address, which you'll need anyway
Users don't often forget their email address (see number one)
Email will be unique unless the user already registered for the site, in which case forward them to a forgot your password screen
Almost everyone is using email as the primary login for access to a website, this means the rate of adoption shouldn't be affected by the fact that you're asking for an email address
Update
After registration, be sure to ask the user to create some kind of username, don't litter a public site with their email address! Also, another benefit of using an email address as a login: you won't need any other information (like password / password confirm), just send them a temp password through the mail, or forgo passwords altogether and send them a one-use URL to their email address every time they'd like to login (see: mugshot.org)
OpenID is very slick, and something you should seriously consider as it basically removes the requirement to save local usernames and passwords and worry about authentication.
A lot of sites nowadays are using both OpenID and their own, giving users the option.
If you do decide to roll your own, I'd recommend using the email address. Be careful, though, if you are creating something that groups users by an account (say, a company that has several users). In this case, the email address might be used more than once (if they do work for more than one company, for example), and you should allow that.
HTH!
I like OpenID, but I'd still go with the email address, unless your user community is very technically savvy. It's still much easier for most people to understand and remember.
If you use an email address for ID, don't require that it be verified. I learned the hard way about this when one day suddenly the number of signups at my site drastically decreased. It turns out that the entire range of IP addresses including my site's IP was blacklisted. It took a long time to resolve it. In other cases, I have seen Gmail marking very legitimate emails as spam, and that can cause trouble too.
It's good to verify the email address, but don't make it block signups.
Right now our customers are mostly businesses.
People seem to be missing that line. If it's for a business, requiring them to login via OpenID really isn't very practical. They'd either have to use an external OpenID provider, or their poor tech people would have to setup and configure a company OpenID.
If this were "should StackOverflow require OpenID for login" or "Should my blog-comment-system allow you to identify yourself via OpenID", my answer would be "absolutely!", but in this case, I don't think OpenID would be a good fit.
If most of your customers are mostly businesses then I think that using anything other than email creates problems for your customers. Most people are comfortable with email address login and since they are a business customer will likely want to use their work email rather than a personal account. OpenID creates a situation where there is a third party involved and many businesses don't like a third party involved.
I think that OpenID is definitely worth looking at. Besides giving you a framework in which to provide a unified id for customers, it can also provide large businesses with the ability to manage their own logins and provide a common login across all products that they use, including your own. This isn't that large of a benefit now when OpenId is still relatively rare, but as more products begin to use it, I suspect that the ability to use a common company OpenId login for each employee could become a good selling point.
Since you're mostly catering to businesses, I don't think that it's all that unreasonable to offer to host the OpenId accounts yourself. I just think that the extra flexibility will benefit your customers.
If you are looking at OpenID you should check out http://eaut.org/ and http://emailtoid.net. Basically you can accept email addresses for a login and behind the scenes translate them to OpenID without the user having to know anything. Its pretty slick stuff...
I personally would say Email w/ Verification, OpenId is a great idea but I find that finding a provider that your already with is a pain, I only had an openId for here cause just 2 days before beta I decided to start a blog on blogspot. But everyone on the internet has an email address, especially when dealing with businesses, people aren't very opt to using there personal blog or whatnot for a business login.
OpenID seems to be a very good alternative to writing your own user management/authentication piece. I'm seeing more and more sites using OpenID these days, so the barrier to entry for your users should be relatively low.