社交/企业身份验证不适用于Azure移动应用程序和Xamarin表单

时间:2019-06-12 14:21:47

标签: authentication xamarin.forms azure-mobile-services

我有一个带有Azure移动应用程序后端的Xamarin.forms应用程序,在该教程中我尝试使用Enterprise ans Social身份验证https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/

我已经能够同时设置两个服务器端并测试它们是否正常工作。可以在这些页面中进行测试

https://tasklistsync2.azurewebsites.net/.auth/login/google https://MyMobileApps.b2clogin.com/MyMobileApps.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_emailPolicy&client_id=9ec9bcd1-ee5f-4abb-9908-8d63a24b6165&nonce=defaultNonce&redirect_uri=https%3A%2F%2Ftasklistsync2.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback&scope=openid&response_type=id_token&prompt=login

我还在移动应用程序中包含了用于使用此身份验证流程的代码,该代码可以一直工作到我输入我的凭据时页面会重新加载,但是页面仍然为空,并且永远不会在登录成功后返回到我的移动应用程序。

这是我单击登录按钮时发生的情况。

async Task ExecuteLoginCommand()
        {
            if (IsBusy)
                return;
            IsBusy = true;

            try
            {
                var cloudService = ServiceLocator.Instance.Resolve<ICloudService>();

                //Login methods

                await cloudService.LoginAsync();           //Social/enterprise
                //await cloudService.LoginAsync(User);      //Custom login

                Application.Current.MainPage = new NavigationPage(new Pages.TaskList());
            }
            catch(Exception ex)
            {
                Debug.WriteLine($"[Login] Error = {ex.Message}");
            }
            finally
            {
                IsBusy = false;
            }
        }

转到我的AzureCloudService类中实现的cloudService.LoginAsync()。

public Task LoginAsync()
        {
            var loginProvider = DependencyService.Get<ILoginProvider>();
            return loginProvider.LoginAsync(client);
        }

也已在android项目中实现。

public async Task LoginAsync(MobileServiceClient client)
        {            
            await client.LoginAsync(context, MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, "tasklistsync2");
        }

因此所有这些过程都将执行,我可以输入我的凭据,但是应用程序停留在那里,登录页面为空白,新的NavigationPage(new Pages.TAskList());行永远不会执行。如果我关闭登录页面,它将转到“尝试并捕获”中的“ finally”块。

我认为缺少的部分是完成登录过程并返回到移动应用程序,但是我不确定如何使这种情况发生(我相信它应该已经发生了)。

本教程中说明的在Azure配置中设置的身份验证过程的回复URL为 https://tasklistsync2.azurewebsites.net/.auth/login/google/callback https://tasklistsync2.azurewebsites.net/.auth/login/aad/callback

1 个答案:

答案 0 :(得分:0)

您需要在特定于iOS和Android的平台上实现登录界面。

 public class iOSPlatform : IPlatform {

            public UIViewController RootView => UIApplication.SharedApplication.KeyWindow.RootViewController;

            public AccountStore AccountStore { get; private set; }

            public iOSPlatform()
            {
                AccountStore = AccountStore.Create();
            }
  public async Task<MobileServiceUser> LoginAsync(MobileServiceClient client)
        {
            var accessToken = await LoginADALAsync();
            var zumoPayload = new JObject();
            zumoPayload["access_token"] = accessToken;
            if (accessToken != null)
                return await client.LoginAsync("aad", zumoPayload);
            else
                return null;
        }

#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        public async Task LogoutAsync()
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            // Do nothing
            var authContext = new AuthenticationContext(Constants.authority);
            if (authContext.TokenCache.ReadItems().Any())
            {
                authContext.TokenCache.Clear();
            }

            //In addition to clearing the token cache, you should also clear the cookies in the web view.
            //Otherwise, the session cookies come into play and that is why you are seeing the web view come up and disappear immediately.
            foreach (var cookie in NSHttpCookieStorage.SharedStorage.Cookies)
            {
                NSHttpCookieStorage.SharedStorage.DeleteCookie(cookie);
            }
        }

        private async Task<string> LoginADALAsync()
        {
            var authContext = new AuthenticationContext(Constants.authority);
            if (authContext.TokenCache.ReadItems().Any())
            {
                authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
            }
            var authResult = await authContext.AcquireTokenAsync(
                Constants.resourceId,
                Constants.clientId,
                new Uri(Constants.redirectUri),
                new PlatformParameters(RootView));
            return authResult.AccessToken;
        }
}

与Android类似,但Android使用Context代替UIViewController

public Context RootView { get; private set; }

        public AccountStore AccountStore { get; private set; }

        public void Init(Context context)
        {
            RootView = context;
            AccountStore = AccountStore.Create(context);
        }