我有一个带有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
答案 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);
}