Multiple authentication methods for Apiary - apiblueprint

I'm just getting started with Apiary and I can't tell if this is a limitation of the product or just me not understanding what to do.
I'm documenting an API which authenticates the user as part of every request. Sometimes the authentication is part of the path (a request for the user's profile would have the user id in the path), other times just as parameters (?user_id=1&auth=secret), and for POST requests, part of the incoming body as JSON.
Also, there are 3 methods of authentication in the app. You can log in with a Facebook UID, email address, or using the unique id of the device you're using. The result is something that looks like this:
##User [/user/{facebook_uid}{?access_token}, /user/{email}{?device_id}, /users/{device_auth_id}{?device_id}]
This works fine, and displays in the API as I'd expect:
But this introduces 2 issues:
1) If I wanted to add a set of parameters shared by all authentication methods, I would need to add it to all 3 like this:
## User [/user/{facebook_uid}{?access_token, extra_thing, this_too},
/user/{email}{?device_id, extra_thing, this_too},
/users/{device_auth_id}{?device_id, extra_thing, this_too}]
This seems a bit messy, it'd be much nicer to apply shared parameters at the end of the path array so they apply to all, something like this:
## User [/user/{facebook_uid}{?access_token}, /user/{email}{?device_id}, /users/{device_auth_id}{?device_id}]{&extra_thing, this_too}
But this doesn't work. Is there a way to do this? The documentation wasn't very helpful with more complicated stuff like this.
Also, would there be a way to create some kind of template which I could apply to all my methods? In the case where the authentication is part of the path its a bit unavoidable, but for other requests it would be nice to just do something like include: authentication and have it pull the unique_id/auth combo from a defined template somewhere.
Thanks!

