Is ory/keto support Contextual and Time-based authorization? - authorization

I have a scenario where I want to restrict access to a document based on his IP address using ory/keto authorization service.
It looks like I can't achieve contextual attribute based authorization using ory/keto. I couldn't find any docs on that in ory/keto doc space. I tried few authorization check payloads to pass the dynamic attributes for the user. An example is provided below (I tried and it didn't work, ory/keto doesn't allow nested subject_sets).
{
"namespace": "document",
"object": "document",
"relation": "view",
"subject_set": {
"namespace": "user",
"object": "john",
"relation": "is",
"subject_set": {
"namespace": "ip-address-range",
"object": "0.0.0.10/11"
}
}
}
Can we achieve Contextual and Time-based authorization with ory/keto? If we can, can I get an example of how could I do it?

There is an issue for this (which was probably the inspiration for Auth0/OpenFGA): https://github.com/ory/keto/issues/319
It is a cool feature but there is no implementation effort yet.

Related

Rest API for Authentication with nHost

So I know there's several SDK packages for many languages available for nHost, however I need to create my own interface to the system since the language I'll be using isn't typical.
I basically just need to know how to interact with authentication endpoints, send a users un/pw and recieve a JWT token. I've been successfully able to do this with aws Cognito, but I'd like to explore this instead.
I'm also not sure if I'm using the right base url, here's my thought so far:
https://kbvlufgpikkxbfkzkbeg.nhost.run/auth/login
So I would POST to there with some json in the body with the un/pw stuff, and the response should be the jwt token right?
I get a "resource does not exist" response from the above, however, so obviously I'm not forming the url correctly in the first place.
Thanks for the help!
Nhost supports multiple sign-on methods.
For example, using the email+password method, you would send:
POST https://xxxxxxxxxxxxx.nhost.run/v1/auth/signin/email-password
{"email":"foo#example.com","password":"bar"}
and the response:
{
"session": {
"accessToken": "somejwt....",
"accessTokenExpiresIn": 900,
"refreshToken": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"user": {
"id": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"createdAt": "2022-09-17T19:13:15.440221+00:00",
"displayName": "foo#example.com",
"avatarUrl": "",
"locale": "en",
"email": "foo#example.com",
"isAnonymous": false,
"defaultRole": "user",
"metadata": {},
"emailVerified": true,
"phoneNumber": null,
"phoneNumberVerified": false,
"activeMfaType": null,
"roles": [
"user",
"me"
]
}
},
"mfa": null
}
The JWT is short-term, when it expires, the refresh token is used to get a new one.
The Nhost JavaScript SDK handles it automatically for you, that's a big benefit to the platform (in addition to being integrated with Hasura). If you are trying to port it to another unsupported language, you'd have to reimplement it. Probably by reading the library and/or running one of their sample client application and reverse-engineering the HTTP over the wire.

How to send different verification emails at the same cognito user pool

I'm using amazon-cognito for my application user access.
I have two different groups inside my user pool.
I want to send differenet email to each user depends on the group he belongs to.
The problem is that the email verification is sent when the user is created at the pool and not after he's linked to a group.
Is there a way do to it?
Any help? advices?
After a lot of digging, I've figured out a solution.
The solution is to use AWS Cognito Lambda.
Use AWS Cognito Lambda for SignUp or AdminCreateUser events depends on your application architecture.
When a user is created either with SignUp or AdminCreateUser functions, there's an option to pass metadata with clientMetadata entry at the object.
For example (from AWS Docs):
{
"ClientMetadata": {
"string" : "string"
},
"DesiredDeliveryMediums": [ "string" ],
"ForceAliasCreation": boolean,
"MessageAction": "string",
"TemporaryPassword": "string",
"UserAttributes": [
{
"Name": "string",
"Value": "string"
}
],
"Username": "string",
"UserPoolId": "string",
"ValidationData": [
{
"Name": "string",
"Value": "string"
}
]
}
According to docs:
clientMetadata
One or more key-value pairs that you can provide as
custom input to the Lambda function that you specify for the pre
sign-up trigger. You can pass this data to your Lambda function by
using the ClientMetadata parameter in the following API actions:
AdminCreateUser, AdminRespondToAuthChallenge, ForgotPassword, and
SignUp.
So, pass the group inside the clientMetadata as an entry:
"ClientMetadata": {
"Group": "MyNiceGroup"
},
...
Inside the lambda implementation, according to the incoming group decide which email to dispatch.

Why to use actions in Dialogflow

