I'm still learning REST API principles and this one still confuses me. Password inside User Resource is private and of course cannot be placed in a response, while sometimes we need to get user data for public (e.g. when someone seeing someone else's user page). How do we handle this based on REST API principles? Should I remove password inside response before sending it?
Yes, you should not return the password in response. I would suggest you should create two DTOs
UserInputDTO: This contains the password and other values
UserOutputDTO: Here you have only those fields which are useful for the output and we can exclude password field and fields related to your internal implementation.
If your input and output looks same then you can add JsonIgnore annotation on the password field.
If by removing you meant setting it null then still the user can see the fieldname password, and if at any time you forgot to set it null then it will be a security issue. To solve this issue, you can use the JsonIgnore annotation.
Related
I read that the route for getting a nested resource in REST should look like this
/articles/:articleId/comments
The owner (:articleId) of the child resource will be visible.
But what if you have an owner that you don't want the client to know about?
For example, let's say I have an app where users have anonymous posts. I wouldn't want other users to see the client fetching the post by /users/123/post/321 because users could identify who wrote the post from the id and it wouldn't be anonymous.
Is the id necessary? Is it ok to instead do /users/posts/321 if all posts have a unique id?
There are no actual requirements for the URL format. It can be whatever you'd like it to be.
If it were me, I would use simply /posts/321 and leave users out of it, since a particular user isn't specified in your URL at all. I think that's the clearest way to handle it in your case.
I've extended the User model in my loopback application, and added phone number as a login method, I use the username field to do this, the only deal is that on login I get the 'email not verified' error, I have my own phoneNumberVerified field, and have overwritten the confirm method to validate the token against the emailVerificationToken and against the phoneNumberVerificationToken and update the corresponding flag, I thought of overwriting the original login method to not allow login only if both emailVerified and phoneNumberVerified fields are false (not just the email) but I don't know how to actually do the login the way loopback does it (I believe it creates an AccessToken or something), and I'm asking for some help on how to do this, thanks XD. I can do the overwriting and validations myself I just need to know how to do the actual login without using the original login method, since I'll be rewriting it.
So I figured out that I actually don't need email or phone number verified validation at all on login (later on the workflow will be required, but that'll be another use case, so it's irrelevant on login to me now XD). So when I was looking on how to overwrite the login method I realized that all the models code it's on the node_modules folder xD
node_modules/loopback/common/models/user.js
And found there in the login method a flag that validates if should check email verified or not, so on my startup script I just put this:
app.models.MyUser.settings.emailVerificationRequired = false;
That stops the email verified validation on login.
And maybe if some of you would like to override the login method I believe copying the whole method from the original user model up there and attaching it to your model and doing some modifications might work xD, it invokes the createAccessToken from the user model (itself) and that's what I believe creates the 'login', what I came to understand is that there is no "session" data, it creates an accesstoken when you successfully login, and as I've been doing just sending the token id to every request 'authenticates' your logged user.
Thanks for reading, have a nice day :)
I have a multi-tenant app in which user can select "current company" after they log in.
There is a DB per company but the model is the same, the workflow is the same, and the controller actions are same....The user can switch companies while being logged in and all actions need to be 'directed' to proper DB.
I know it is possible to customize context creation in EFContextProvider<T> by overriding CreateContext() but how do I pass the extra info (parameter, e.g. CompanyId) that would allow me to create context with correct connection string?
Is this possible?
I find the easiest way is to include the tenant id in a custom HTTP header.
Because the tenant id changes during the session, you probably want to create a custom Breeze ajax adapter (wrap the one you're using now) that sets this header dynamically during its implementation of the ajax method.
On the server you fish the header out of the request.
MAKE SURE YOU ARE VALIDATING USER AND HEADER ON THE SERVER
Assume I want to create a very simple todolist RESTful API, where each user owns a list of todos. The user is already authenticated over http BASIC or DIGEST.
At this point I am not sure what the URL scheme should look like.
Would it be:
http://servername/todos/
where my server filters the appropriate todos according to the authentification given to me by the http header.
Or should I include the username in the URI instead:
http://servername/users/username/todos/
On some websites I have even seen that they hand over the user name as a parameter like this:
http://servername/todos?username=babsi
As far as I can tell all three choices are stateless as I always receive the username, but just over different sources. From what I can tell to make sure that the URI is accessed by the proper user I always need to check the http header anyways. So which of the ways would you consider the best URI design in REST or should I do in a different way entirely?
You can use the following:
http://servername/todos/ GET list all todos
http://servername/users/ GET list all users
http://servername/users/{user_id}/ GET list an user
http://servername/users/{user_id}/todos/ GET list all todos for an user
I think the point here is how you want to design the relationships between your resources, if a todo just can exist in the context of an user use a hierarchy like approach as above.
As general rule i usually follow this:
Use path variables to encode hierarchy: /parent/child
Put punctuation characters in path variables to avoid implying hierarchy where
none exists: /parent/child1;child2
Use query variables to imply inputs into an algorithm, for
example: /search?q=jellyfish&start=20
Having the username in the URL depends on what you want to do (if anything at all) when you receive a request where the username in the URL does not match the authentication. If you want to re-authorize the user in this situation then yes - it's OK to have the username in the URL, otherwise it's OK to have it just in your header or other authentication scheme if there is no such need.
One fairly common example of a valid requirement would be if you have to have a main user (or group of such users) that can impersonate other users.
When the user in question is always the user who is holding the authentication token, then use something like "me" in your path.
http://example.com/users/me/<path-to-inner-resource>
Otherwise, user should be treated just like any other resource in your system, in which case the resource identifier for that user becomes a part of the path.
http://example.com/users/<id>/<path-to-inner-resource>
Take a look at Twitter APIs as an example.
https://developer.twitter.com/en/docs/twitter-api/users/follows/quick-start/follows-lookup
I want to make my system redirect unknown requests such as
www.address.com/a_company
to the adress
www.address.com/companies/company/ and display the company a_company if it exists in the database, otherwise throw the user to a 404 not found page.
So in detail, I want to make namespace that is as the first example dynamically, if the company exist in the database, I have no problem connecting to the database and retrieving information or finding a way to parse a company name, I just need help how to make my system check and run a function every time the address doesn't exist and show the second page (/companies/company/)..
I am using an Acl as well, but I think it should be fine if the page is /companies/company and then possibly add /?c=a_company or similar.
Thank you.
/Marcus
simply create a front controller plugin which checks the request params agains the database before the request is dispatched.