First, there isn't really support for having a single model with multiple resource representations. It is an unusual thing to do and is actually good food for thought.
Second, using multiple URIs in [path segment] is probably going to confuse Apiary's mock server and make it unusable.
In my opinion, I'd split this into three models: Facebook User, E-mail User and Device User, with slightly different documentation (how are they created? Can you really create all of them through api? etc. etc.)
It also depends on how you want to document this. As path segments are not validated (it would be strange to have different resources based on the type of the arguments), you can just have (and I'd personally do just that)
## User [/user/{id}{?access_token, extra_thing, this_too}]
+ Parameters
+ id (required, string, `test#example.com`)...id of the user. Can be either user's e-mail, facebook id or device id from where user was created.
As for reusable parts, this is currently being implemented with authentication being part of that.

Related

how to implement Multi-Tenant functionality in asp.net-core

I have an Asp.net Core application I want to be able to allow multiple/ different Tenant(Client)to access the same application but using different url's. I have common database for all tenant(client).
So It is the main part I want to host my application in a domain say... www.myapplication.com then allow different Tenant(client) to access the same application using
1.www.TenantOne.myapplication.com
2.www.TenanatTwo.myapplication.com.
3.www.{TENANCY_NAME}.myapplication.com
I can't find any info on how to do this and I'm stuck.
How to do it? Please provide the code. Thanks.
As Saravanan suggested these types of questions don't belong here on SO. To get you started, I suggest you start looking if there are any frameworks such as SaaSKit available to add a multi tenancy layer to the pipeline.
The essential part is to know where each request comes from. Using subdomains is a good way to achieve that and middleware is a good place to 'identify' your tenant. You could have a database to persist the tenants but the implementation is entirely up to you. I also wrote a little article on the subject. Although it isn't ASP.NET Core, the principles still apply.
The approach I believe you are looking for is similar to the article at the url below.
https://dotnetthoughts.net/building-multi-tenant-web-apps-with-aspnet-core/
In it, the author splits the requesting URL into an array of strings delimited by the dot in the address. The variable 'subdomain' is then set to the first element of that array. In your question, it looks like you may want to use the second element in the array, but you get the idea.
var fullAddress = actionExecutingContext.HttpContext?.Request?
.Headers?["Host"].ToString()?.Split('.');
var subdomain = fullAddress[0];
//do something, get something, return something
How you use this data is up to you. The author of the article created a filter attribute, but there are many possibilities such as passing the tenant name as a parameter to a service function.
Sorry,you have to get something to start with and then come back for the people to help you with.
I would say that this is all of a domain based wild card mapping and change in your authentication logic to get the tenant id from the URL. Once you identified the tenant, you just login and then take it forward. Like you might be having a database with the tenant details like
tenant1 | tenant1.company.com | guid-ofthe-tenant | etc...
Once you get the URL, you lookup in the above table and get the tenant code and then you choose the login mode and then proceed.
In case you have tried something yet, we would be happy to point you if it does not work yet.

HTTP Verbs, WebAPI

I would like to know the usage scenario of POST vs PUT in a WebAPI . I know the basic concepts that POST is for creating resource and PUT is for updating resource but not able to fully understand why we need a PUT over a POST.
I have 2 WebAPI methods which creates/updates data to my SQL store
1. CreateUser(UserDto)
2. UpdateUser(UserDto)
UserDto contains userId, username and email.
I can use POST for both CreateUser and UpdateUser methods which creates and updates user to my store.
Then what is the real advantage of using POST for CreateUser and PUT for updateuser? Is it just a standard/convention?
Thank you
POST always creates something new. PUT updates a existing thing. It is a convention.
You should have:
POST /users : to create a new user. The payload should not include the ID
PUT /user/(id) : to replace a user DTO with the data in the payload. Again, the payload should not contain an user id
PATCH /user/(id): to update specific members of the user, but the id.
It is a design convention, like software design patterns, to make it easy to communicate and understand by whoever has to consume the API.
POST is usually used to add a new resource into collection of resources.
Like this: POST /users.
This operation is NOT idempotent and it will have a side effect at each call.
While PUT is usually used with a replace semantic and you know the exact resource which you want to replace.
Like this: PUT /users/1.
This operation is idempotent and it will not have any side effects on subsequent calls.

JSON API REST endpoint with permissions-restricted fields

JSON API REST endpoint with permissions-restricted fields
I am working on a JSON API-compliant REST api. Some endpoints contain fields that should be restricted (read-only or not available) for certain users.
What is the best way to architect the api to allow that certain users have access to certain fields, while others do not? By "best", I mean:
Most compliant with REST standards, ideally JSON API standards
Most clarity in terms of preventing bugs and confusion on behalf of clients consuming the API
I am considering the following options, each with their set of concerns/ questions. I would be more than grateful for any other solutions!
Option 1: Return null on restricted fields for users without permissions
Different data values would be returned per-user. Is this strictly anti-REST?
Lack of distinction between null meaning "null value" and null meaning "You don't have access to this"
In REST/ JSON API architecture, is it okay for an endpoint to return different data per user, based on permissions? I have the impression that this would be contrary to the spirit of resource-based REST architecture, but I could not find anything specific to point to in any doc or standard (e.g. JSON API). Also applies to Option 2.
Is there any paradigm for adding some sort of "You don't have access" flag in the resource's metadata?
Option 2: Exclude restricted fields entirely for users without permissions
Different data values would be returned per-user. Is this strictly anti-REST?
Possibility of "undefined" errors in client, when trying to retrieve field value
Option 3: Move restricted field(s) onto another endpoint, available as an ?include='field_name' relation for those with permission
Example: /api/entity includes attribute field "cost" which is only available to Admin users. Admin users can request cost data via GET /api/entity?include=cost. For all users, "cost" is exposed as a relation in the resource object, with a "type" and "id".
This is the option I am leaning toward. The main con here is endpoint clutter. I have a lot of relations that would need to be made into separate endpoints, simply to support a permissions-quarantined data on an already-existing endpoint.
In the JSON API specs, I am having trouble determining if it's ok for an endpoint to exist as a relation only, e.g. can we have /api/entity/1/cost, but NOT have a top-level api endpoint, /api/cost. My assumption is that if a resource has a "type" (in this case, the relation type being 'cost'), it also has to live on a top-level endpoint.
In this scenario, the client could get a 401: Unauthorized error response if a non-admin user tries to GET /api/entity?include=cost or GET /api/cost/:id
Note: I have already built a separate permissions schema so that the client can determine which CRUD privileges the user has, per top-level endpoint, before making any requests. Permission sets are indexed by resource type.
Any help on the matter would be very much appreciated! And if anything needs to be clarified, feel free to ask.
I would definitely not use undefined or null to indicate fields that the user is not allowed to see. To me, that feels like a lie and represents that the data is really not there. They would have to really know your API in order to get a grasp of what is really going on.
I would recommend something more like your 3rd option, except I would make it a different endpoint altogether. So in your example, the endpoints would be:
/api/entity/1/cost
and for admins
/api/admin/entity/1/cost
or something like that.
This way your server code for the admin endpoint could just be focused on authenticating this admin user and getting them back all the fields that they have visibility on. If a non admin user tries to hit that route, reject them with an unauthorized status code.
I'm not saying that you should not implement the GET param to be able to specify fields as well. You can if you want to, but I don't think it just won't be necessary in this case.

Custom profile URL for own site, been though various posts..!

I've been through a few similar posts,
Facebook Like Custom Profile URL PHP
Custom URL / Apache URL Rewriting
But its still not clear, the actual method/process is not available..
Guys , little more guidance would do a lot..
I would like to put forward the questions here:
Users should have a chance to decide what is their url, Just like in case of fb, twitter
for example: www.facebook.com/harry.inaction
I am using the linux, apache, mysql, php environment for this.
Users are identified based on their user id's which get created automatically when they join in
And I fail at the very first step, seriously I don't know get started.
Thanks
It's going to be impossible to put any details as an answer because you've got to build this system of yours and there's more than one way to do it. Design decisions will need to be made based on the way you want things to work and what you already have (they're going to have to work together in some way).
Say you've already got a system for creating users (and it sounds like you do) and you already have a system for viewing profiles. You'll need to extend this system so that you store an extra "my_vanity_url" field in your user table in your database. This field needs to be unique. When a user edits their profile, they have the option of changing this to whatever they want (limiting it to only letters and numbers and dashes for simplicity).
Next, when you display this profile, say it is via /profile.php, your code needs to check a few things.
First it needs to check how it's called, looking at $_SERVER['REQUEST_URI'] you can see either /user/some-vanity-name or /profile.php?u=1234.
If it's the latter, you need to redirect the browser, do a database lookup to see who the user with user_id 1234 is.
Pull the "my_vanity_url" column out of the database for this user and redirect the browser to /user/my_vanity_url_value (replacing my_vanity_url_value with the value of that column).
So now, if you go to http://your.domain.com/profile.php?u=1234, your browser gets redirected and the URL address bar will say http://your.domian.com/user/my_name.
Next, you need to be able to take that unique name and turn it back into the old ugly looking profile page. Two things need to happen here:
You need to extend your profile.php once more to take an optional vanity name as opposed to a user_id
You need to use mod_rewrite to internally route vanity names to /profile.php
For the first thing, you simply look for a different $_GET[] parameter instead of whatever it is for a user_id. Say it's called name: so look at $_GET['name'], see if it exists, if it does lookup the user in the user table whose vanity url name is $_GET['name']. Return the profile of that user.
For the second thing, you just need to put this in the appropriate place in your htaccess file in your document root:
RewriteEngine On
RewriteRule ^/?user/([A-Za-z0-9-]+)/?$ /profile.php?name=$1 [L]
This is just an example for how to implement something like this. It may be completely inapplicable for what you have, but it should give you an idea of what you need to do.

