Page updated Jan 16, 2024

Set up authorization rules

Amplify gives you the ability to limit which individuals or groups should have access to create, read, update, or delete data on your types by specifying an @auth directive.

Here's a high-level overview of the authorization scenarios we support in the Amplify libraries. Each scenario has options you can tune to fit the needs of your application.

DataStore only supports authorization rules specified on this page.

The links provided below to the CLI documentation for specific authorization rules only apply to those particular rules. Datastore only supports a subset of all possible authorization rules provided by the CLI. Therefore, the other authorization rules or setups described in the linked page do not apply to Datastore.

If your app uses authentication, it is recommended to call DataStore.clear() on sign-in or sign-out to remove any user-specific data. In scenarios where a mobile device can be shared by several users, calling DataStore.clear() will ensure that data does not leak from one user to another.

Commonly used @auth rule patterns

Per User / Owner Based Data Access

The following are commonly used patterns for owner based authorization. For more information on how to fine tune these examples, please see the CLI documentation on owner based authorization.

  • Create/Read/Update/Delete mutations are private to the owner.
type YourModel @model @auth(rules: [{ allow: owner }]) { ... }
1type YourModel @model @auth(rules: [{ allow: owner }]) {
2 ...
3}
  • Owners can create and delete; other signed-in users can read and update.
type YourModel @model @auth( rules: [ { allow: owner, operations: [create, delete] } { allow: private, operations: [read, update] } ] ) { ... }
1type YourModel
2 @model
3 @auth(
4 rules: [
5 { allow: owner, operations: [create, delete] }
6 { allow: private, operations: [read, update] }
7 ]
8 ) {
9 ...
10}

Static Group Authorization

The following are commonly used patterns for static group authorization. For more information on how to fine tune these examples, please see the CLI documentation on static group authorization.

  • Users belonging to the "Admin" group can CRUD (create, read, update, and delete), others cannot access anything.
type YourModel @model @auth(rules: [{ allow: groups, groups: ["Admin"] }]) { ... }
1type YourModel @model @auth(rules: [{ allow: groups,
2 groups: ["Admin"] }]) {
3 ...
4}
  • Users belonging to the "Admin" group can create and delete, other signed users can read and update.
type YourModel @model @auth( rules: [ { allow: groups, groups: ["Admin"], operations: [create, delete] } { allow: private, operations: [read, update] } ] ) { ... }
1type YourModel
2 @model
3 @auth(
4 rules: [
5 { allow: groups, groups: ["Admin"], operations: [create, delete] }
6 { allow: private, operations: [read, update] }
7 ]
8 ) {
9 ...
10}

Owner and Static Group Combined

The following are commonly used patterns for combining owner and static group authorization. For more information on how to fine tune these examples, please see the CLI documentation on static group authorization.

  • Users have their own data, but users who belong to the Admin group have access to their data and anyone else in that group. Users in the Admin group have the ability to make mutation on behalf of users not in the Admin group
type YourModel @model @auth(rules: [{ allow: owner }, { allow: groups, groups: ["Admin"] }]) { ... }
1type YourModel
2 @model
3 @auth(rules: [{ allow: owner }, { allow: groups, groups: ["Admin"] }]) {
4 ...
5}

Public Data Access

The following are commonly used patterns to grant everyone access. For more information on how to fine tune these examples, please see the CLI documentation on public data access.

  • Auth provider is API Key
type YourModel @model @auth(rules: [{ allow: public }]) { ... }
1type YourModel @model @auth(rules: [{ allow: public }]) {
2 ...
3}
  • Auth provider is IAM
type YourModel @model @auth(rules: [{ allow: public, provider: iam }]) { ... }
1type YourModel @model @auth(rules: [{ allow: public, provider: iam }]) {
2 ...
3}

Signed-in User Data Access

The following are commonly used patterns for private authorization. For more information on how to fine tune these examples, please see the CLI documentation on signed-in user data access.

  • Cognito user pool authenticated users can CRUD all posts, regardless of who created it. Guest users do not have access.
