aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
87 stars 75 forks source link

@auth Combining Owner/Groups rules for Multi-Tenant Apps #449

Open lennybr opened 5 years ago

lennybr commented 5 years ago

Is your feature request related to a problem? Please describe. Ability to support multi-tenancy thru AppSync where individual items are "owned/belong" to a tenant instead of a user and we still have the ability to permission queries and mutations. Generated resolvers today effectively use isOwner || isInGroup(x for x in cognitoGroups) logic so multiple @auth rules cannot be combined to create more granular permissions.

Describe the solution you'd like A few ideas:

Describe alternatives you've considered Currently using the existing @auth owner strategy with custom ownerField and identityFIeld values, and setting the tid claim on the token with a pre-token generation Lambda function:

@auth(rules: [{allow: owner, ownerField: "tid", identityField: "claims.tid"}])

When used as the only @auth strategy, it works as intended (e.g. inserting the correct tid value during mutations; filters by tid value during queries, etc.).

But when I combine with @auth static groups strategy for permissions, the authorisation checks use OR logic instead of AND logic. I can't check for instance that a record both belongs to Tenant A (which the user belongs to) and has Permission X.

paulsson commented 3 years ago

@mrsimply @ronaldocpontes I'll try to keep this example as simple as possible. It took me quite a while to come up with this and wrap my head around...

Hypothetical data resource types and relationships: Users are assigned to a Business (employee of) A Business has 1 or more Locations A User can also be assigned to 1 or more Locations of the Business (many-to-many relationship not shown in below schema)

Now let's say there are 2 types of roles for a user:

schema.graphql

type Business
  @model
  @auth(rules: [
    # grants "root" admins CRUD operations on all Businesses
    { allow: groups, groups: ["Admin"], operations: [create, read, update, delete] }
    # grants Business admins read, update operations if the calling user is an employee of (assigned to) the Business
    { allow: groups, groupsField: "id", operations: [read, update] }
    # grants Location admins read access if the calling user is an employee of (assigned to) the Business
    { allow: groups, groupsField: "id", groupClaim: "locationAdmin", operations: [read] }
  ]) {
  id: ID!
  name: String!
  locations: [Location] @connection(keyName: "byBusiness", fields: ["id"])
}

type Location
  @model
  @auth(rules: [
    # grants "root" admins CRUD operations on all Locations
    { allow: groups, groups: ["Admin"], operations: [create, read, update, delete] }
    # grants Business admins create, read, update operations if the calling user is an employee of (assigned to) the Business
    { allow: groups, groupsField: "businessID", operations: [create, read, update] }
    # grants Location admins read, update access if the calling user is an employee of (assigned to) the Business
    { allow: groups, groupsField: "id", operations: [read, update] }
  ])
  @key(name: "byBusiness", fields: ["businessID", "name"]) {
  id: ID!
  businessID: ID!
  name: String!
}