I am new to Dialogflow so my question may be too simple. However, I do not understand what is the purpose of naming actions in Dialogflow. I have watched videos on youtube and people in them are using actions when they have a webhook. For example they may have an if condition in their source code
(e.g. in python
if action == 'action_name':
...
)
which executes something particular in this case.
However the json output which is retrieved by the source code has the following form:
{
"id": "123d9e8e-314f-451b-8b15-5e3b55baa980",
"timestamp": "2018-03-16T17:03:05.987Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "Hello",
"action": "input.welcome",
"actionIncomplete": false,
"parameters": {},
"contexts": [],
"metadata": {
"intentId": "effe6b2b-3372-4f89-882f-ff937b2b2abb",
"webhookUsed": "false",
"webhookForSlotFillingUsed": "false",
"intentName": "Welcome"
},
"fulfillment": {
"speech": "Hello, how can I help you?",
"messages": [
{
"type": 0,
"speech": "Hello, how can I help you?"
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success",
"webhookTimedOut": false
},
"sessionId": "491d57cb-0af2-45ac-a658-9e47ec6658ce",
"alternativeResultsFromKnowledgeService": {}
}
Since the json data contains the IntentName why to bother naming an unique action for this specific intent when you can get directly the name of the intent in your json?
I tend to think of this in two ways, depending on exactly what I'm building. (Or sometimes a combination of these two ways.)
The Intent Name is a human-usable name, while the Action is something that is more intended for use by the webhook and more directly maps to a function.
Since you can have more than one Intent use the same Action, it can be convenient to map a few different ways the user may say something (and the parameters they may send along with them) to the same method. While you could do that by listing all the different Intent names in your code, it is easier to do that on the Dialogflow side.
In truth - use whatever works best for you. I tend to name my Intents and my Actions very similarly, but do branching based on what makes the most sense for the code (which sometimes also includes other values that may be sent).

REST Media Type Proliferation

I took a look at this question that seeks to address the issue of REST media-type explosion. One of the suggestions was to have a media-type that describes a collection of anything. So for example, we could have an application/vnd.collection+json which is a collection with well-defined semantics that can hold a list of references to other resources:
{
"size": "3"
"elements": [
{ "href" : "http://my.api.com/resource/1" },
{ "href" : "http://my.api.com/resource/2" },
{ "href" : "http://my.api.com/resource/3" }
]
}
I know an option to alleviate chattiness is to include embedded representations of resources. How would a "generic" media-type for lists accomplish that? Don't the semantics of the list change based on which embedded resource is inside it? This is especially relevant if embedded resources have different processing-rules (which would ideally be conveyed by the media type). Would be alright in this case to allow in-band information that describes the media type of the embedded resource? For example we could have application/vnd.collection+json for both links and embedded resources that do something like this:
{
"size": "3"
"element-content-type": "application/vnd.link+json"
"elements": [
{ "href" : "http://my.api.com/resource/1" },
{ "href" : "http://my.api.com/resource/2" },
{ "href" : "http://my.api.com/resource/3" }
]
}
and if it contains an embedded resource:
{
"size": "3"
"element-content-type": "application/vnd.resource+json"
"elements": [
{
"id": "1"
"name": "Cool Resource"
},
{
"id": "2"
"name": "Awesome Resource"
},
{
"id": "3"
"name": "Super Awesome Resource"
}
]
}
The assumption is that application/vnd.link+json and application/vnd.resource+json have been documented as well.
I thought about this a little bit more, and I think it is actually OK to include the content-type like that. The reason is, we already do this. In HTML the script tag has a type attribute that can be application/javascript or application/vbscript (for example). The provides the browser a hint as to how to process the content of that tag. Similarly, I think the content-type in the above example achieves the same purpose: it tells the client how to process the elements in the collection.
I wanted to update this answer some more. It appears that another way to do this is to use a rel. At least, this is how HAL does it. You can create a namespaced rel with a curie so that you end up resolving the rel to a URL that points to documentation about that resource. This way you have access to the documentation and that should tell you all you need to know about the resource(s).

RESTful API: Modelling a collection of resources that have access to another resource

I'm building a RESTful API that exposes my application's users as users.
My application also features 'documents' and each user has access to specific documents. I'm thinking the natural way to represent that is by exposing the accessible documents through users/{user-id}/documents.
However, from a usability perspective, it's important for my clients to be able to fetch (and modify) the users that have access to a specific document. Because of that I'm considering 'reversing' this representation to documents/{document-id}/users.
Do these (and especially the latter) seem like proper ways to model this relationship? If I do go with such a solution, how do I model 'granting access to a document'?
I'm leaning towards PUTing a pre-existing user (presumably acquired by GETing users) into documents/{document-id}/users/{user-id}. That seems unsatisfactory however, as I'll be doing an 'update' operation not to actually update the resource but to insert it into a collection. It is especially problematic in terms of semantics as I expect my server-side to ultimately not take into account the complete, sent user representation but rather only cross-reference the id with ids of pre-existing users in order to create an association.
On the other hand, I can't POST into documents/{document-id}/users as I'm not aiming at the creation of a new resource - I specifically don't want one to be created.
Am I doing it wrong?
The users don't really belong to the document resource, right? What you're really saying is these users have access to this document. So what should probably be returned from /documents/{document-id}/users is not a direct representation of the user entity, but instead some kind of representation of the user's permission to the entity. Perhaps inside of that representation is a link to the full user itself.
So, if you were returning the Collection+JSON media type, maybe you'd have something like:
{
"collection":
{
"version":"1.0",
"href":"/documents/document123",
"items":
[
{
"href":"/documents/document123/users/user3841",
"data": [
{ "name":"userName", "value":"John Doe", "prompt":"User Name" },
{ "name":"permissions", "value":["Read"], "prompt":"User Permissions" }
],
"links": [
{ "rel":"user", "href":"/users/3841" }
]
},
{
"href":"http//whatever/documents/document123/users/user9387",
"data": [
{ "name":"userName", "value":"John Doe", "prompt":"User Name" },
{ "name":"permissions", "value":["Read"], "prompt":"User Permissions" }
],
"links": [
{ "rel":"user", "href":"/users/9387" }
]
}
]
}
}