aws-amplify / amplify-cli

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development.
Apache License 2.0
2.82k stars 820 forks source link

Viewer support #740

Closed michael-golfi closed 4 years ago

michael-golfi commented 5 years ago

Is your feature request related to a problem? Please describe. I'd like to have a viewer context for current authenticated user for multi-user applications without needing to add manually to the query, resolvers and CF template.

Describe the solution you'd like I'd like to create a viewer transformer to implement automatically adding a viewer field to the query type that looks at the identity username to search for current user.

Describe alternatives you've considered I've tried manually adding the fields, indexes and resolvers but they would get erased after every amplify push unless if I stop auto-compiling the gql.

michael-golfi commented 5 years ago

Would that PR be the right approach to tackle this?

mikeparisstuff commented 5 years ago

Hey @michael-golfi, I think this is a great idea and can be tackled in two steps. The first step would be to propose a design here so that we can get community feedback before diving into an implementation. This is a use case that I suspect a lot of people run into and I think we would benefit from hearing more about those scenarios. The API category currently focuses on User Pools as a authentication provider but we should think about how a viewer would work with other auth providers that will be supported in the future. We are working on a number of changes that will allow you to implement a viewer field yourself (see #574) but I could see this generalizing to something like:

directive @viewer on FIELD_DEFINITION

which could be used:

# Would match up to the shape of your "identity"
type User {
}
type Query {
  me: User @viewer  # adds a resolver that returns $ctx.identity
}

One problem with the above design is that your APIs "User" type would have to partially match with the shape of your $ctx.identity. We could potentially get around this with an argument like:

directive @viewer(fields: [FieldMapping]) on FIELD_DEFINITION
input FieldMapping {
  api: String, 
  identity: String
}

would would be used like so

# Would match up to the shape of your "identity"
type User {
  username: String
}
type Query {
  me: User @viewer(fields: [{ api: "username", identity: "claims.username" }])  
   # adds a resolver that maps the `$ctx.identity.claims.username` to the username field in the api.
   # this allows you to map custom identity fields to any api field
}

This is one idea but please share your own design. We are very happy to accept PRs as well but for features as impactful as this it would be helpful to hear a few different options.

michael-golfi commented 5 years ago

Thanks @mikeparisstuff !

Sorry - I definitely didn't intend on overriding any existing work and efforts done to-date. I started working on this and only then realized this might be reusable for others.

Connecting a viewer to an identity sounds like a really great idea. Are there any plans to generalize that for having user fields that directly query a cognito pool, among other identity providers?

Something like the following user model?

type CognitoUser @cognito_model {
    id: ID
    username: String
    email: String
    phone: String
}

type Query {
    getUser(id: ID!): CognitoUser
    listUsers(...): [CognitoUser]
}
mikeparisstuff commented 5 years ago

We have discussed approaches like this in the past and will continue to improve auth use cases in the future. Before going too deep down the rabbit hole can I ask that you provide more details on the particular use cases you are trying to solve for? It is technically possible to call out to the Cognito API from AppSync today using HTTP resolvers but it will be more performant to implement a viewer field that looks directly at the $ctx.identity as it will reduce the number of network calls.

Also, you can currently "fake" a Query.viewer field by creating user objects in DynamoDB and then using @auth and Query.getUser(id: "my-cognito-username-or-sub") to protect and request information for the logged in user. I agree that having a direct path to the logged in user identity is useful, but given that there are many ways to implement a solution, I want to make sure we are solving problems that are driven by real world use cases.

kaustavghosh06 commented 4 years ago

Closing due to lack of further customer engagement and community interest. Please feel free to comment on this thread or open up a new issue if you're still stuck on this issue.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels for those types of questions.