type User
  @model
  @auth(rules: [
    # grants "root" admins CRUD operations on all Users
    { allow: groups, groups: ["Admin"], operations: [create, read, update, delete] }
    # allow the User to read, update their own User record
    { allow: owner, ownerField: "id", operations: [read, update]
    # grants Business admins create, read, update operations if the calling user is an employee of (assigned to) the Business
    { allow: groups, groupsField: "businessID", operations: [create, read, update] }
    # grants Location admins read access if the calling user is an employee of (assigned to) the Business
    { allow: groups, groupsField: "businessID", groupClaim: "locationAdmin", operations: [read] }
  ]) {
  id: ID!  # use the Cognito sub/id as the id here
  businessID: ID!
  emailAddress: AWSEmail!
  role: Role
  business: Business! @connection(fields: ["businessID"])
}

enum Role {
  BUSINESS_ADMIN
  LOCATION_ADMIN
}

Cognito pre-token generation lambda handler code:

const getUserQuery = `query GetUser(
  $id: ID!
) {
  getUser(id: $id) {
    role
    business {
      id
      locations(limit: 100) {
        items {
          id
        }
      }
    }
    locations {
      items {
        location {
          id
        }
      }
    }
  }
}`;

exports.handler = async (event, context, callback) => {
  // get the user ID (Cognito sub)
  const userSub = event.request.userAttributes.sub;
  // get the user groups assigned through Cognito groups
  const groups = event.request.groupConfiguration.groupsToOverride;

  // get the calling User record from the GraphQL API
  // make sure to load the Business with id and all Locations belonging to 
  // the Business as well as all Locations the user is assigned to
  // NOTE: api.gqlCall is a utility method for making AppSync/GraphQL API calls
  const userResp = await api.gqlCall(
    getUserQuery, 'GetUser', { id: userSub }, graphqlEndpoint, REGION,
  );

  // make sure we got user data returned from the GQL API call
  if (userResp.data && userResp.data.getUser) {
    const businessId = userResp.data.getUser.business.id
    const claimsToAddOrOverride = {
      business_id: businessId,
    };
    const customGroups = [];
    if (!groups.includes('Admin')) {
      # don't need to do any of this for "root" admins
      if (userResp.data.getUser.role === "BUSINESS_ADMIN") {
        customGroups.push(businessId);
        // add all Business Location IDs to customGroups
        userResp.data.getUser.business.locations.items.forEach((item) => {
          customGroups.push(item.location.id);
        });
      } else if (userResp.data.getUser.role === "LOCATION_ADMIN") {
        // add only the specific Location IDs that the user is assigned to
        userResp.data.getUser.locations.items.forEach((item) => {
          customGroups.push(item.location.id);
        });
        claimsToAddOrOverride.locationAdmin = businessId;
      } else {
        claimsToAddOrOverride.readAccess = businessId;
      }
    }
    event.response = {
      claimsOverrideDetails: {
        groupOverrideDetails: {
          groupsToOverride: [...groups, ...customGroups],
        },
        claimsToAddOrOverride,
      }
    };
  }
  callback(null, event);
}

I hope this can help give some good ideas for others!

ronaldocpontes commented 3 years ago

Awesome @paulsson! This seems to solve our multi-tenant authentication requirements quite neatly with the current functionality in Amplify. Your solution should be added to the official Amplify docs. Thanks for sharing!

theunsa commented 3 years ago

Thanks for the great example @paulsson. I'm new to this, as such still trying to wrap my head around the tricks one needs to pull to accomplish this feature, so apologies if these questions are common sense to you and others:

  1. Is the Cognito pre-token generation lambda handler relevant to identity tokens only or access tokens as well?
  2. And follow up question ... according to https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html, the Pre Token Generation Lambda Trigger will get called for every identity or access token refresh. From the App Client config in the User Pool I can see the "token expiration" must be between 5 minutes and 1 day. Am I correct in saying that the Cognito pre-token generation lambda handler will be called on every token refresh raising possible lambda cost concerns one should be aware of? I guess one could set those tokens to expire once a day to lessen such concerns but I'm not really sure it is good practise to have such long lived access tokens?
dantasfiles commented 3 years ago

@theunsa

  1. Is the Cognito pre-token generation lambda handler relevant to identity tokens only or access tokens as well?

In @paulsson example:

event.response = {
      claimsOverrideDetails: {
        groupOverrideDetails: {
          groupsToOverride: [...groups, ...customGroups],
        },
        claimsToAddOrOverride,
      }
    };

Back when I was working with tokens, it worked like this: the ID token gets the added groups and claims, while the access token gets the added groups but not the claims. So if you want to use the added claims from the lambda function, you have to override AWS Amplify's normal authorization behavior, as @paulsson says:

This requires you to pass the id_token instead of the access_token JWT in the 'Authorization' header unfortunately, but not a big deal.

Here's another example of doing that

If you just want to use the added groups in your authorization (for simpler use cases than @paulsson example), then you can use the access token as normal.

octaneC8H18 commented 3 years ago

Hi @mikeparisstuff Any update on this ? :)

rhorohit commented 3 years ago

@paulsson We have implemented multi-tenant using your snippet and added all the required auth rules. These rules are working perfectly fine in AWS Console. But when we are trying to access the appsync graphql API to retrieve User records through Postman/ node scripts it's not fetching any data.

As similar to yours, we have the used tenantid => businessid, teamid => locationid and userid - userid. We have the many to many relation between user and team.

With this, the TenantAdmin has complete access towards the tenant and is working as expected. Team Manager should have access to his team and all the users with in his team. This is where we are facing the problem. In appsync UI console, the user data retrieved perfectly alright, but the same listusers query is not retrieving any data when we are making a request using nodescript or postman. Please find below screenshots for more details:

AppsyncUIConsole

PostmanListUsers

