This section covers the client-side development experience for password and user management. To learn more about exposing administration actions to your application, click [here](/cli/auth/admin).

## Password operations

### Change password

<BlockSwitcher>
<Block name="TypeScript">

```ts
import { Auth } from 'aws-amplify';

async function changePassword (oldPassword: string, newPassword: string) {
  try {
    const user = await Auth.currentAuthenticatedUser();
    const data = await Auth.changePassword(user, oldPassword, newPassword);
    console.log(data);
  } catch(err) {
    console.log(err);
  }
};
```
</Block>
<Block name="JavaScript">

```javascript
import { Auth } from 'aws-amplify';

async function changePassword (oldPassword, newPassword) {
  try {
    const user = await Auth.currentAuthenticatedUser();
    const data = await Auth.changePassword(user, oldPassword, newPassword);
    console.log(data);
  } catch(err) {
    console.log(err);
  }
};
```
</Block>
</BlockSwitcher>

### Forgot password

<BlockSwitcher>
<Block name="TypeScript">

```ts
// Send confirmation code to user's email
async function forgotPassword(username: string) {
  try {
    const data = await Auth.forgotPassword(username);
    console.log(data);
  } catch(err) {
    console.log(err);
  }
};

// Collect confirmation code and new password
async function forgotPasswordSubmit(username: string, code: string, newPassword: string) {
  try {
    const data = await Auth.forgotPasswordSubmit(username, code, newPassword);
    console.log(data);
  } catch(err) {
    console.log(err);
  }
};
```
</Block>
<Block name="JavaScript">

```javascript
import { Auth } from 'aws-amplify';

// Send confirmation code to user's email
async function forgotPassword(username) {
  try {
    const data = await Auth.forgotPassword(username);
    console.log(data);
  } catch(err) {
    console.log(err);
  }
} 

// Collect confirmation code and new password
async function forgotPasswordSubmit(username, code, newPassword) {
  try {
    const data = await Auth.forgotPasswordSubmit(username, code, newPassword);
    console.log(data);
  } catch(err) {
    console.log(err);
  }
}
```
</Block>
</BlockSwitcher>

### Complete new password

The user is asked to provide the new password and required attributes during the first sign-in attempt if a valid user directory is created in Amazon Cognito. During this scenario, the following method can be called to process the new password entered by the user.

<BlockSwitcher>
<Block name="TypeScript">

```ts
import { Auth } from 'aws-amplify';

async function completeNewPassword(username: string, password: string) {
  try {
    const user = await Auth.signIn(username, password);

    if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
      const { requiredAttributes } = user.challengeParam; // the array of required attributes, e.g ['email', 'phone_number']
    }
const newPassword = 'newPassword'
    const loggedInUser = await Auth.completeNewPassword(
      user, // the Cognito User Object
      newPassword, // the new password
      // OPTIONAL, the required attributes
      {
        email: 'xxxx@example.com',
        phone_number: '1234567890'
      }
    )

    console.log(loggedInUser);
  } catch(err) {
    console.log(err);
  }
};
```
</Block>
<Block name="JavaScript">

```js
import { Auth } from 'aws-amplify';

async function completeNewPassword(username, password) {
  try {
    const user = await Auth.signIn(username, password);
const newPassword = 'newPassword'
    if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
      const { requiredAttributes } = user.challengeParam; // the array of required attributes, e.g ['email', 'phone_number']
      const loggedInUser = await Auth.completeNewPassword(
        user, // the Cognito User Object
        newPassword, // the new password
        // OPTIONAL, the required attributes
        {
          email: 'xxxx@example.com',
          phone_number: '1234567890'
        }
      )

      console.log(loggedInUser);
    }
  } catch(err) {
    console.log(err);
  }
};
```
</Block>
</BlockSwitcher>

## Account recovery verification

Either the phone number or the email address is required for account recovery. You can let the user verify those attributes by:

<BlockSwitcher>
<Block name="TypeScript">

```ts
// To initiate the process of verifying the attribute like 'phone_number' or 'email'
async function verifyCurrentUserAttribute(attr: string) {
  try {
    await Auth.verifyCurrentUserAttribute(attr);
    console.log('a verification code is sent');
  } catch(err) {
    console.log('failed with error', err);
  }
};

// To verify attribute with the code
async function verifyCurrentUserAttributeSubmit(attr: string, verificationCode: string) {
  try {
    await Auth.verifyCurrentUserAttributeSubmit(attr, verificationCode);
    console.log('phone_number verified');
  } catch(err) {
    console.log('failed with error', err);
  }
};
```
</Block>
<Block name="JavaScript">