Combining GET and POST in Sinatra (Ruby)

I am trying to make a RESTful api and have some function which needs credentials. For example say I'm writing a function which finds all nearby places within a certain radius, but only authorised users can use it.
One way to do it is to send it all using GET like so:
http://myapi.heroku.com/getNearbyPlaces?lon=12.343523&lat=56.123533&radius=30&username=john&password=blabla123
but obviously that's the worst possible way to do it.
Is it possible to instead move the username and password fields and embed them as POST variables over SSL, so the URL will only look like so:
https://myapi.heroku.com/getNearbyPlaces?lon=12.343523&lat=56.123533&radius=30
and the credentials will be sent encrypted.
How would I then in Sinatra and Ruby properly get at the GET and POST variables? Is this The Right Way To Do It? If not why not?
If you are really trying to create a restful API instead if some URL endpoints which happen to speak some HTTP dialect, you should stick to GET. It's even again in your path, so you seem to be pretty sure it's a get.
Instead of trying to hide the username and password in GET or POST parameters, you should instead use Basic authentication, which was invented especially for that purpose and is universally available in clients (and is available using convenience methods in Sinatra).
Also, if you are trying to use REST, you should embrace the concept of resources and resoiurce collections (which is implied by the R and E of REST). So you have a single URL like http://myapi.heroku.com/NearbyPlaces. If you GET there, you gather information about that resource, if you POST, you create a new resource, if you PUT yopu update n existing resource and if you DELETE, well, you delete it. What you should do before is th structure your object space into these resources and design your API around it.
Possibly, you could have a resource collection at http://myapi.heroku.com/places. Each place as a resource has a unique URL like http://myapi.heroku.com/places/123. New polaces can be created by POSTing to http://myapi.heroku.com/places. And nearby places could be gathered by GETing http://myapi.heroku.com/places/nearby?lon=12.343523&lat=56.123533&radius=30. hat call could return an Array or URLs to nearby places, e.g.
[
"http://myapi.heroku.com/places/123",
"http://myapi.heroku.com/places/17",
"http://myapi.heroku.com/places/42"
]
If you want to be truly discoverable, you might also embrace HATEOAS which constraints REST smentics in a way to allows API clients to "browse" through the API as a user with a browser would do. To allow this, you use Hyperlink inside your API which point to other resources, kind of like in the example above.
The params that are part of the url (namely lon, lat and radius) are known as query parameters, the user and password information that you want to send in your form are known as form parameters. In Sinatra both of these type of parameters are made available in the params hash of a controller.
So in Sinatra you would be able to access your lon parameter as params[:lon] and the user parameter as params[:user].
I suggest using basic or digest authentication and a plain GET request. In other words, your request should be "GET /places?lat=x&lon=x&radius=x" and you should let HTTP handle the authentication. If I understand your situation correctly, this is the ideal approach and will certainly be the most RESTful solution.
As an aside, your URI could be improved. Having verbs ("get") and query-like adjectives ("nearby") in your resource names is not really appropriate. In general, resources should be nouns (ie. "places", "person", "books"). See the example request I wrote above; "get" is redundant because you are using a GET request and "nearby" is redundant because you are already querying by location.

Resources