I want to provide the ability for resetting a user`s password. This call obviously must not require authentification.
First I thought of something like this:
DELETE /users/{id}/password: generates a reset token that gets sent to the user via email
POST /users/{id}/password: requires the new password and a valid reset token in the body
But the problem is, the application or website cannot provide me the ID of the user, because all it can ask the user for is his email address.
There are a number of other (unauthenticated) calls to our API, where the ID is not present and the user is only identified by its email.
We discussed the following solutions in our team:
Replacing the ID in the URL with the users email
Cut out the ID from the URL and provide the email with query parameters
If I had to choose between those two, I would take the first one, because I think it is not RESTful to provide something essential with query parameters, as they always represent something optional, like filtering a resource.
Are there better ways to design these URLs or is replacing the ID with the users email just fine concerning REST contraints?
POST /passwordResets
{
"emailAddress": "bob#example.com"
}
Then you have the flexibility to reset by userId also, and you can track the resets just like any other resource for auditing purposes.
Of your two options, the first isn't awful if you can use an email address to uniquely identify a user. It's conceptually wrong, though, because there should be one canonical location for each resource, and now you have two - /users/bob/password and /users/bob#example.com/password.
The second option is just wrong. /users/password is not meaningful. The direct implication of /users is that the next path element is a user. /users/password is closer to RPC than REST.
Related
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.
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.
As far as REST APIs go, which is the better structure to follow in general?
Assume GET/PUT/POST/DELETE for all resources.
1) Use currently signed in user for /users/**/* routes.
/users
/users/password
/users/email
/users/preferences
/users/documents
/documents/:id
2) Having absolute paths with IDs and using /users/:id for currently signed in user?
/users
/users/:id/password
/users/:id/email
/users/:id/preferences
/preferences/:id
Does it matter?
If the resource you are referring can be multiple, you should go with
/resource/resource_id
In the above case, user can only be the current person, so using a pattern like /users/user_id, sounds odd. Because, you will have to handle different cases like What if a logged in USER A triggers an api call with a different user-id USER B??
You can have a namespace like /profile for managing the email, name, image etc. You don't have to make it as /users/profile as it is implicit that the data is going to be manipulated / accessed for the current logged in user.
Both are fine. What's nice about creating unique endpoints for every user, is that one day you can allow user X to access information about user Y.
The pattern I followed in a recent API was to create a unique endpoint for every user, but 1 endpoint /current-user that redirects to the /user/:some-id.
A url might indicate an identity. It makes a lot of sense that other resources might refer to user as a 'creator' or 'modifier' of sommething, and in those places you might want to use a url (and not just a userId).
I have a REST based service where a user can return a list of their own books (this is a private list).
The URL is currently ../api/users/{userId}/books
With each call they will also be supplying an authentication token supplied earlier.
My question(s) is:
Is supplying the userId in the URL redundant? As we get a token with each call we can find out which user is performing the call and return their list of books. The userId is not strictly required.
Would removing the userId break REST principles as /users/books/ looks like it should return all books for all users?
Should I just bite the bullet and authenticate them against the token and then check that the token belongs to the same userId?
Short answer
You could use me in the URL to refer to the current user. With this approach, you would have a URL as following: /users/me/books.
An answer for each question
Is supplying the userId in the URL redundant? As we get a token with each call we can find out which user is performing the call and return their list of books. The userId is not strictly required.
You could consider doing something like this: /users/me/books. Where me refers to the current user. It's easier to understand than /users/books, which can be used to return all books from the users.
For some flexibility, besides /users/me/books, you could support /users/{userId}/books.
The URL /users/me can be used to return data from the current user. Many APIs, such as StackExchange, Facebook, Spotify and Google+ adopt this approach.
Would removing the userId break REST principles as /users/books/ looks like it should return all books for all users?
I don't think it will break any REST principles, but I think your resources will not be properly indetified. As I answered above, I would use /users/me/books and also support /users/{userId}/books.
Should I just bite the bullet and authenticate them against the token and then check that the token belongs to the same userId?
When using the userId in the URL to request private information from a user, there's no harm in checking if the token belongs to the user with the userId included in the URL.
I dont think that removing userId would break any REST principles, because after all, /users and them /books, its a little bit openend to interpretation and REST says basically nothing about it, on the other way if you are going to stay with the id inside the request, you MUST check that the user id is the same as the connected user, anyways, for me the 1 is redundant because you already have that information, plus, every time you are going to make useless checks because anyways the authentified userId is the one that you are going to trust in all cases.
Best Regards
REST is resources oriented so in your point what is the resource user or book. My point of view it's book. And I think you can request this resources
/api/books?user={userid}
But this URL can not solve your permission issue so you have to do it in your code with token information you can get with a OAuth2 protocol or whatever.
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