```javascript
// To initiate the process of verifying the attribute like 'phone_number' or 'email'
async function verifyCurrentUserAttribute(attr) {
  try {
    await Auth.verifyCurrentUserAttribute(attr);
    console.log('a verification code is sent');
  } catch(err) {
    console.log('failed with error', err);
  }
};

// To verify attribute with the code
async function verifyCurrentUserAttributeSubmit(attr, verificationCode) {
  try {
    await Auth.verifyCurrentUserAttribute(attr, verificationCode);
    console.log('phone_number verified');
  } catch(err) {
    console.log('failed with error', err);
  }
};
```
</Block>
</BlockSwitcher>


## Retrieve current authenticated user

You can call `Auth.currentAuthenticatedUser()` to get the current authenticated user object.

<BlockSwitcher>
<Block name="TypeScript">

```ts
import { Auth } from 'aws-amplify';

async function currentAuthenticatedUser() {
  try {
    const user = await Auth.currentAuthenticatedUser({
      bypassCache: false // Optional, By default is false. If set to true, this call will send a request to Cognito to get the latest user data
    });
    console.log(user);
  } catch(err) {
    console.log(err);
  }
};
```
</Block>
<Block name="JavaScript">

```javascript
import { Auth } from 'aws-amplify';

async function currentAuthenticatedUser() {
  try {
    const user = Auth.currentAuthenticatedUser({
      bypassCache: false // Optional, By default is false. If set to true, this call will send a request to Cognito to get the latest user data
    });
  } catch(err) {
    console.log(err);
  }
};
```
</Block>
</BlockSwitcher>

