Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add client examples of accessing models with specific auth modes #7080

Merged
merged 20 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c5df46d
add client side code for public access
chrisbonifacio Mar 19, 2024
045a302
add client side code for signed in user access
chrisbonifacio Mar 19, 2024
dc78ce2
add client side code for multi user access
chrisbonifacio Mar 19, 2024
f5d9399
add client side code for per user/owner access
chrisbonifacio Mar 19, 2024
2d067ad
add client side code for custom id & group claims
chrisbonifacio Mar 19, 2024
76e5437
add client side code for custom access
chrisbonifacio Mar 19, 2024
82e9471
add client side code for user pool group access
chrisbonifacio Mar 19, 2024
5d00b1b
add client side code for oidc access
chrisbonifacio Mar 19, 2024
d452b89
Update src/pages/gen2/build-a-backend/data/customize-authz/signed-in-…
chrisbonifacio Mar 27, 2024
5db56fa
add info callout and configuration code to public/private iam examples
chrisbonifacio Apr 8, 2024
2ca526a
move callout up
chrisbonifacio Apr 8, 2024
78371c4
remove "**note**" from callouts
chrisbonifacio Apr 8, 2024
2d5be52
remove allowGuestAccess info from private iam example
chrisbonifacio Apr 11, 2024
ef584f3
edit the public iam example, adding allowGuestAss to Amplify.configur…
chrisbonifacio Apr 11, 2024
bc39f46
add ts tag and accordion title
chrisbonifacio Apr 11, 2024
06b6c54
Update src/pages/gen2/build-a-backend/data/customize-authz/configure-…
renebrandel Apr 11, 2024
71ccb79
Merge branch 'main' into cbonif/client-code-for-data-auth
chrisbonifacio Apr 11, 2024
b60a787
<ModelName> > <model-name>
chrisbonifacio Apr 11, 2024
45c0243
add filename titles to code snippets
chrisbonifacio Apr 12, 2024
0117ae2
Update src/pages/gen2/build-a-backend/data/customize-authz/public-dat…
renebrandel Apr 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Amplify Data supports using custom identity and group claims if you do not wish

To use custom claims specify `identityClaim` or `groupClaim` as appropriate. In the example below, the `identityClaim` is specified and the record owner will check against this `user_id` claim. Similarly, if the `user_groups` claim contains a "Moderator" string then access will be granted.

```ts
```ts title="amplify/data/resource.ts"
import { a, defineData, type ClientSchema } from '@aws-amplify/backend';