type YourModel @model @auth(rules: [{ allow: private }]) { ... }
1type YourModel @model @auth(rules: [{ allow: private }]) {
2 ...
3}
  • IAM authenticated users can CRUD all posts, regardless of who created it. Guest users do not have access:
type YourModel @model @auth(rules: [{ allow: private, provider: iam }]) { ... }
1type YourModel @model @auth(rules: [{ allow: private, provider: iam }]) {
2 ...
3}

Owner based Authorization with OIDC provider

The following are commonly used patterns for owner based authorization using a 3rd party OIDC provider (e.g. Facebook, Google, etc...). For more information on how to fine tune these examples, please see the CLI documentation on using an oidc authorization provider.

  • Using a 3rd party OIDC provider to achieve owner based authorization.
type YourModel @model @auth(rules: [{ allow: owner, provider: oidc, identityClaim: "sub" }]) { ... }
1type YourModel
2 @model
3 @auth(rules: [{ allow: owner, provider: oidc, identityClaim: "sub" }]) {
4 ...
5}

When using a third-party OIDC auth provider, you are required to provide an instance of APIAuthProviderFactory. Your factory implementation must be capable of creating objects conforming to the AmplifyOIDCAuthProvider protocol. The responsibility of the AmplifyOIDCAuthProvider is to return the JWT token that was provided by your OIDC provider. To do this:

  • Create a subclass of APIAuthProviderFactory
class MyAPIAuthProviderFactory: APIAuthProviderFactory { let myAuthProvider = MyOIDCAuthProvider() override func oidcAuthProvider() -> AmplifyOIDCAuthProvider? { return myAuthProvider } }
1class MyAPIAuthProviderFactory: APIAuthProviderFactory {
2 let myAuthProvider = MyOIDCAuthProvider()
3
4 override func oidcAuthProvider() -> AmplifyOIDCAuthProvider? {
5 return myAuthProvider
6 }
7}
  • Implement your class which conforms to AmplifyOIDCAuthProvider:
class MyOIDCAuthProvider : AmplifyOIDCAuthProvider { func getLatestAuthToken() async throws -> String { .... } }
1class MyOIDCAuthProvider : AmplifyOIDCAuthProvider {
2 func getLatestAuthToken() async throws -> String {
3 ....
4 }
5}
  • Finally, register your instance of APIAuthProviderFactory prior to calling Amplify.configure():
let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels()) try Amplify.add(plugin: dataStorePlugin) try Amplify.add(plugin: AWSAPIPlugin(apiAuthProviderFactory: MyAPIAuthProviderFactory())) try Amplify.configure()
1let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels())
2try Amplify.add(plugin: dataStorePlugin)
3try Amplify.add(plugin: AWSAPIPlugin(apiAuthProviderFactory: MyAPIAuthProviderFactory()))
4try Amplify.configure()

Static Group Authorization with OIDC provider

The following are commonly used patterns for using groupClaims to achieve group based authorization using a 3rd party OIDC provider. For more information on how to fine tune these examples, please see the CLI documentation on static group authorization.

  • Using a custom value for groupClaim to achieve static group authorization with a 3rd party OIDC provider.
type YourModel @model @auth( rules: [ { allow: groups provider: oidc groups: ["Admin"] groupClaim: "https://myapp.com/claims/groups" } ] ) { ... }
1type YourModel
2 @model
3 @auth(
4 rules: [
5 {
6 allow: groups
7 provider: oidc
8 groups: ["Admin"]
9 groupClaim: "https://myapp.com/claims/groups"
10 }
11 ]
12 ) {
13 ...
14}

Configure Multiple Authorization Types

For some use cases, you will want DataStore to use multiple authorization types. For example, an app might use API Key for public content and Cognito User Pool for personalized content once the user logs in.