type User @model @auth(rules: [ { allow: public, provider: apiKey, operations: [read] },

allow the User to read, update their own User record

{ allow: owner, ownerField: "id", identityClaim: "userID", operations: [create, read, update]},
# static group
{ allow: groups, groups: ["InternalAdmin"], operations: [create, read, update, delete]},
{ allow: groups, groupsField: "tenantID", operations: [create, read, update] }
{ allow: groups, groupsField: "tenantID", groupClaim: "teamAdmin", operations: [read] }    

]) @key(name: "userByEmail", fields: ["email"], queryField: "userByEmail") { id: ID email: String tenantID: ID! tenant: Tenant @connection (fields: ["tenantID"]) firstName: String! lastName: String teams: [UserTeam] @connection(keyName: "byUser", fields: ["id"]) userRole: [UserType!]! } type UserTeam @model @auth(rules: [ { allow: public, provider: apiKey, operations: [read] }, {allow: groups, groups: ["InternalAdmin"], operations: [create, read, update, delete]} { allow: groups, groupsField: "tenantID", operations: [create, read, update, delete] } { allow: groups, groupsField: "tenantID", groupClaim: "teamAdmin", operations: [read] }
]) @key(name: "byUser", fields: ["userID", "teamID"]) @key(name: "byTeam", fields: ["teamID", "userID"]) { id: ID! teamID: ID! userID: ID! tenantID: ID! createdAt: AWSDateTime updatedAt: AWSDateTime team: Team! @connection(fields: ["teamID"]) user: User! @connection(fields: ["userID"]) }

Additional to it, the same issue is with the team member as well, the are not able to retrieve even his own user record when the request is made from nodescript or the postman. The same is working good with the appsync UI console. (Basically the owner auth rule on the User model.)

We tried logging, but it did not help much. If anyone would have faced this issue kindly provide your inputs and suggestions.

@RossWilliams @ronaldocpontes @dantasfiles @dabit3

paulsson commented 3 years ago

In appsync UI console, the user data retrieved perfectly alright, but the same listusers query is not retrieving any data when we are making a request using nodescript or postman.

@rhorohit the AppSync Console automatically adds the authenticated Cognito user's JWT token to the request. In Postman or any script you develop you will have to add the Cognito user's JWT token to the request headers. The @auth rules are applied to the encoded user details in the Cognito JWT token so if you aren't passing that then you won't get any data. Hope that helps!

rhorohit commented 3 years ago

@paulsson I have added tokens explicitly in Postman OAuth 2.0 and also Auth PreTokenGeneration is correctly adding claims and groups. Also, it is fetching Teams records as per the auth rules but not retrieving users/ tenants records. Please find the screen-shots below:

PostmanToken_1

PostmanToken_2

PreTokenGenerationLogs

PostmanListTeams

To us, it looks like below 2 rules are causing troubles for Postman API call

UserTeam model: { allow: groups, groupsField: "tenantID", groupClaim: "teamAdmin", operations: [read] }

User model: { allow: owner, ownerField: "id", identityClaim: "userID", operations: [create, read, update]}

any suggestion would be helpful.

rhorohit commented 3 years ago

@paulsson @RossWilliams @dantasfiles @dabit3 We have written a set of auth rules to implement multitenant. It is working as expected in AWS Console Appsync GraphiQL. But the same is not working for all the models with Postman API call.

I am able to fetch records for Teams model using Postman API call but not for User model.

Please suggest if any additional configuration is required to make this work.

rhorohit commented 3 years ago

@paulsson @RossWilliams @dabit3 @dantasfiles We have created an issue to address this problem. Please find the issue link as below. It has step by step process to replicate it. we also have added a sample project with schema and pretoken function.

https://github.com/aws-amplify/amplify-cli/issues/7037

paulsson commented 3 years ago

We have written a set of auth rules to implement multitenant. It is working as expected in AWS Console Appsync GraphiQL. But the same is not working for all the models with Postman API call.

@rhorohit the Appsync Console does not do anything "magical" when calling your API. The @auth rules are all applied the same no matter what client is sending the API request. If you are making the Appsync API request correctly from Postman then it will work exactly the same.

I believe you are not passing your JWT token properly from Postman. I don't know what the "Manage Tokens" window is in your Postman screenshot. I suggest you pass your JWT token as described by the Appsync docs which says to pass it as a header named authorization in your request.

Hint: If you open up your "Network" console in your browser when using the Appsync console to make a query you will see exactly how the request is made.

rajbachu6 commented 3 years ago

