/*
* Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Threading;
using Amazon.CognitoIdentityProvider;
using Amazon.CognitoIdentityProvider.Model;
using Amazon.Extensions.CognitoAuthentication.Util;
namespace Amazon.Extensions.CognitoAuthentication
{
public partial class CognitoUser
{
///
/// The client secret for the associated client, if one is set
///
private string ClientSecret { get; set; }
///
/// The secret hash for the associated user, if a client secret is set
///
internal string SecretHash { get; set; }
///
/// The session for the associated user.
///
public CognitoUserSession SessionTokens { get; set; }
///
/// The CognitoDevice associated with this user, if exists
///
public CognitoDevice Device { get; set; }
///
/// The userID of the associated user. UserID can only be configured through the
/// constructor, and once set it cannot be changed.
///
public string UserID { get; private set; }
///
/// The username of the associated user. Username can only be configured through the
/// constructor, and once set it cannot be changed.
///
public string Username { get; private set; }
///
/// The user pool of the associated user. UserPool can only be configured through
/// the constructor, and once set it cannot be changed.
///
public CognitoUserPool UserPool { get; private set; }
///
/// The clientID of the associated user. ClientID can only be configured through
/// the constructor, and once set it cannot be changed.
///
public string ClientID { get; private set; }
///
/// The status of the associated user.
///
public string Status { get; private set; }
///
/// The IAmazonCognitoIdentityProvider client of the associated user. Provider can
/// only be configured through the constructor, and once set it cannot be changed.
///
internal IAmazonCognitoIdentityProvider Provider { get; private set; }
///
/// The attributes of the associated user.
///
public Dictionary Attributes { get; private set; } = new Dictionary();
///
/// The settings of the associated user.
///
public Dictionary Settings { get; set; }
///
/// Private property to get and set the pool name of the user pool the user
/// is associated with.
///
private string PoolName { get; set; }
///
/// Creates an instance of CognitoUser
///
/// UserID of the specified user
/// ClientID associated with the user pool
/// CognitoUserPool this user is associated with
/// IAmazonCognitoIdentityProvider for the specified user pool
/// Client secret for the specified client, if exists
/// Username for user, if different from userID
public CognitoUser(string userID, string clientID,
CognitoUserPool pool,
IAmazonCognitoIdentityProvider provider,
string clientSecret = null,
string status = null,
string username = null,
Dictionary attributes = null)
{
if(pool.PoolID.Contains("_"))
{
this.PoolName = pool.PoolID.Split('_')[1];
}
else
{
throw new ArgumentException("Pool's poolID malformed, should be of the form _.");
}
this.ClientSecret = clientSecret;
if (!string.IsNullOrEmpty(clientSecret))
{
this.SecretHash = CognitoAuthHelper.GetUserPoolSecretHash(userID, clientID, clientSecret);
}
this.UserID = userID;
this.Username = userID;
if (!string.IsNullOrEmpty(username))
{
this.Username = username;
}
else
{
this.Username = userID;
}
this.Status = status;
this.UserPool = pool;
this.ClientID = clientID;
this.SessionTokens = null;
if (attributes != null)
{
this.Attributes = attributes;
}
this.Provider = provider;
if (this.Provider is AmazonCognitoIdentityProviderClient eventProvider)
{
eventProvider.BeforeRequestEvent += CognitoAuthHelper.ServiceClientBeforeRequestEvent;
}
}
///
/// Confirms the sign up of the associated user using the provided confirmation code
/// using an asynchronous call
///
/// Confirmation code sent to user via email or SMS
/// Boolean specifying whether forced alias creation is desired
public virtual Task ConfirmSignUpAsync(string confirmationCode, bool forcedAliasCreation)
{
return ConfirmSignUpAsync(confirmationCode, forcedAliasCreation, default);
}
///
/// Confirms the sign up of the associated user using the provided confirmation code
/// using an asynchronous call
///
/// Confirmation code sent to user via email or SMS
/// Boolean specifying whether forced alias creation is desired
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task ConfirmSignUpAsync(string confirmationCode, bool forcedAliasCreation, CancellationToken cancellationToken)
{
ConfirmSignUpRequest confirmRequest = CreateConfirmSignUpRequest(confirmationCode, forcedAliasCreation);
return Provider.ConfirmSignUpAsync(confirmRequest, cancellationToken);
}
///
/// Request to resend registration confirmation code for a user using an asynchronous call
///
/// Returns the delivery details for the confirmation code request
public virtual Task ResendConfirmationCodeAsync()
{
return ResendConfirmationCodeAsync(default);
}
///
/// Request to resend registration confirmation code for a user using an asynchronous call
///
/// Returns the delivery details for the confirmation code request
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task ResendConfirmationCodeAsync(CancellationToken cancellationToken)
{
ResendConfirmationCodeRequest resendRequest = CreateResendConfirmationCodeRequest();
return Provider.ResendConfirmationCodeAsync(resendRequest, cancellationToken);
}
///
/// Allows the user to reset their password using an asynchronous call. Should be used in
/// conjunction with the ConfirmPasswordAsync method
///
public virtual Task ForgotPasswordAsync()
{
return ForgotPasswordAsync(default);
}
///
/// Allows the user to reset their password using an asynchronous call. Should be used in
/// conjunction with the ConfirmPasswordAsync method
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task ForgotPasswordAsync(CancellationToken cancellationToken)
{
ForgotPasswordRequest forgotPassRequest = CreateForgotPasswordRequest();
return Provider.ForgotPasswordAsync(forgotPassRequest, cancellationToken);
}
///
/// Confirms the user's new password using the confirmation code sent to them using
/// an asynchronous call
///
/// The confirmation code sent to the user
/// The new desired password for the user
public virtual Task ConfirmForgotPasswordAsync(string confirmationCode, string newPassword)
{
return ConfirmForgotPasswordAsync(confirmationCode, newPassword, default);
}
///
/// Confirms the user's new password using the confirmation code sent to them using
/// an asynchronous call
///
/// The confirmation code sent to the user
/// The new desired password for the user
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task ConfirmForgotPasswordAsync(string confirmationCode, string newPassword, CancellationToken cancellationToken)
{
ConfirmForgotPasswordRequest confirmResetPassRequest =
CreateConfirmPasswordRequest(confirmationCode, newPassword);
return Provider.ConfirmForgotPasswordAsync(confirmResetPassRequest, cancellationToken);
}
///
/// Allows an authenticated user to change their password using an
/// asynchronous call
///
/// The user's old password
/// The desired new password
public virtual Task ChangePasswordAsync(string oldPass, string newPass)
{
return ChangePasswordAsync(oldPass, newPass, default);
}
///
/// Allows an authenticated user to change their password using an
/// asynchronous call
///
/// The user's old password
/// The desired new password
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task ChangePasswordAsync(string oldPass, string newPass, CancellationToken cancellationToken)
{
ChangePasswordRequest changePassRequest = CreateChangePasswordRequest(oldPass, newPass);
return Provider.ChangePasswordAsync(changePassRequest, cancellationToken);
}
///
/// Gets the details for the current user using an asynchronous call
///
/// Returns a tuple containing the user attributes and settings, in that order
public virtual Task GetUserDetailsAsync()
{
return GetUserDetailsAsync(default);
}
///
/// Gets the details for the current user using an asynchronous call
///
/// Returns a tuple containing the user attributes and settings, in that order
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task GetUserDetailsAsync(CancellationToken cancellationToken)
{
EnsureUserAuthenticated();
GetUserRequest getUserRequest = new GetUserRequest()
{
AccessToken = SessionTokens.AccessToken
};
return Provider.GetUserAsync(getUserRequest, cancellationToken);
}
///
/// Gets the attribute verification code for the specified attribute using
/// an asynchronous call
///
/// Name of the attribute the verification code is being sent to.
/// Should be either email or phone_number.
/// Returns the delivery details for the attribute verification code request
public virtual Task GetAttributeVerificationCodeAsync(string medium)
{
return GetAttributeVerificationCodeAsync(medium, default);
}
///
/// Gets the attribute verification code for the specified attribute using
/// an asynchronous call
///
/// Name of the attribute the verification code is being sent to.
/// Should be either email or phone_number.
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
/// Returns the delivery details for the attribute verification code request
public virtual Task GetAttributeVerificationCodeAsync(string medium, CancellationToken cancellationToken)
{
GetUserAttributeVerificationCodeRequest getAttributeCodeRequest =
CreateGetUserAttributeVerificationCodeRequest(medium);
return Provider.GetUserAttributeVerificationCodeAsync(getAttributeCodeRequest, cancellationToken);
}
///
/// Sign-out from all devices associated with this user using an asynchronous call
///
public virtual Task GlobalSignOutAsync()
{
return GlobalSignOutAsync(default);
}
///
/// Sign-out from all devices associated with this user using an asynchronous call
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task GlobalSignOutAsync(CancellationToken cancellationToken)
{
EnsureUserAuthenticated();
GlobalSignOutRequest globalSignOutRequest = new GlobalSignOutRequest()
{
AccessToken = SessionTokens.AccessToken
};
SessionTokens = null;
return Provider.GlobalSignOutAsync(globalSignOutRequest, cancellationToken);
}
///
/// Deletes the current user using an asynchronous call
///
public virtual Task DeleteUserAsync()
{
return DeleteUserAsync(default);
}
///
/// Deletes the current user using an asynchronous call
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task DeleteUserAsync(CancellationToken cancellationToken)
{
EnsureUserAuthenticated();
DeleteUserRequest deleteUserRequest = new DeleteUserRequest()
{
AccessToken = SessionTokens.AccessToken
};
return Provider.DeleteUserAsync(deleteUserRequest, cancellationToken);
}
///
/// Verifies the given attribute using an asynchronous call
///
/// Attribute to be verified. Should either be email or phone_number
/// The verification code for the attribute being verified
public virtual Task VerifyAttributeAsync(string attributeName, string verificationCode)
{
return VerifyAttributeAsync(attributeName, verificationCode, default);
}
///
/// Verifies the given attribute using an asynchronous call
///
/// Attribute to be verified. Should either be email or phone_number
/// The verification code for the attribute being verified
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual Task VerifyAttributeAsync(string attributeName, string verificationCode, CancellationToken cancellationToken)
{
VerifyUserAttributeRequest verifyUserAttributeRequest =
CreateVerifyUserAttributeRequest(attributeName, verificationCode);
return Provider.VerifyUserAttributeAsync(verifyUserAttributeRequest, cancellationToken);
}
///
/// Updates the user's attributes defined in the attributes parameter (one at a time)
/// using an asynchronous call
///
/// The attributes to be updated
public virtual async Task UpdateAttributesAsync(IDictionary attributes)
{
await UpdateAttributesAsync(attributes, default);
}
///
/// Updates the user's attributes defined in the attributes parameter (one at a time)
/// using an asynchronous call
///
/// The attributes to be updated
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual async Task UpdateAttributesAsync(IDictionary attributes, CancellationToken cancellationToken)
{
UpdateUserAttributesRequest updateUserAttributesRequest =
CreateUpdateUserAttributesRequest(attributes);
await Provider.UpdateUserAttributesAsync(updateUserAttributesRequest, cancellationToken).ConfigureAwait(false);
//Update the local Attributes property
foreach (KeyValuePair entry in attributes)
{
Attributes[entry.Key] = entry.Value;
}
}
///
/// Deletes the attributes specified in the attributeNamesToDelete list using
/// an asynchronous call
///
/// List of attributes to delete
public virtual async Task DeleteAttributesAsync(IList attributeNamesToDelete)
{
await DeleteAttributesAsync(attributeNamesToDelete, default);
}
///
/// Deletes the attributes specified in the attributeNamesToDelete list using
/// an asynchronous call
///
/// List of attributes to delete
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual async Task DeleteAttributesAsync(IList attributeNamesToDelete, CancellationToken cancellationToken)
{
DeleteUserAttributesRequest deleteUserAttributesRequest =
CreateDeleteUserAttributesRequest(attributeNamesToDelete);
await Provider.DeleteUserAttributesAsync(deleteUserAttributesRequest, cancellationToken).ConfigureAwait(false);
//Update the local Attributes property
foreach (string attribute in attributeNamesToDelete)
{
if (Attributes.ContainsKey(attribute))
{
Attributes.Remove(attribute);
}
}
}
///
/// Sets the MFAOptions to be the settings desibed in the userSettings dictionary
/// using an asynchronous call
///
/// Dictionary for the user MFA settings of the form [attribute, delivery medium]
public virtual async Task SetUserSettingsAsync(IDictionary userSettings)
{
await SetUserSettingsAsync(userSettings, default);
}
///
/// Sets the MFAOptions to be the settings desibed in the userSettings dictionary
/// using an asynchronous call
///
/// Dictionary for the user MFA settings of the form [attribute, delivery medium]
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
public virtual async Task SetUserSettingsAsync(IDictionary userSettings, CancellationToken cancellationToken)
{
SetUserSettingsRequest setUserSettingsRequest = CreateSetUserSettingsRequest(userSettings);
await Provider.SetUserSettingsAsync(setUserSettingsRequest, cancellationToken).ConfigureAwait(false);
//Update the local Settings property
foreach (KeyValuePair entry in userSettings)
{
Settings[entry.Key] = entry.Value;
}
}
///
/// Lists the CognitoDevices associated with this user using an asynchronous call
///
/// Maxmimum number of devices to be returned in this call
/// Token to continue earlier search
/// Returns a list of CognitoDevices associated with this user
[Obsolete("This method is deprecated since it only lists the first page of devices. The method ListDevicesV2Async should be used instead which allows listing additional pages of devices.")]
public virtual async Task> ListDevicesAsync(int limit, string paginationToken)
{
return await ListDevicesAsync(limit, paginationToken, default);
}
///
/// Lists the CognitoDevices associated with this user using an asynchronous call
///
/// Maxmimum number of devices to be returned in this call
/// Token to continue earlier search
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
/// Returns a list of CognitoDevices associated with this user
[Obsolete("This method is deprecated since it only lists the first page of devices. The method ListDevicesV2Async should be used instead which allows listing additional pages of devices.")]
public virtual async Task> ListDevicesAsync(int limit, string paginationToken, CancellationToken cancellationToken)
{
ListDevicesRequest listDevicesRequest = CreateListDevicesRequest(limit, paginationToken);
ListDevicesResponse listDevicesReponse = await Provider.ListDevicesAsync(listDevicesRequest, cancellationToken).ConfigureAwait(false);
List devicesList = new List();
foreach (DeviceType device in listDevicesReponse.Devices)
{
devicesList.Add(new CognitoDevice(device, this));
}
return devicesList;
}
///
/// Executes the ListDevicesAsync service call to access device types associated with this user using an asynchronous call.
/// The response returned contains DeviceType objects which could be used to construct list of CognitoDevice type objects and
/// a PaginationToken which could be used to access remaining device types (if any).
///
/// Maxmimum number of devices to be returned in this call
/// Token to continue earlier search
/// Returns underlying ListDevicesResponse that contains list of DeviceType objects along with PaginationToken.
public virtual async Task ListDevicesV2Async(int limit, string paginationToken)
{
return await ListDevicesV2Async(limit, paginationToken, default);
}
///
/// Executes the ListDevicesAsync service call to access device types associated with this user using an asynchronous call.
/// The response returned contains DeviceType objects which could be used to construct list of CognitoDevice type objects and
/// a PaginationToken which could be used to access remaining device types (if any).
///
/// Maxmimum number of devices to be returned in this call
/// Token to continue earlier search
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
/// Returns underlying ListDevicesResponse that contains list of DeviceType objects along with PaginationToken.
public virtual async Task ListDevicesV2Async(int limit, string paginationToken, CancellationToken cancellationToken)
{
ListDevicesRequest listDevicesRequest = CreateListDevicesRequest(limit, paginationToken);
return await Provider.ListDevicesAsync(listDevicesRequest, cancellationToken).ConfigureAwait(false);
}
///
/// Request code for authenticator app.
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
/// with secret code.
public virtual async Task AssociateSoftwareTokenAsync(CancellationToken cancellationToken)
{
EnsureUserAuthenticated();
AssociateSoftwareTokenRequest request = new AssociateSoftwareTokenRequest
{
AccessToken = SessionTokens.AccessToken
};
return await Provider.AssociateSoftwareTokenAsync(request, cancellationToken).ConfigureAwait(false);
}
///
/// Verify code from authenticator app.
///
/// Code from authenticator app.
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
/// which contains token verification status.
public virtual async Task VerifySoftwareTokenAsync(string code, CancellationToken cancellationToken) {
if (string.IsNullOrEmpty(code))
throw new ArgumentNullException(nameof(code));
EnsureUserAuthenticated();
VerifySoftwareTokenRequest request = new VerifySoftwareTokenRequest
{
AccessToken = SessionTokens.AccessToken,
FriendlyDeviceName = Device?.GetDeviceName(),
UserCode = code
};
return await Provider.VerifySoftwareTokenAsync(request, cancellationToken).ConfigureAwait(false);
}
///
/// Update settings for software MFA settings.
///
/// Software MFA preferred at sign in.
/// Enable or disable software MFA.
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation
///
public async Task UpdateSoftwareMfaSettingsAsync(bool isPreferred, bool isEnabled, CancellationToken cancellationToken)
{
EnsureUserAuthenticated();
SetUserMFAPreferenceRequest request = new SetUserMFAPreferenceRequest {
AccessToken = SessionTokens.AccessToken,
SoftwareTokenMfaSettings = new SoftwareTokenMfaSettingsType() {
PreferredMfa = isPreferred,
Enabled = isEnabled
}
};
await Provider.SetUserMFAPreferenceAsync(request, cancellationToken).ConfigureAwait(false);
}
private ConfirmSignUpRequest CreateConfirmSignUpRequest(string confirmationCode, bool forcedAliasCreation)
{
ConfirmSignUpRequest confirmRequest = new ConfirmSignUpRequest()
{
ClientId = ClientID,
Username = Username,
ForceAliasCreation = forcedAliasCreation,
ConfirmationCode = confirmationCode
};
if (!string.IsNullOrEmpty(SecretHash))
{
confirmRequest.SecretHash = SecretHash;
}
return confirmRequest;
}
private ResendConfirmationCodeRequest CreateResendConfirmationCodeRequest()
{
ResendConfirmationCodeRequest resendRequest = new ResendConfirmationCodeRequest()
{
Username = Username,
ClientId = ClientID
};
if (!string.IsNullOrEmpty(SecretHash))
{
resendRequest.SecretHash = SecretHash;
}
return resendRequest;
}
private ForgotPasswordRequest CreateForgotPasswordRequest()
{
ForgotPasswordRequest forgotPassRequest = new ForgotPasswordRequest()
{
ClientId = ClientID,
Username = Username
};
if (!string.IsNullOrEmpty(SecretHash))
{
forgotPassRequest.SecretHash = SecretHash;
}
return forgotPassRequest;
}
private ConfirmForgotPasswordRequest CreateConfirmPasswordRequest(string confirmationCode, string newPassword)
{
ConfirmForgotPasswordRequest confirmResetPassRequest = new ConfirmForgotPasswordRequest()
{
Username = Username,
ClientId = ClientID,
Password = newPassword,
ConfirmationCode = confirmationCode
};
if (!string.IsNullOrEmpty(SecretHash))
{
confirmResetPassRequest.SecretHash = SecretHash;
}
return confirmResetPassRequest;
}
private ChangePasswordRequest CreateChangePasswordRequest(string oldPass, string newPass)
{
EnsureUserAuthenticated();
ChangePasswordRequest changePassRequest = new ChangePasswordRequest()
{
PreviousPassword = oldPass,
ProposedPassword = newPass,
AccessToken = SessionTokens.AccessToken
};
return changePassRequest;
}
private GetUserAttributeVerificationCodeRequest CreateGetUserAttributeVerificationCodeRequest(string attributeName)
{
EnsureUserAuthenticated();
GetUserAttributeVerificationCodeRequest getAttributeCodeRequest = new GetUserAttributeVerificationCodeRequest()
{
AccessToken = SessionTokens.AccessToken,
AttributeName = attributeName
};
return getAttributeCodeRequest;
}
///
/// Internal function that creates a CognitoUserSession based on the authentication result
///
/// An authentication result during authentication flow
/// Optional variable to override the refreshToken manually
/// Returns a CognitoUserSession based on the authentication result
private CognitoUserSession GetCognitoUserSession(AuthenticationResultType authResult, string refreshTokenOverride = null)
{
string idToken = authResult.IdToken;
string accessToken = authResult.AccessToken;
string refreshToken;
DateTime currentTime = DateTime.UtcNow;
if (!string.IsNullOrEmpty(refreshTokenOverride))
{
refreshToken = refreshTokenOverride;
}
else
{
refreshToken = authResult.RefreshToken;
}
return new CognitoUserSession(idToken, accessToken, refreshToken, currentTime, currentTime.AddSeconds(authResult.ExpiresIn));
}
///
/// Sign-out by making the invalidating user session
///
public void SignOut()
{
this.SessionTokens = null;
}
private VerifyUserAttributeRequest CreateVerifyUserAttributeRequest(string attributeName, string verificationCode)
{
EnsureUserAuthenticated();
VerifyUserAttributeRequest verifyUserAttributeRequest = new VerifyUserAttributeRequest()
{
AttributeName = attributeName,
AccessToken = SessionTokens.AccessToken,
Code = verificationCode
};
return verifyUserAttributeRequest;
}
private UpdateUserAttributesRequest CreateUpdateUserAttributesRequest(IDictionary attributes)
{
EnsureUserAuthenticated();
UpdateUserAttributesRequest updateUserAttributesRequest = new UpdateUserAttributesRequest()
{
AccessToken = SessionTokens.AccessToken,
UserAttributes = CognitoAuthHelper.CreateAttributeList(attributes)
};
return updateUserAttributesRequest;
}
private DeleteUserAttributesRequest CreateDeleteUserAttributesRequest(IList attributeNamesToDelete)
{
if (attributeNamesToDelete == null || attributeNamesToDelete.Count < 1)
{
throw new ArgumentNullException("attributeNamesToDelete cannot be null or empty.", "attributeNamesToDelete");
}
EnsureUserAuthenticated();
DeleteUserAttributesRequest deleteUserAttributesRequest = new DeleteUserAttributesRequest()
{
AccessToken = SessionTokens.AccessToken,
UserAttributeNames = new List(attributeNamesToDelete)
};
return deleteUserAttributesRequest;
}
private SetUserSettingsRequest CreateSetUserSettingsRequest(IDictionary userSettings)
{
if (userSettings == null || userSettings.Count < 1)
{
throw new ArgumentNullException("userSettings cannot be null or empty.", "userSettings");
}
EnsureUserAuthenticated();
List settingsList = new List();
foreach (KeyValuePair setting in userSettings)
{
settingsList.Add(new MFAOptionType() { AttributeName = setting.Key, DeliveryMedium = setting.Value });
}
SetUserSettingsRequest setUserSettingsRequest = new SetUserSettingsRequest()
{
AccessToken = SessionTokens.AccessToken,
MFAOptions = settingsList
};
return setUserSettingsRequest;
}
private ListDevicesRequest CreateListDevicesRequest(int limit, string paginationToken)
{
EnsureUserAuthenticated();
ListDevicesRequest listDevicesRequest = new ListDevicesRequest()
{
AccessToken = SessionTokens.AccessToken,
Limit = limit,
PaginationToken = paginationToken
};
return listDevicesRequest;
}
private void EnsureUserAuthenticated()
{
if (SessionTokens == null || !SessionTokens.IsValid())
{
throw new NotAuthorizedException("User is not authenticated.");
}
}
}
}