const schema = a.schema({
Expand All @@ -37,3 +37,24 @@ export type Schema = ClientSchema<typeof schema>;
export const data = defineData({ schema });

```

In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` with the `userPool` auth mode.
renebrandel marked this conversation as resolved.
Show resolved Hide resolved

```ts
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

const { errors, data: newTodo } = await client.models.Todo.create(
{
postname: 'My New Post'
content: 'My post content',
},
// highlight-start
{
authMode: 'userPool',
}
// highlight-end
);
```
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function getStaticProps(context) {

You can define your own custom authorization rule with a Lambda function.

```ts
```ts title="amplify/data/resource.ts"
import {
type ClientSchema,
a,
Expand Down Expand Up @@ -51,6 +51,26 @@ export const data = defineData({
});
```

In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` with the `lambda` auth mode.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

const { errors, data: newTodo } = await client.models.Todo.create(
{
content: 'My new todo',
},
// highlight-start
{
authMode: 'lambda',
}
// highlight-end
);
```

The Lambda function of choice will receive an authorization token from the client and execute the desired authorization logic. The AppSync GraphQL API will receive a payload from Lambda after invocation to allow or deny the API call accordingly.

To configure a Lambda function as the authorization mode, create a new file `amplify/data/custom-authorizer.ts`. You can use this Lambda function code template as a starting point for your authorization handler code:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The `multipleOwners` rule grants a set of users access to a record by automatica

If you want to grant a set of users access to a record, you use the `multipleOwners` rule. This automatically creates a `owner: a.string().array()` field to store the allowed owners.

```ts
```ts title="amplify/data/resource.ts"
const schema = a.schema({
Todo: a
.model({
Expand All @@ -28,6 +28,41 @@ const schema = a.schema({
});
```

In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` with the `userPool` auth mode.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

// Create a record with current user as first owner
const { errors, data: newTodo } = await client.models.Todo.create(
{
content: 'My new todo',
},
// highlight-start
{
authMode: 'userPool',
}
// highlight-end
);
```
```ts
// Add another user as an owner
await client.models.Todo.update(
{
id: newTodo.id,
owner: [...(newTodo.owner as string[]), otherUserId],
},
// highlight-start
{
authMode: "userPool"
}
// highlight-end
);
```

## Override to a list of owners

You can override the `inField` to a list of owners. Use this if you want a dynamic set of users to have access to a record. In the example below, the `authors` list is populated with the creator of the record upon record creation. The creator can then update the `authors` field with additional users. Any user listed in the `authors` field can access the record.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ The `owner` authorization strategy restricts operations on a record to only the

You can use the `owner` authorization strategy to restrict a record's access to a specific user. When `owner` authorization is configured, only the record's `owner` is allowed the specified operations.

```ts

```ts title="amplify/data/resource.ts"
// The "owner" of a Todo is allowed to create, read, update, and delete their own todos
const schema = a.schema({
Todo: a
Expand All @@ -29,7 +30,7 @@ const schema = a.schema({
});
```

```ts
```ts title="amplify/data/resource.ts"
// The "owner" of a Todo record is only allowed to create, read, and update it.
// The "owner" of a Todo record is denied to delete it.
const schema = a.schema({
Expand All @@ -41,6 +42,26 @@ const schema = a.schema({
});
```

In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` with the `userPool` auth mode.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

const { errors, data: newTodo } = await client.models.Todo.create(
{
content: 'My new todo',
},
// highlight-start
{
authMode: 'userPool',
}
// highlight-end
);
```

Behind the scenes, Amplify will automatically add a `owner: a.string()` field to each record which contains the record owner's identity information upon record creation.

By default, the Cognito user pool's user information is populated into the `owner` field. The value saved includes `sub` and `username` in the format `<sub>::<username>`. The API will authorize against the full value of `<sub>::<username>` or `sub` / `username` separately and return `username`. You can alternatively configure [OpenID Connect as an authorization provider](/gen2/build-a-backend/data/customize-authz/using-oidc-authorization-provider).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The public authorization strategy grants everyone access to the API, which is pr

To grant everyone access, use the `.public()` authorization strategy. Behind the scenes, the API will be protected with an API key.

```ts
```ts title="amplify/data/resource.ts"
const schema = a.schema({
Todo: a
.model({
Expand All @@ -27,11 +27,31 @@ const schema = a.schema({
});
```

In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` by specifying the `apiKey` auth mode.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

const { errors, data: newTodo } = await client.models.Todo.create(
{
content: 'My new todo',
},
// highlight-start
{
authMode: 'apiKey',
}
// highlight-end
);
```

## Add public authorization rule using IAM authentication

You can also override the authorization provider. In the example below, `iam` is specified as the provider which allows you to use an "Unauthenticated Role" from the Cognito identity pool for public access instead of an API key. Your Auth resources defined in `amplify/auth/resource.ts` generates scoped down IAM policies for the "Unauthenticated role" in the Cognito identity pool automatically.

```ts
```ts title="amplify/data/resource.ts"
const schema = a.schema({
Todo: a
.model({
Expand All @@ -40,3 +60,49 @@ const schema = a.schema({
.authorization([a.allow.public('iam')]),
});
```

In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` with the `iam` auth mode.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

<Callout info>
In the Amplify Library's client configuration file (`amplifyconfiguration.json`) set `allowGuestAccess` to `true`. This lets the Amplify Library use the unauthenticated role from your Cognito identity pool when your user isn't logged in.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

<Accordion title="amplifyconfiguration.json">
```json
{
"Auth": {
"Cognito": {
"userPoolId": "YOUR_USER_POOL_ID",
"userPoolClientId": "YOUR_USER_POOL_CLIENT_ID",
"identityPoolId": "YOUR_IDENTITY_POOL_ID",
"allowGuestAccess": true
},
},
"API": {
"GraphQL": {
"endpoint": "YOUR_API_ENDPOINT",
"region": "YOUR_API_REGION",
"defaultAuthMode": "YOUR_DEFAULT_AUTHORIZATION_MODE",
},
},
}
```
</Accordion>
</Callout>

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

const { errors, data: newTodo } = await client.models.Todo.create(
{
content: 'My new todo',
},
// highlight-start
{
authMode: 'iam',
}
// highlight-end
);
```
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ You can use the `private` authorization strategy to restrict a record's access t

In the example below, anyone with a valid JWT token from the Cognito user pool is allowed access to all Todos.

```ts
```ts title="amplify/data/resource.ts"
const schema = a.schema({
Todo: a
.model({
Expand All @@ -33,11 +33,32 @@ const schema = a.schema({
});
```

## Override the authentication provider
In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` with the `userPool` auth mode.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

const { errors, data: newTodo } = await client.models.Todo.create(
{
content: 'My new todo',
},
// highlight-start
{
authMode: 'userPool',
}
// highlight-end
);
```

## Use identity pool for signed-in user authentication

You can also override the authorization provider. In the example below, `iam` is specified as the provider which allows you to use an "Unauthenticated Role" from the Cognito identity pool for public access instead of an API key. Your Auth resources defined in `amplify/auth/resource.ts` generates scoped down IAM policies for the "Unauthenticated role" in the Cognito identity pool automatically.

```ts

```ts title="amplify/data/resource.ts"
const schema = a.schema({
Todo: a
.model({
Expand All @@ -47,4 +68,50 @@ const schema = a.schema({
});
```

In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` with the `iam` auth mode.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

<Callout info>
In the Amplify Library's client configuration file (`amplifyconfiguration.json`) set `allowGuestAccess` to `true`. This lets the Amplify Library use the authenticated role from your Cognito identity pool when your user is logged in.

<Accordion title="amplifyconfiguration.json">
```json
{
"Auth": {
"Cognito": {
"userPoolId": "YOUR_USER_POOL_ID",
"userPoolClientId": "YOUR_USER_POOL_CLIENT_ID",
"identityPoolId": "YOUR_IDENTITY_POOL_ID",
"allowGuestAccess": true
},
},
"API": {
"GraphQL": {
"endpoint": "YOUR_API_ENDPOINT",
"region": "YOUR_API_REGION",
"defaultAuthMode": "YOUR_DEFAULT_AUTHORIZATION_MODE",
},
},
}
```
</Accordion>
</Callout>

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

const { errors, data: newTodo } = await client.models.Todo.create(
{
content: 'My new todo',
},
// highlight-start
{
authMode: 'iam',
}
// highlight-end
);
```

In addition, you can also use OpenID Connect with `private` authorization. See [OpenID Connect as an authorization provider](/gen2/build-a-backend/data/customize-authz/using-oidc-authorization-provider/).
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You can use the `group` authorization strategy to restrict access based on user

When you want to restrict access to a specific set of user groups, provide the group names in the `groups` parameter. In the example below, only users that are part of the "Admin" user group are granted access to the Salary model.

```ts
```ts title="amplify/data/resource.ts"
// allow one specific group
const schema = a.schema({
Salary: a
Expand All @@ -29,6 +29,28 @@ const schema = a.schema({
});
```

In your application, you can perform CRUD operations against the model using `client.models.<ModelName>` with the `userPool` auth mode.
chrisbonifacio marked this conversation as resolved.
Show resolved Hide resolved

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

// As a signed-in user that belongs to the 'Admin' User Pool Group
const { errors, data: newSalary } = await client.models.Salary.create(
{
wage: 50.25,
currency: 'USD'
},
// highlight-start
{
authMode: 'userPool',
}
// highlight-end
);
```

This can then be updated to allow access to multiple defined groups; in this example below we added access for "Leadership".

```ts
Expand Down
Loading
Loading