Thanks so much @paulsson, we compared the headers and noticed that appsync console query is using the IDToken as the Authorization param, whereas our amplify API call and the postman calls were using the Access Token. With the help of https://github.com/aws-amplify/amplify-js/issues/4751, I have made changes to have my API use the IDToken instead of the access token. My Problem Solved. Now we have the proper Auth rules working.

Nxtra commented 3 years ago

@paulsson Thanks for your schema, very useful.

I'm wondering about the following: "As a businessAdmin, am I able to inject a location for another business"

-> a businessAdmin has full CRU access to the Location type: { allow: groups, groupsField: "businessID", operations: [create, read, update] } -> A businessAdmin can create a location with another businessID (other than his own), right?

Should we overwrite the createLocation resolver in this case?

paulsson commented 3 years ago

I'm wondering about the following: "As a businessAdmin, am I able to inject a location for another business"

-> a businessAdmin has full CRU access to the Location type: { allow: groups, groupsField: "businessID", operations: [create, read, update] } -> A businessAdmin can create a location with another businessID (other than his own), right?

Should we overwrite the createLocation resolver in this case?

@Nxtra sorry I missed this. No, a businessAdmin will not be able to create a location with another businessID. This is enforced by the groupField. They will only have create, read, update permissions for locations that have the same businessID assigned as the business that the calling user belongs to.

{ allow: groups, groupsField: "businessID", operations: [create, read, update] }

You can run this yourself in the AppSync console and see this being enforced. The location will not be created and the response will contain an unauthorized error like this:

{
  "data": {
    "createLocation": null
  },
  "errors": [
    {
      "path": [
        "createLocation"
      ],
      "data": null,
      "errorType": "Unauthorized",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": null
        }
      ],
      "message": "Not Authorized to access createLocation on type Location"
    }
  ]
}
spc16670 commented 2 years ago

I implemented the solution in my app and using claims seems to work very well - downsides are I have to configure amplify to send id token instead of access token therefore exposing user information and every time the user logs in I have to hit the db incurring all associated costs.

I have a different issue however that I am not sure where to get an advice on - I asked on SO but very few people get to view my question and there are no answers -

https://stackoverflow.com/questions/69964661/how-to-write-amplify-model-data-to-multiple-tables-based-on-some-attribute-and-e

What is the best forum to see advice on my issue?

zepelega commented 2 years ago

Hi @paulsson , can you tell me what the require did you use for this lamba, trying to find for the api.gqlCall(), I'm new to this and I can't find it in anywhere.

Hope you can help me.

const userResp = await api.gqlCall( getUserQuery, 'GetUser', { id: userSub }, graphqlEndpoint, REGION, );

nhruch commented 2 years ago

@paulsson I have the same question as @zepelega , where did this API call come from?

Separately, how is this solution possible when you have a circular dependency between Amplify's Auth (pre token lambda) and API (table that stores group). In order to create the Auth module with a pre token generation lambda, you have to give it access to the API through IAM. In order to set up the API with an IAM auth rule, you need an Auth module that depends on having a pre token generation lambda with API access. Trying to accomplish this via the Amplify CLI returns a circular dependency error.

paulsson commented 2 years ago

@zepelega api.gqlCall is just some shared common code that I wrote that is used in all my lambdas/code that needs to make GraphQL/AppSync API calls. Nothing fancy.

@nhruch here is another GitHub issue where I detailed how to break the circular dependency: https://github.com/aws-amplify/amplify-cli/issues/1874#issuecomment-606073890

paulsson commented 2 years ago

@nhruch looks like Amplify CLI added built-in functionality to break these circular dependencies. https://github.com/aws-amplify/amplify-cli/issues/4568#issuecomment-858909745

dlamon1 commented 2 years ago

Any update on this?

dlamon1 commented 2 years ago

The following is a working Lambda that includes @paulsson 's code with the addition of an API call to graphql. This works by adding "type": "module" to package.json as well as removing the loader function in function/src/index.js and replacing it with this code. Run amplify function update, select Resource access permissions, and add api.

import crypto from '@aws-crypto/sha256-js';
import { defaultProvider } from '@aws-sdk/credential-provider-node';
import { SignatureV4 } from '@aws-sdk/signature-v4';
import { HttpRequest } from '@aws-sdk/protocol-http';
import fetch from "node-fetch";
import { Request as Request } from "node-fetch";

const { Sha256 } = crypto;

