I am building a user account service which handles basic log in/out and view/edit account profile etc.
They enter their email and password which I need to authenticate. Please do not comment on any security issues (API not public etc) thanks!
The service has a RESTful API so was considering how best I design the API. I have some options...
GET api/accounts?email=x&password=y
Returns an array of Accounts of size 1 if valid (or 0 if not)
or
POST api/login_requests (where body contains email/passwword)
Returns an Account if valid (or Not Found if not)
I'm thinking the latter but not sure this is really restful (I don't really have login_request resources - so seems a bit procedural).
Thoughts? Maybe there are other options/standard approaches?
GET, in HTTP protocol communication term, try to 'read' information . And this itself have possible states value that can be handler, (200, 201, 400, 404) .
If the case is such static response, (like 1 or 0 if not) , would be a clever option directly resolve with the protocol (it why it exist ) .
Related
I am developing a web API which will return Forbidden http status for multiple reasons-
User is blocked.
IP is blocked.
Request limit exceeded.
User is unverified.
I am returning response in following way-
return Content(HttpStatusCode.Forbidden, message); //message : "Limit reached" etc.
Now, I need to handle these reasons differently at client. Should I identify the reason from returned message? This message is to be displayed to user and might change in future.
What is the best practice for this?
What is the best practice for this?
Rather than trying to invent a schema of your own, you should probably look for something standardized, like Problem Details for HTTP APIs.
Problem Details describes a human readable "title" and "detail" field, and a "type" that is a link to human readable documentation.
Consumers MUST use the "type" string as the primary identifier for the problem type; the "title" string is advisory and included only for users who are not aware of the semantics of the URI and do not have the ability to discover them (e.g., offline log analysis). Consumers SHOULD NOT automatically dereference the type URI.
Consumers SHOULD NOT parse the "detail" member for information; extensions are more suitable and less error-prone ways to obtain such information.
Your error message should be descriptive for your client. Ideally you need to include the following information:
developers message (technical description - "cache is out-of-date", "service A is unavailable")
human-readable message (business description - "this time is booked already", "company A is closed and cannot be modified")
hint how to solve ("refresh your cache", "try again in 5 minutes", "request permission A from administrator")
href to your online documentation
Header like "error_code: 100". A custom code should also be described in the documentation. This one you may rely on in your client's code and handle appropriately
Also what do you mean by:
User is unverified.
In case user is not Authenticated (api doesn't know who is he), api is supposed to return 401 http status code. If user lacks some permission and therefore cannot modify the resource than 403 is totally fine. However it would be great to describe which permission exactly is missing
We have listing and details page for mobile, desktop, android and ios?
We have two apis- one for listing and other for details of those listings. So one api is assosiated with other.
listing api looks like:
/api/books/?price=100-300
details api looks like:
/api/book/{bookId}
listing api in response sends back details api link for each listing:
For example:
Request:
/api/books/?price=100-300
will have Response:
{
"books":[
{
"id": 1,
"price": 120,
"pages": 400,
"detailsUrl": "/api/book/{bookId}"
}
]
}
The problem is, should I send detailsUrl with each listing or let all the clients create this? Since they have bookId, they can create it.
What is considered to be best practise considering the url params in details api url may get added in future, api may be versioned and all other possibilities for widely used apis?
I'd put my money on creating the link.
There is a perfect explanation why putting id is not enough
DO NOT include just an entity's ID (such as 12) in a response, because
that way you're forcing clients to put together resource URIs
themselves. In order to do that, they would need to have prior
knowledge of what URIs there are, and you're losing control over the
URI space on the server side.
I recommend to read the entire, linked text (approved answer), it's very detailed and got nice resources. As the author mentioned, there is a popular convention how to make connections between resources - HAL. Consider this instead of detailsUrl.
Even if a link to the resource is obvious right now and you decided to put id alone, in other resources after some time it won't be so simple and you will be forced to specify full URL. Then your API won't be consistent. Experience has taught me it's always easier and better for maintenance to send back full link.
I have a RESTful service using HAL links. There is a customer resource and a preferredCard resource. A customer does not always have a preferredCard selected.
As the user must be logged in there is no need to pass customer or card id we will pull it from their identity.
PreferredCard url: GET: <root>/<version>/preferredCard
I think I have two options.
1) Add a preferredCard link on the customer and return a 404 (NotFound) if there is no preferredCard, otherwise return the preferredCard resource.
2) Don't display a link to the preferredCard on the customer if one doesn't exist.
Any thoughts on what is best here. Worried that in the first option I am returning a 4XX when the client didn't really mess up
Thanks
I think you need to handle both situations.
If you know the user has no prefered card, don't give them a link to something that isn't going to work. Maybe give them an alternate link to select one.
Equally, if that URL can exist, the user could always come back to it later, even if it has been removed. In this case, you may want to consider a custom 404 pages. The 404 error would let the user know that the resource they wanted cannot be found, but you can still provide some content, perhaps something explaining what is going on (that there is no current prefered card) and offers some useful links, in this case a link to the page where they can create/select a prefered card.
If there is no preferredCard for the customer-resource, then you may want to serve a createPreferredCard or selectPreferredCard-link instead of just hiding the link to a 404.
This would look like a clean approach to me, since you are hiding stuff that doesn't work, but offer options.
The API documented here - http://developer.yammer.com/restapi/#rest-users clearly states:
"4) Alias to /api/v1/users/current user’s id.format. Supports include_followed_users, include_followed_tags, and include_group_memberships parameters.
GET https://www.yammer.com/api/v1/users/by_email.json?email=user#domain.com`
Yet, when we try this, it does not return any followed user information at all! The request we're using is like so:
https://www.yammer.com/api/v1/users/by_email.json?email=me#company.com&include_followed_users=true
However, this request DOES return followed users, but only for the current user:
https://www.yammer.com/api/v1/users/current.json?include_followed_users=true
Am I missing something completely obvious and being stupid or is there a real issue here? If this was taken out for whatever reason, then you'd have thought that the API documentation would have been updated.
The Yammer Team did eventually get back to me on this. Their response below:
(I've removed https://www.yammer.com from URLs because I don't have enough rep' to post more links)
Hey Jason Dunbar looks like the documentation here is wrong.
I looked in to this and had some conversations with a few engineers this week and have the following (albeit more arduous workaround):
1) Call get user by email endpoint and retrieve the id attribute from here: /api/v1/users/by_email.json?email=user…
2) To grab following users, take that id and:
GET /api/v1/users/following/[:id].json
3) To grab group memberships for that user you'll need to impersonate him/her (verified admin only) and
GET /api/v1/users/current.json
We'll get the documentation updated ASAP with this. Also happy to keep the conversation going to help if needed.
Make sure you are setting the email parameter to the user's email that they are registered with.
E.G. if your company has multiple domains but the Yammer network is under bigco.com and the user is registered with an email under bigcosubsidiary.com you'll need to make a request to the API with user#bigcosubsidiary.com.
-as mentioned - it looks like its only for current.json - you can check it here http://yammer-dev.herokuapp.com/endpoints/4 - hope it helps.
Rich
We're writing an app with an Android view and a website. Our app needs to associate some data with Facebook, Google, or Twitter (call them 'FGT'), and then hit the associated service to return true if that data is authenticated. The control flow is...
Android generates some data
User selects an FG or T account
getAuthToken
upload the data+token, via HTTPS POST, to our website
Our website (in Django, not that it matters) sends the Auth Token to FGT
FGT returns true if it likes that token, and false if it doesn't
The goal is preventing an attacker from concocting data and throwing it at our site with curl. And we /don't/ need to upload the data all the way to F, G, or T. We don't need to go all the way to a Hybrid App, where our webservice authenticates itself to F, G, or T, and then uses F, G, or T's API to post, e-mail, or tweet in the user's name.
There's obviously a simple answer for this out there somewhere; hopefully just three URIs, one each for F, G, or T, into which I can insert the Auth Token. That's why I would prefer NOT to download and install the SDK for each of Facebook, Google, and Twitter, and then write tons of service-specific code for each case. That would clutter up the code, and leave me screwed when the client requests Tumblr or MSN.
(A related question: What's the second parameter of getAuthToken()? "ah"? "mail"?)
So, while I continue to read books, source code, and SO posts showing how to do hard things the hard way, can someone tip me off how to do an easy thing the easy way?
The thread "validating Android's authToken on third party server" answered the sub-question "what simple URI to hit to test a token?"
The magic uri, for Google, is: https://accounts.google.com/o/oauth2/tokeninfo?access_token=%token_here%
The next question is How to thump an Access Token out of getAuthToken. The scope there should be the minimum possible to show a user really lives here:
String SCOPE = "oauth2:https://www.googleapis.com/auth/userinfo.profile";
am.getAuthToken(a, SCOPE, false, this, null);
My this class implements AccountManagerCallback<Bundle> and provides the method run(AccountManagerFuture<Bundle> result). That, per documentation such as "Android AccountManagerFuture getResult gives IOEXcelption when trying to get authorization token", might call startActivity() to challenge the user to authorize this activity, or it might use a token that's already stored in the AccountManager. (And note that implementing a class just to call-back yourself is pernicious, especially if the target method's named merely run(), so do as I say not as I do, kids!)
The resulting token is 52 bytes long, beginning with 'ya29.', so it's _ probably _ an access_token, not 331 characters, which is probably an id_token.
The resulting token is not bound to any specific channel (where "channel" is one unique set of client, server, and scope). So, from a simple curl, I can hit that /tokeninfo URI with it, and get this (scrubbed) JSONic wisdom:
{
"issued_to" : "442575845966-mde4be7eingpb5pntfs839jipsetro6s.apps.googleusercontent.com",
"audience" : "424242424242-mde4ab7defghi5jklmn839opqrstuv6s.apps.googleusercontent.com",
"user_id" : "424242424242424242424",
"scope" : "https://www.googleapis.com/auth/userinfo.profile",
"expires_in" : 2272
}
And so this answer would have formed, for me, the missing link between all the other documentation I was trying to read. Aaand now I need to do it all again for Facebook & Twitter...
There is a simple URL.
Each authtoken is granted against a scope. Each scope allows the authtoken to do certain things. If you try to do something that the scopes permit, that thing will fail or succeed based on the validity of the authtoken.
The simplest scope to request is probably 'email'.
If you go to the Oauth2 Playground at https://developers.google.com/oauthplayground/ you can experiment with scopes and calls to get one that suits you. You'll be able to see the URLs that you then need to replicate in your app.