This method can be used to check if a user is logged in when the page is loaded. It will throw an error if there is no user logged in. This method should be called after the Auth module is configured or the user is logged in. To ensure that you can listen on the auth events `configured` or `signIn`. [Learn how to listen on auth events.](/lib/utilities/hub#authentication-events)

### Retrieve attributes for current authenticated user

You can also access the user's attributes like their email address, phone number, sub, or any other attributes that are associated with them from the user object returned by `Auth.currentAuthenticatedUser`.

```ts
const { attributes } = await Auth.currentAuthenticatedUser();
```

## Retrieve current session

`Auth.currentSession()` returns a `CognitoUserSession` object which contains JWT `accessToken`, `idToken`, and `refreshToken`.

This method will automatically refresh the `accessToken` and `idToken` if tokens are expired and a valid `refreshToken` presented. So you can use this method to refresh the session if needed.

```javascript
import { Auth } from 'aws-amplify';

async function currentSession() {
  try {
    const data = await Auth.currentSession();
    console.log(data);
  } catch(err) {
    console.log(err);
  }
};
```

## Managing user attributes

Attributes such as name, email address, phone number help you identify individual users. The Amplify JavaScript library contains 
a set of APIs that can help you manage attributes in your user pool.

### Pass user attributes during sign up

Amazon Cognito has a set of default standard attributes; you also have the ability to define custom attributes.
Up to 50 custom attributes can be added to your user pool. 
You can find a [list of all the standard attributes here](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#cognito-user-pools-standard-attributes) and [documentation for custom attributes here](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-custom-attributes).
You can pass them in the `attributes` object of `Auth.signUp` function parameters:

```javascript
Auth.signUp({
  username: 'jdoe',
  password: 'mysecurerandompassword#123',
  attributes: {
    email: 'me@domain.com',
    phone_number: '+12128601234', // E.164 number convention
    given_name: 'Jane',
    family_name: 'Doe',
    nickname: 'Jane',
    'custom:attribute_name': 'attribute_value'
  }
});
```

### Retrieve user attributes

```ts
const user = await Auth.currentAuthenticatedUser();

const { attributes } = user;
```

### Update user attributes

```ts
import { Auth } from 'aws-amplify';

async function updateUserAttributes () {
  try {
    const user = await Auth.currentAuthenticatedUser();
    const result = await Auth.updateUserAttributes(user, {
      email: 'me@anotherdomain.com',
      family_name: 'Lastname'
    });
    console.log(result); // SUCCESS
  } catch(err) {
    console.log(err);
  }
};
```

<Callout>
Note: If you change an attribute that requires confirmation (i.e. email or phone number), you will receive a confirmation code to that attribute.
</Callout> 

`Auth.updateUserAttributes()` function dispatches hub event to help identify attributes that require
verification. You can listen to `updateUserAttributes` event on `auth` channel:


```javascript
import { Hub } from 'aws-amplify';

Hub.listen('auth', ({payload}) => {
  if (payload.event === 'updateUserAttributes') {
    const resultObject = payload.data;
  }
});
```

You can learn more about how to listen to Hub events [here](https://docs.amplify.aws/lib/utilities/hub/q/platform/js/).

Example of the dispatched `resultObject`:

```javascript
{
  'email': {
    isUpdated: false // indicates that attribute requires verification
    codeDeliveryDetails: {
      AttributeName: 'email',
      DeliveryMedium: 'EMAIL',
      Destination: 'm***@a...'
    }
  },
  'family_name': {
    isUpdated: true
  }
}
```
If a user sends several attributes for update and one or more of them is `read_only` or doesn't exist, the Amplify JavaScript library will throw
an error and dispatch `updateUserAttributes_failure` Hub event. None of the attributes in the request will be updated.

### Confirm attribute

If you change the email address, you will receive a confirmation code to the new email address. Below is an example of how to confirm the new 
email address in your app:

```javascript
const result = await Auth.verifyCurrentUserAttributeSubmit('email', '<verification_code>');
```

### Delete user attributes

If you need to delete one or more user attributes, you can call `Auth.deleteUserAttributes` function from the Amplify JavaScript library:

```ts
import { Auth } from 'aws-amplify';

async function deleteUserAttributes() {
  try {
    const user = await Auth.currentAuthenticatedUser();
    const result = await Auth.deleteUserAttributes(user, ['family_name']);
    console.log(result); // SUCCESS
  } catch(err) {
    console.log(err);
  }
};
```

## Updating and verifying a Cognito user email address

Updating an email address using `Auth.updateUserAttributes` will require a verification of the new email address. The user will be emailed a verification code to the updated email address and your application will need to receive the verification code and send it to `Auth.verifyCurrentUserAttributeSubmit` before the email address will be updated in Cognito.

The React application below implements this flow of updating the email address for the current user when the "Update Email" button is clicked, then provides a form to capture the verification code sent to the user.

<BlockSwitcher>
<Block name="TypeScript">

```ts
// App.js
import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import { Auth } from 'aws-amplify';
import { useState } from 'react';

async function updateUserEmail() {
  try {
    const user = await Auth.currentAuthenticatedUser();
    await Auth.updateUserAttributes(user, {
      email: 'updatedEmail@mydomain.com'
    });

    console.log('a verification code is sent');
  } catch(err) {
    console.log('failed with error', err);
  }
}

async function verifyEmailValidationCode(code: string) {
  try {
    await Auth.verifyCurrentUserAttributeSubmit('email', code);
    console.log('email verified');
  } catch(err) {
    console.log('failed with error', err);
  }
}

function ValidationCodeForm() {
  const [validationCode, setValidationCode] = useState<string | null>(null);
  return (
    <div>
      <label>
        Verification Code (sent to the new email):
        <input
          onChange={(e) => {
            setValidationCode(e.target.value);
          }}
          type="text"
          name="vc"
        />
      </label>
      <button onClick={() => validationCode && verifyEmailValidationCode(validationCode)}>
        Send Code
      </button>
    </div>
  );
}

export default function App() {
  const [showValidationCodeUI, setShowValidationCodeUI] = useState(false);

  return (
    <Authenticator>
      {({ signOut, user }) => (
        <div className="App">
          <div>
            <pre>{JSON.stringify(user?.attributes, null, 2)}</pre>
          </div>
          {showValidationCodeUI === false && (
            <button
              onClick={async () => { 
                await updateUserEmail();
                setShowValidationCodeUI(true);
              }}
            >
              Update Email
            </button>
          )}
          {showValidationCodeUI === true && <ValidationCodeForm />}
          <button onClick={signOut}>Sign out</button>
        </div>
      )}
    </Authenticator>
  );
}
```
</Block>
<Block name="JavaScript">

```javascript
// App.js
import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import { Auth } from 'aws-amplify';
import { useState } from 'react';

async function updateUserEmail() {
  try {
    const user = await Auth.currentAuthenticatedUser();
    await Auth.updateUserAttributes(user, {
      email: 'updatedEmail@mydomain.com'
    });

    console.log('a verification code is sent');
  } catch(err) {
    console.log('failed with error', err);
  }
}

async function verifyEmailValidationCode(code) {
  try {
    await Auth.verifyCurrentUserAttributeSubmit('email', code);
    console.log('email verified');
  } catch(err) {
    console.log('failed with error', err);
  }
}

function ValidationCodeForm() {
  const [validationCode, setValidationCode] = useState(null);
  return (
    <div>
      <label>
        Verification Code (sent to the new email):
        <input
          onChange={(e) => {
            setValidationCode(e.target.value);
          }}
          type="text"
          name="vc"
        />
      </label>
      <button onClick={() => verifyEmailValidationCode(validationCode)}>
        Send Code
      </button>
    </div>
  );
}

export default function App() {
  const [showValidationCodeUI, setShowValidationCodeUI] = useState(false);

  return (
    <Authenticator>
      {({ signOut, user }) => (
        <div className="App">
          <div>
            <pre>{JSON.stringify(user.attributes, null, 2)}</pre>
          </div>
          {showValidationCodeUI === false && (
            <button
              onClick={async () => {
                await updateUserEmail();
                setShowValidationCodeUI(true);
              }}
            >
              Update Email
            </button>
          )}
          {showValidationCodeUI === true && <ValidationCodeForm />}
          <button onClick={signOut}>Sign out</button>
        </div>
      )}
    </Authenticator>
  );
}
```
</Block>
</BlockSwitcher>

## Managing security tokens

> When using Authentication with AWS Amplify, you don't need to refresh Amazon Cognito tokens manually. The tokens are automatically refreshed by the library when necessary.

Security Tokens like _IdToken_ or _AccessToken_ are stored in _localStorage_ for the browser and in _AsyncStorage_ for React Native. If you want to store those tokens in a more secure place or you are using Amplify in server side, then you can provide your own `storage` object to store those tokens.

For example:

```ts
class MyStorage {
  // the promise returned from sync function
  static syncPromise = null;
  // set item with the key
  static setItem(key: string, value: string): string;
  // get item with the key
  static getItem(key: string): string;
  // remove item with the key
  static removeItem(key: string): void;
  // clear out the storage
  static clear(): void;
  // If the storage operations are async(i.e AsyncStorage)
  // Then you need to sync those items into the memory in this method
  static sync(): Promise<void> {
    if (!MyStorage.syncPromise) {
      MyStorage.syncPromise = new Promise((res, rej) => {});
    }
    return MyStorage.syncPromise;
  }
}

// tell Auth to use your storage object
Auth.configure({
  storage: MyStorage
});
```

Here is the example of how to use AsyncStorage as your storage object which will show you how to sync items from AsyncStorage into Memory:

```javascript
import { AsyncStorage } from 'react-native';

const MYSTORAGE_KEY_PREFIX = '@MyStorage:';
let dataMemory = {};

/** @class */
class MyStorage {
  static syncPromise = null;
  /**
   * This is used to set a specific item in storage
   */
  static setItem(key, value) {
    AsyncStorage.setItem(MYSTORAGE_KEY_PREFIX + key, value);
    dataMemory[key] = value;
    return dataMemory[key];
  }

  /**
   * This is used to get a specific key from storage
   */
  static getItem(key) {
    return Object.prototype.hasOwnProperty.call(dataMemory, key)
      ? dataMemory[key]
      : undefined;
  }

  /**
   * This is used to remove an item from storage
   */
  static removeItem(key) {
    AsyncStorage.removeItem(MYSTORAGE_KEY_PREFIX + key);
    return delete dataMemory[key];
  }

  /**
   * This is used to clear the storage
   */
  static clear() {
    dataMemory = {};
    return dataMemory;
  }

  /**
   * Will sync the MyStorage data from AsyncStorage to storageWindow MyStorage
   */
  static sync() {
    if (!MyStorage.syncPromise) {
      MyStorage.syncPromise = new Promise((res, rej) => {
        AsyncStorage.getAllKeys((errKeys, keys) => {
          if (errKeys) rej(errKeys);
          const memoryKeys = keys.filter((key) =>
            key.startsWith(MYSTORAGE_KEY_PREFIX)
          );
          AsyncStorage.multiGet(memoryKeys, (err, stores) => {
            if (err) rej(err);
            stores.map((result, index, store) => {
              const key = store[index][0];
              const value = store[index][1];
              const memoryKey = key.replace(MYSTORAGE_KEY_PREFIX, '');
              dataMemory[memoryKey] = value;
            });
            res();
          });
        });
      });
    }
    return MyStorage.syncPromise;
  }
}

Auth.configure({
  storage: MyStorage
});
```

To learn more about tokens, please visit [Amazon Cognito Developer Documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html).