// use your own endpoint here
const GRAPHQL_ENDPOINT = <YOUR_API_ENDPOINT>;
const AWS_REGION = process.env.AWS_REGION || 'us-east-2';

const query = `query GetUser(
  $id: ID!
) {
  getUser(id: $id) {
    role
    business {
      id
      locations(limit: 100) {
        items {
          id
        }
      }
    }
  }
}`;

export async function handler(event) {

  // get the user ID (Cognito sub)
  const userSub = event.request.userAttributes.sub;

  // get the user groups assigned through Cognito groups
  const groups = event.request.groupConfiguration.groupsToOverride;

  // Return early if user is admin, will have full auth access anyway
  if (groups.includes('admin')) { return event }

  const endpoint = new URL(GRAPHQL_ENDPOINT);

  const signer = new SignatureV4({
    credentials: defaultProvider(),
    region: AWS_REGION,
    service: 'appsync',
    sha256: Sha256
  });

  const requestToBeSigned = new HttpRequest({
    method: 'POST',
    headers: {
      host: endpoint.host
    },
    hostname: endpoint.host,
    body: JSON.stringify({ query: query, variables: { id: userSub } }),
    path: endpoint.pathname
  });

  const signed = await signer.sign(requestToBeSigned);
  const request = new Request(endpoint, signed);

  let statusCode = 200;
  let body;
  let response;

  try {
    response = await fetch(request);
    body = await response.json();
    if (body.errors) statusCode = 400;
  } catch (error) {
    statusCode = 400;
    body = {
      errors: [
        {
          status: response.status,
          message: error.message,
          stack: error.stack
        }
      ]
    };

    return event
  }

  // Return if no user is found in DB, handle this case
  if (!body.data.getUser) return event

  const claimsToAddOrOverride = {}
  const customGroups = [];

  const businessId = body.data.getUser?.business?.id

  if (businessId) {
    claimsToAddOrOverride.business_id = businessId
  }

  if (body.data.getUser?.role === "BUSINESS_ADMIN") {
    customGroups.push(businessId);

    // add all Business Location IDs to customGroups
    body.data.getUser?.business?.locations?.items.forEach((item) => {
      customGroups.push(item.location.id);
    });

  } else if (body.data.getUser.role === "LOCATION_ADMIN") {

    // add only the specific Location IDs that the user is assigned to
    body.data.getUser?.locations?.items.forEach((item) => {
      customGroups.push(item.location.id);
    });

    claimsToAddOrOverride.locationAdmin = businessId;

  } else {

    claimsToAddOrOverride.readAccess = businessId;
  }

  event.response = {
    claimsOverrideDetails: {
      groupOverrideDetails: {
        groupsToOverride: [...groups, ...customGroups],
      },
      claimsToAddOrOverride,
    }
  };

  return event;
}

Another hurdle as of CLI v8.5.0 is V2 of graphql. There is a breaking change where the auth rule doesn't like to read from the id's. I've changed my structure to the following and in the front end pass in the same UUID to both id and authid

type Business
  @model
  @auth(
    rules: [
      # grants "root" admins CRUD operations on all Businesses
      {
        allow: groups
        groups: ["admin"]
        operations: [create, read, update, delete]
      }
      # grants Business admins read, update operations if the calling user is an employee of (assigned to) the Business
      { allow: groups, groupsField: "authid", operations: [read, update] }
      # grants Location admins read access if the calling user is an employee of (assigned to) the Business
      {
        allow: groups
        groupsField: "authid"
        groupClaim: "locationAdmin"
        operations: [read]
      }
    ]
  ) {
  id: ID!
  authid: String!
  name: String!
  locations: [Location] @hasMany(indexName: "byBusiness", fields: ["id"])
}
BBopanna commented 2 years ago

AWS team - this feature of supporting multi tenancy is critical for enterprise grade apps. Cant believe this is open from 2018 and no action yet!! @dabit3 @kaustavghosh06 can you please help promote this ? also this is marked P4 ?!!!??? damn this is P1.

isaiahtaylor commented 2 years ago

Subscription tiers is another use case for this. Very difficult to model different types of permissions for different users without logical AND.

Crusade1337 commented 1 year ago

Being able to use AND as well as OR to combine different auth rules would make it much easier. We are currently facing the Issue, where we need to have the User (owner) to have access, as well as a group of Admins per Tenant.

