## SignUp

Creates a new user in Cognito User Pools:

```swift
AWSMobileClient.default().signUp(username: "your_username",
                                        password: "Abc@123!",
                                        userAttributes: ["email":"john@doe.com", "phone_number": "+1973123456"]) { (signUpResult, error) in
    if let signUpResult = signUpResult {
        switch(signUpResult.signUpConfirmationState) {
        case .confirmed:
            print("User is signed up and confirmed.")
        case .unconfirmed:
            print("User is not confirmed and needs verification via \(signUpResult.codeDeliveryDetails!.deliveryMedium) sent at \(signUpResult.codeDeliveryDetails!.destination!)")
        case .unknown:
            print("Unexpected case")
        }
    } else if let error = error {
        if let error = error as? AWSMobileClientError {
            switch(error) {
            case .usernameExists(let message):
                print(message)
            default:
                break
            }
        }
        print("\(error.localizedDescription)")
    }
}
```

## User Attributes

You can provide custom user attributes in the `signUp()` method by passing them into the `userAttributes` argument as key-value pairs. For example:

```swift
AWSMobileClient.default().signUp(
    username: "your_username",
    password: "Abc@123!",
    userAttributes: [
        "nickname":"Johnny", 
        "badge_number": "ABC123XYZ"
        ]) { (signUpResult, error) in
            //Use results as before
        }
```

## Confirm SignUp

Confirms a new user after signing up (MFA):

```swift
AWSMobileClient.default().confirmSignUp(username: "your_username", confirmationCode: signUpCodeTextField.text!) { (signUpResult, error) in
    if let signUpResult = signUpResult {
        switch(signUpResult.signUpConfirmationState) {
        case .confirmed:
            print("User is signed up and confirmed.")
        case .unconfirmed:
            print("User is not confirmed and needs verification via \(signUpResult.codeDeliveryDetails!.deliveryMedium) sent at \(signUpResult.codeDeliveryDetails!.destination!)")
        case .unknown:
            print("Unexpected case")
        }
    } else if let error = error {
        print("\(error.localizedDescription)")
    }
}
```

## Re-send a Confirmation Code (MFA)

```swift
AWSMobileClient.default().resendSignUpCode(username: "your_username", completionHandler: { (result, error) in
    if let signUpResult = result {
        print("A verification code has been sent via \(signUpResult.codeDeliveryDetails!.deliveryMedium) at \(signUpResult.codeDeliveryDetails!.destination!)")
    } else if let error = error {
        print("\(error.localizedDescription)")
    }
})
```

## SignIn

Sign in with user credentials:

```swift
AWSMobileClient.default().signIn(username: "your_username", password: "Abc@123!") { (signInResult, error) in
    if let error = error  {
        print("\(error.localizedDescription)")
    } else if let signInResult = signInResult {
        switch (signInResult.signInState) {
        case .signedIn:
            print("User is signed in.")
        case .smsMFA:
            print("SMS message sent to \(signInResult.codeDetails!.destination!)")
        default:
            print("Sign In needs info which is not et supported.")
        }
    }
}
```

## Confirm SignIn (MFA)

```swift
AWSMobileClient.default().confirmSignIn(challengeResponse: "code_here") { (signInResult, error) in
    if let error = error  {
        print("\(error.localizedDescription)")
    } else if let signInResult = signInResult {
        switch (signInResult.signInState) {
        case .signedIn:
            print("User is signed in.")
        default:
            print("\(signInResult.signInState.rawValue)")
        }
    }
}
```

## Force a Password Reset

If a user is required to change their password on first login, a `newPasswordRequired` state will be returned when `signIn` is called and you will need to provide a new password. This can be done by using `confirmSignIn`:

