The `AWSMobileClient` provides client APIs and building blocks for developers who want to create user authentication experiences. This includes declarative methods for performing authentication actions, a simple "drop-in auth" UI for performing common tasks, automatic token and credentials management, and state tracking with notifications for performing workflows in your application when users have authenticated.

**Amazon Cognito**

[Amazon Cognito User Pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html) is a full-featured user directory service to handle user registration, storage, authentication, and account recovery. Cognito User Pools returns JWT tokens to your app and does not provide temporary AWS credentials for calling authorized AWS Services.
[Amazon Cognito Federated Identities](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html) on the other hand, is a way to authorize your users to use AWS services. With an identity pool, you can obtain temporary AWS credentials with permissions you define to access other AWS services directly or to access resources through Amazon API Gateway.

When working together, Cognito User Pools acts as a source of user identities (identity provider) for the Cognito Federated Identities. Other sources can be OpenID, Facebook, Google, etc. AWS Amplify uses User Pools to store your user information and handle authorization, and it leverages Federated Identities to manage user access to AWS Resources, for example allowing a user to upload a file to an S3 bucket.

**Prerequisite:** [Install and configure the Amplify CLI](/cli)<br/>
**Recommendation:** [Complete the Getting Started guide](/start)

## How it works

The AWSMobileClient manages your application session for authentication related tasks. The credentials it pulls in can be used by other AWS services when you call a `.getInstance()` constructor. The Amplify category examples in this documentation use this by default, however [you can also use this with any AWS service via the generated SDK clients](/sdk/configuration/setup-options).

### State tracking

`AWSMobileClient` offers on-demand querying for the "login state" of a user in the application. For instance, you can check if the user is signed-in or not and present an appropriate screen. This is done through a couple of mechanisms:

- `isSignedIn` property defined as a BOOLEAN for the most simple use cases
- `currentUserState` used for more advanced scenarios, such as determining if the user has Guest credentials, Authenticated with User Pools, has Federated credentials, or has signed out.

This allows you to write workflows in your application based on the state of the user and what you would like to present on different screens. The `AWSMobileClient` also offers realtime notifications on user state changes which you can register for in your application using `.addUserStateListener()` as in the code below.

```java
AWSMobileClient.getInstance().addUserStateListener(new UserStateListener() {
    @Override
    public void onUserStateChanged(UserStateDetails userStateDetails) {
        switch (userStateDetails.getUserState()){
            case GUEST:
                Log.i("AuthQuickStart", "user is in guest mode");
                break;
            case SIGNED_OUT:
                Log.i("AuthQuickStart", "user is signed out");
                break;
            case SIGNED_IN:
                Log.i("AuthQuickStart", "user is signed in");
                break;
            case SIGNED_OUT_USER_POOLS_TOKENS_INVALID:
                Log.i("AuthQuickStart", "need to login again");
                break;
            case SIGNED_OUT_FEDERATED_TOKENS_INVALID:
                Log.i("AuthQuickStart", "user logged in via federation, but currently needs new tokens");
                break;
            default:
                Log.e("AuthQuickStart", "unsupported");
        }
    }
});
```

### Token fetch and refresh

#### Cognito User Pool tokens
The `AWSMobileClient` will return valid JWT tokens from your cache immediately if they have not expired. If they have expired it will look for a **Refresh** token in the cache. If it is available and not expired it will be used to fetch a valid **IdToken** and **AccessToken** and store them in the cache.

If the Refresh tokens have expired and you then make call to any AWS service, such as a AppSync GraphQL request or S3 upload, the `AWSMobileClient` will dispatch a state notification that a re-login is required. At this point you can choose to present the user with a login screen, call `AWSMobileClient.default().signIn()`, or perform custom business logic. For example:

```java
AWSMobileClient.getInstance().addUserStateListener(new UserStateListener() {
    @Override
    public void onUserStateChanged(UserStateDetails userStateDetails) {
        switch (userStateDetails.getUserState()) {
            case SIGNED_OUT:
                // user clicked signout button and signedout
                Log.i("AuthQuickStart", "user signed out");
                break;
            case SIGNED_OUT_USER_POOLS_TOKENS_INVALID:
                Log.i("AuthQuickStart", "need to login again.");
                AWSMobileClient.getInstance().signIn(username, password, null, new Callback<SignInResult>() {
                    //... 
                });
                //Alternatively call .showSignIn()
                break;
            default:
                Log.i("AuthQuickStart", "unsupported");
        }
    }
});
```

You can register to listen for this state change anywhere in your app with `.addUserStateListener()`, such as in `onCreate()` in the above example. If you want to cancel the re-login process, for instance if your application is shared among multiple users of the device or a user clicks "cancel" on the re-login attempt, you can call `releaseSignInWait()` to terminate the call and then call a `signOut()`.

#### AWS Credentials

AWS Credentials are used for signing requests to services that use AWS IAM, and for mobile clients they are provided by Amazon Cognito Identity Pools. Similar to JWT tokens, `AWSMobileClient` will return valid AWS Credentials from your cache immediately if they have not expired. If they are expired they will be refreshed using the JWT token that has been federated if the session is authenticated. For Guest scenarios they will be automatically refreshed. 

### Offline support

`AWSMobileClient` is optimized to account for applications transitioning from offline to online connectivity, and refreshing credentials at the appropriate time so that errors do not occur when actions are taken and connectivity is not available. In no cases will the `AWSMobileClient` automatically sign out a user if connectivity is not available. You must always make an explicit `signOut()` call for a user to be signed out of a session. 

In most cases if you are offline and make a service request, and your tokens are valid, the `AWSMobileClient` will pass the request directly to the service client. Therefore it is your responsibility to check network connectivity. In the case of the AWS AppSync client it supports offline operations and the request will be enqueued and automatically sent when connectivity is restored, refreshing credentials if necessary. [See the API guide for more information on AppSync](/sdk/api/graphql).

If you are offline and make a service request, and your tokens are **NOT** valid, the service request will be blocked and notifications for `SIGNED_OUT_USER_POOLS_TOKENS_INVALID` or `SIGNED_OUT_FEDERATED_TOKENS_INVALID` will be sent to the listener. In the case of the AppSync client this can be ignored and the queries will come from cache or mutations enqueued with credentials automatically refreshing upon reconnection. For all other services, if this happens and you are offline you should not make the service request until you come back online, at which point the `AWSMobileClient` will automatically re-enter the token refresh flow outlined above and then make the service call with the updated credentials.
