public IEnumerator Revoke()
        {
            LastError = null;

            if (!Authenticated)
            {
                LastError = new RDataAuthenticationException("You need to be authenticated to Revoke the authentication");
                yield break;
            }
            // If refresh token is not expired, revoke it by sending the revoke request
            if (!RefreshTokenExpired)
            {
                var revokeRequest = new RevokeRequest(RefreshToken);
                yield return(StartCoroutine(_httpClient.Send <RevokeRequest, RevokeRequest.RevokeResponse>(revokeRequest)));

                // If we have an error and this error is not an UnauthorizedException or ForbiddenException, we want to throw it
                // Otherwise, consume the error and revoke the token on the client (the token is already expired/revoked on the server)
                if (revokeRequest.HasError &&
                    !(revokeRequest.Error is Http.Exceptions.UnauthorizedException) &&
                    !(revokeRequest.Error is Http.Exceptions.ForbiddenException))
                {
                    LastError = new RDataAuthenticationException(revokeRequest.Error);
                    yield break;
                }

                if (!revokeRequest.HasResponse)
                {
                    LastError = new RDataAuthenticationException("Failed to Revoke(), http request failed but has no error");
                    yield break;
                }
            }

            ResetValues();
            SaveToPlayerPrefs();
        }
        public IEnumerator Authenticate(string username, string password)
        {
            LastError = null;

            if (Authenticated)
            {
                LastError = new RDataAuthenticationException("Failed to Authenticate - already authenticated. Call Revoke() to Revoke the previous authentication");
                yield break;
            }
            // Send authentication request
            var localAuthRequest = new AuthenticateLocalRequest(username, password);

            yield return(StartCoroutine(_httpClient.Send <AuthenticateLocalRequest, AuthenticateLocalRequest.AuthenticateLocalResponse>(localAuthRequest)));

            if (localAuthRequest.HasError && localAuthRequest.Error is RData.Http.Exceptions.UnauthorizedException)
            {
                LastError = new InvalidCredentialsException(localAuthRequest.Error);
                yield break;
            }

            if (localAuthRequest.HasError)
            {
                LastError = new RDataAuthenticationException(localAuthRequest.Error);
                yield break;
            }

            if (!localAuthRequest.HasResponse)
            {
                LastError = new RDataAuthenticationException("Failed to authenticate, http request failed but has no error");
                yield break;
            }

            // Process the authentication response - build new AuthenticationInfo object
            _authenticationInfo = new AuthenticationInfo();

            _authenticationInfo.accessToken           = localAuthRequest.Response.accessToken;
            _authenticationInfo.refreshToken          = localAuthRequest.Response.refreshToken;
            _authenticationInfo.user                  = localAuthRequest.Response.user;
            _authenticationInfo.refreshTokenExpiresAt = localAuthRequest.Response.refreshTokenExpiresAt;
            _authenticationInfo.accessTokenExpiresAt  = localAuthRequest.Response.accessTokenExpiresAt;

            // Save into player prefs
            SaveToPlayerPrefs();
        }
        public IEnumerator EnsureValidAccessToken()
        {
            if (!Authenticated)
            {
                LastError = new RDataAuthenticationException("Not authenticated");
                yield break;
            }

            if (RefreshTokenExpired)
            {
                LastError = new RDataAuthenticationException("Refresh token expired");
                yield break;
            }

            if (AccessTokenExpired)
            {
                yield return(Refresh());
            }

            // AccessToken should now contain valid access token
        }
        public IEnumerator Register(string username, string email, string password)
        {
            LastError = null;

            // Send registration request
            var localRegistrationRequest = new RegisterLocalRequest(username, email, password);

            yield return(StartCoroutine(_httpClient.Send <RegisterLocalRequest, RegisterLocalRequest.RegisterLocalResponse>(localRegistrationRequest)));

            if (localRegistrationRequest.HasError)
            {
                if (localRegistrationRequest.Error is RData.Http.Exceptions.BadRequestException &&
                    localRegistrationRequest.Error.HasApiError &&
                    localRegistrationRequest.Error.ApiError.Name == "UsernameTakenError")
                {
                    LastError = new UsernameTakenException(localRegistrationRequest.Error);
                    yield break;
                }
                else if (localRegistrationRequest.Error is RData.Http.Exceptions.BadRequestException &&
                         localRegistrationRequest.Error.HasApiError &&
                         localRegistrationRequest.Error.ApiError.Name == "EmailTakenError")
                {
                    LastError = new EmailTakenException(localRegistrationRequest.Error);
                    yield break;
                }
                else
                {
                    // Unknown error
                    LastError = new RDataAuthenticationException(localRegistrationRequest.Error);
                    yield break;
                }
            }

            if (!localRegistrationRequest.HasResponse)
            {
                LastError = new RDataAuthenticationException("Failed to register, http request failed but has no error");
                yield break;
            }
        }
        public IEnumerator Refresh()
        {
            LastError = null;

            if (!Authenticated)
            {
                LastError = new RDataAuthenticationException("You need to be authenticated to Revoke the authentication");
                yield break;
            }
            if (RefreshTokenExpired)
            {
                LastError = new RDataAuthenticationException("Failed to refresh the access token: refresh token expired.");
                yield break;
            }

            var refreshRequest = new RefreshRequest(RefreshToken);

            yield return(StartCoroutine(_httpClient.Send <RefreshRequest, RefreshRequest.RefreshResponse>(refreshRequest)));

            if (refreshRequest.HasError)
            {
                LastError = new RDataAuthenticationException(refreshRequest.Error);
                yield break;
            }

            if (!refreshRequest.HasResponse)
            {
                LastError = new RDataAuthenticationException("Failed to Refresh(), http request failed but has no error");
                yield break;
            }

            _authenticationInfo.accessToken          = refreshRequest.Response.accessToken;
            _authenticationInfo.accessTokenExpiresAt = refreshRequest.Response.accessTokenExpiresAt;
            _authenticationInfo.user = refreshRequest.Response.user; // Role or other user parameters might have updated
            SaveToPlayerPrefs();
        }