```swift
AWSMobileClient.default().signIn(username: "abc123", password: "Abc123!@") { (signInResult, error) in
    if let signInResult = signInResult {
        switch(signInResult.signInState) {
        case .signedIn:
            print("User signed in successfully.")
        case .smsMFA:
            print("Code was sent via SMS to \(signInResult.codeDetails!.destination!)")
        case .newPasswordRequired:
            print("A change of password is needed. Please provide a new password.")
        default:
            print("Other signIn state: \(signInResult.signInState)")
        }
    } else if let error = error {
        print("Error occurred: \(error.localizedDescription)")
    }
}

AWSMobileClient.default().confirmSignIn(challengeResponse: "NEW_PASSWORD_HERE") { (signInResult, error) in
    if let signInResult = signInResult {
        switch(signInResult.signInState) {
        case .signedIn:
            print("User signed in successfully.")
        case .smsMFA:
            print("Code was sent via SMS to \(signInResult.codeDetails!.destination!)")
        default:
            print("Other signIn state: \(signInResult.signInState)")
        }
    } else if let error = error {
        print("Error occurred: \(error.localizedDescription)")
    }
}
```

## SignOut

```swift
AWSMobileClient.default().signOut()
```

## Global SignOut

Using global signout, you can signout a user from all active login sessions. By doing this, you are invalidating all tokens (id token, access token and refresh token) which means the user is signed out from **all** devices. 

> **Note** Although the tokens are revoked the temporary AWS credentials (Access and Secret Keys) will remain valid until they expire, which by default is 1 hour.

```swift
AWSMobileClient.default().signOut(options: SignOutOptions(signOutGlobally: true)) { (error) in
    print("Error: \(error.debugDescription)")
}
```

## Forgot Password

Forgot password is a 2 step process. 

1. Call a `forgotPassword()` method which sends a confirmation code via email or phone number. The details of how the code was sent are included in the response of `forgotPassword()`. 
2. Once the code is given call `confirmForgotPassword()` with the confirmation code.

```swift
AWSMobileClient.default().forgotPassword(username: "my_username") { (forgotPasswordResult, error) in
    if let forgotPasswordResult = forgotPasswordResult {
        switch(forgotPasswordResult.forgotPasswordState) {
        case .confirmationCodeSent:
            print("Confirmation code sent via \(forgotPasswordResult.codeDeliveryDetails!.deliveryMedium) to: \(forgotPasswordResult.codeDeliveryDetails!.destination!)")
        default:
            print("Error: Invalid case.")
        }
    } else if let error = error {
        print("Error occurred: \(error.localizedDescription)")
    }
}
```

```swift
AWSMobileClient.default().confirmForgotPassword(username: "my_username", newPassword: "MyNewPassword123!!", confirmationCode: "ConfirmationCode") { (forgotPasswordResult, error) in
    if let forgotPasswordResult = forgotPasswordResult {
        switch(forgotPasswordResult.forgotPasswordState) {
        case .done:
            print("Password changed successfully")
        default:
            print("Error: Could not change password.")
        }
    } else if let error = error {
        print("Error occurred: \(error.localizedDescription)")
    }
}
```

## Utility Properties

AWSMobileClient provides several property helpers that are automatically cached locally.

```swift
AWSMobileClient.default().username       //String
AWSMobileClient.default().isSignedIn     //Boolean
AWSMobileClient.default().identityId     //String
```

> Note: The property `username` is available only when using username-password based auth with Cognito User Pools.

## Managing Security Tokens

When using Authentication with AWSMobileClient, you do not need to refresh Amazon Cognito tokens manually. The tokens are automatically refreshed by the SDK when necessary.

### OIDC Tokens

```swift
AWSMobileClient.default().getTokens { (tokens, error) in
    if let error = error {
        print("Error getting token \(error.localizedDescription)")
    } else if let tokens = tokens {
        print(tokens.accessToken!.tokenString!)
    }
}
```

### AWS Credentials

```swift
AWSMobileClient.default().getAWSCredentials { (credentials, error) in
    if let error = error {
        print("\(error.localizedDescription)")
    } else if let credentials = credentials {
        print(credentials.accessKey)
    }
}
```