By default, DataStore uses your API's default authorization type specified in the amplifyconfiguration.json/.dart/aws-exports.js file. Every network request sent through DataStore uses that authorization type, regardless of the model's @auth rule. To change the default authorization type, run amplify update api.

To enable DataStore to use multiple authorization types based on the model's @auth rules, run amplify update api to configure additional auth types and deploy by running amplify push. Then, configure the "auth mode strategy" when initializing DataStore:

In your App scene, configure Amplify in the initializer:

@main struct MyAmplifyApp: App { var body: some Scene { WindowGroup { ContentView() } } init() { do { let datastoreConfiguration = DataStoreConfiguration.custom(authModeStrategy: .multiAuth) let dataStorePlugin = AWSDataStorePlugin( modelRegistration: AmplifyModels(), configuration: datastoreConfiguration ) try Amplify.add(plugin: dataStorePlugin) try Amplify.configure() print("Amplify configured with DataStore plugin") } catch { print("Failed to initialize Amplify with \(error)") } } }
1@main
2struct MyAmplifyApp: App {
3
4 var body: some Scene {
5 WindowGroup {
6 ContentView()
7 }
8 }
9
10 init() {
11 do {
12 let datastoreConfiguration = DataStoreConfiguration.custom(authModeStrategy: .multiAuth)
13 let dataStorePlugin = AWSDataStorePlugin(
14 modelRegistration: AmplifyModels(),
15 configuration: datastoreConfiguration
16 )
17 try Amplify.add(plugin: dataStorePlugin)
18 try Amplify.configure()
19 print("Amplify configured with DataStore plugin")
20 } catch {
21 print("Failed to initialize Amplify with \(error)")
22 }
23 }
24}

Add to your AppDelegate's application:didFinishLaunchingWithOptions method

func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { do { let datastoreConfiguration = DataStoreConfiguration.custom(authModeStrategy: .multiAuth) let dataStorePlugin = AWSDataStorePlugin( modelRegistration: AmplifyModels(), configuration: datastoreConfiguration ) try Amplify.configure() print("Amplify configured with DataStore plugin") } catch { print("Failed to initialize Amplify with \(error)") return false } return true }
1func application(
2 _ application: UIApplication,
3 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
4) -> Bool {
5
6 do {
7 let datastoreConfiguration = DataStoreConfiguration.custom(authModeStrategy: .multiAuth)
8 let dataStorePlugin = AWSDataStorePlugin(
9 modelRegistration: AmplifyModels(),
10 configuration: datastoreConfiguration
11 )
12 try Amplify.configure()
13 print("Amplify configured with DataStore plugin")
14 } catch {
15 print("Failed to initialize Amplify with \(error)")
16 return false
17 }
18
19 return true
20}

This configuration enables DataStore to synchronize data using the model's @auth rule provider for each model.

Multiple authorization types priority order

If there are multiple @auth rules on a model, the rules will be ranked by priority (see below), and DataStore will attempt the synchronization with each authorization type until one succeeds (or they all fail).

Priorityallow: AuthStrategyprovider
1owneruserPools
2owneroidc
3groupuserPools
4groupoidc
5privateuserPools
6privateiam
7publiciam
8publicapiKey

If there is not an authenticated user session, DataStore will only attempt public rules.

If a model has no auth rules defined, DataStore will continue to use the default authorization type from amplifyconfiguration.json/.dart.

Example with multiple authorization types

type YourModel @model @auth( rules: [ { allow: owner } { allow: public, provider: apiKey, operations: [read] } ] ) { ... }
1type YourModel
2 @model
3 @auth(
4 rules: [
5 { allow: owner }
6 { allow: public, provider: apiKey, operations: [read] }
7 ]
8 ) {
9 ...
10}

DataStore will attempt to use owner-based authorization first when synchronizing data if there is an authenticated user. If that request fails for some reason, DataStore will attempt the request again with public authorization. If there is no authenticated user, public authorization will be used.