For a user generated content website, I want to give ability to my users to restrict on who can see the content.
Domain based restriction seems like a good choice( users can embed content content on their own site).
Any samples/suggestions/known gotchas on how we should implement domain restriction on content?
Our solution is developed on asp.net mvc
The authorization scheme you would use is independent of whether you use DDD or not.
You would probably use a Role-based authorization scheme. Every item of content then comes with an Access Control List (ACL), which is basically a list of roles and their rights -- for instance, all users who are in the FoodAuthors group can modify a particular piece of content, and all users in the FoodReaders group can only read it. Users who are in neither group/role have no access to the content.
Furthermore, you can divide up your content into categories (or "channels", whatever term you prefer), and organize these categories/channels in a tree structure. Then you can put ACLs on the categories/channels rather than on the content itself. So, an article on whole foods would be put in the /Health/Food channel, for instance, and the FoodReaders group would get read access to all content in that channel.
Related
Specifically, can SCIM be used to add Users to pre-existing (non SCIM-created) groups? We need to provision users via SCIM, but then add them to Groups created manually in the site (a .Net application).
As I understand it, it can't be done like this. Group Update requests (i.e. PATCH requests) seem to require the "id" attribute as the unique identifier for the group, and this "id" seems to be only generated in SCIM Create Requests. So if a Resource (Group / User) wasn't originally created via SCIM, SCIM can't update/replace/delete it. Is that correct?
e.g. PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
I thought about a workaround convention, such as using "user:1234" and "group:1234" as the "id" attribute format (i.e. [resource type]:[internal type-specific ID]), and then any User or Group can be specified by "id", even if it wasn't created via SCIM. But that seems pretty hacky.
Is there a better way of doing this? Many thanks for any help, very new to SCIM!
Yes, SCIM can be used to manage "brownfield" scenarios where existing non-SCIM created objects exist.
Typically the logic flow that happens for a user object is:
GET on /users with a filter (as defined in RFC7644 3.4.2.2) using an attribute that is uniqueness constrained (such as userName, email).
If no user found matching that criteria, create a new user with POST to /users
If a user was found, it should bereturned with an id value even if it was not created via SCIM
The general logic of "Search using a friendly identifier -> create if not found/cache the id value and associated it with existing user in the other directory" is pretty simple and can be successfully used with other object types (ie: groups) as well.
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.
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.
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.
For example, I have a field that give user to type their domain, the user can type any domain on this, but I don't valid this domain is belong that user. Of course, I can generate a random number text file for user to upload, and when I get the random number text file, if it is match, I can just treat it as a valid domain holder. But, except from this method, is that anyway to do so? Thanks.
Options I have seen:
Have user Create a Text file in document root, check for it
Send Email to contacts listed in whois (Or other ROLE type accounts (postmaster, hostmaster, etc...), with token they need to
return
Have them create an 'A' record in their DNS that is unique and you can query for.
There really isn't any other way of telling if they have control over the domain. Using whois information isn't 100% accurate as people don't update it, or their info isn't registered to them, or is hidden behind something like domains by proxy. There is no standard information in DNS, that can tell you ownership. Since google uses the DNS method and the text file method (I think), you can probably safely assume that is a good way to verify it.