IF we would be able to use AND we could just have a group "admins" and the tenant_ID in the groupfield. Then you could gran access if ( Owner || ( group: "admins" && groupfield matches)).

I feel like this feature should have been added a long time ago. Idk why this has been open since 2018 since it's such a good feature suggestion

alexanderchan commented 1 year ago

Given the complexity of this we’ve given up trying to manage using directives. In the end custom resolvers with the full power of a coding language and an auth a lambda is the better way to go for our use case when going off the beaten path rather than try to solve with a dsl. Probably not the solution people want to hear but perhaps will convince people to move off it before things go too far down a path.

Alex-Github-Account commented 1 year ago

Why not at least add an global "option" to switch logic of combining @auth rules from "OR" to "AND" between "ownership" and "group" rules? that would effectively mean that schema.graphql syntax NO needs to be changed, it would simply be interpreted with AND logic if switch is set somewhere in the AWS console. Feature of supporting multi tenancy is critical for enterprise grade apps and entrie @auth is only applicable to student projects and tutorials if we cant split by tenants.

8maxxam8 commented 1 year ago

Also interested in into this topic...

mauriceburn commented 1 year ago

Any news on this? I was new to AWS and intimidated at first. But with Amplify it’s a piece of cake… until you try to do a multi tenant app :-((( PLEASE Implement this !!!

przemekblasiak commented 1 year ago

Dear AWS Team, this is critical in order to build any scalable SaaS product. We need it urgently, please let us know if that's coming or not anytime soon.

redjonzaci commented 1 year ago

Any update on this?

redjonzaci commented 12 months ago

Honestly, I don't see that here.

image
dlamon1 commented 12 months ago

butTheYoutuberSaidThisProductWasGood

On Wed, Sep 13, 2023, 5:43 AM Redjon Zaci @.***> wrote:

Honestly, I don't see that here. [image: image] https://user-images.githubusercontent.com/73707194/267608646-fe29309b-4db0-4f4a-8ebe-94f7f11dd179.png

— Reply to this email directly, view it on GitHub https://github.com/aws-amplify/amplify-category-api/issues/449#issuecomment-1717297747, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKJQCJZCBBLSSPDMUEKFGKTX2F53HANCNFSM5WGKWFMQ . You are receiving this because you commented.Message ID: @.***>

ronaldocpontes commented 11 months ago

@mikeparisstuff @kaustavghosh06 @mdwt Is there anyone even looking at this? Is Amplify still actively supported by Amazon/AWS and if so, is multi-tenant app support a priority in Amplify's roadmap?

maziarzamani commented 11 months ago

My best guess is that this is not prioritised, hence I avoid using amplify for multi-tenant applications 😩

chrisl777 commented 11 months ago

It would be awesome if there were a multi-tenant auth/api setup and schema out-of-the-box, i.e. a template that we could apply to spin up a multi-tenant application without so many gymnastics to make it work.

ronaldocpontes commented 11 months ago

@renebrandel Would https://github.com/aws-amplify/amplify-category-api/issues/430 enable this use case for supporting Combining Owner/Groups rules for Multi-Tenant Apps?

flobo79 commented 10 months ago

Now how about we talk about alternative services which might kick AWS out out of bed? Firebase/Firestore doesnt work for me as I'm based in Germany / DSGVO compliance. What other services have you considered as alternatives for these requirements?

trevorgildersleeve commented 9 months ago

Am I understanding this right that Gen2's introduction of composite identifiers is the answer to solving multi-tenancy? https://docs.amplify.aws/gen2/build-a-backend/data/data-modeling/identifiers/

chrisl777 commented 9 months ago

One thing to look at in Gen 2 (that also exists to some degree in Gen 1), is the ability to use a Lambda for custom data access.

https://docs.amplify.aws/gen2/build-a-backend/data/customize-authz/custom-data-access-patterns/

chunyenHuang commented 9 months ago

Am I understanding this right that Gen2's introduction of composite identifiers is the answer to solving multi-tenancy? https://docs.amplify.aws/gen2/build-a-backend/data/data-modeling/identifiers/

It seems to me it just represents the primary key and sort key.

One thing to look at in Gen 2 (that also exists to some degree in Gen 1), is the ability to use a Lambda for custom data access.

https://docs.amplify.aws/gen2/build-a-backend/data/customize-authz/custom-data-access-patterns/ This looks closer to the topic. Thanks for pointing out.

maziarzamani commented 3 months ago

Any updates?