MAUI中IdentityModel OidcClient浏览器在iPad无法全屏的问题
问题:MAUI中IdentityModel OidcClient在iPad上无法全屏显示认证页面
我们使用Visual Studio 2022最新版本开发MAUI项目时,发现通过IdentityModel OidcClient的Browser.InvokeAsync打开的浏览器在iPad(iOS)上无法占用全部屏幕空间,但在安卓平板及iPhone中均可正常全屏显示。
显示效果对比
- iPad显示效果:

- 安卓平板显示效果:

- iPhone显示效果:

我们希望iPad端的表现能与iPhone一致,以下是认证相关代码:
public async Task<LoginSession> LoginAsync() { List<KeyValuePair<string, string>> parameters = new() { new KeyValuePair<string, string>(OidcConstants.AuthorizeRequest.ResponseType, OidcConstants.ResponseTypes.IdTokenToken), new KeyValuePair<string, string>(OidcConstants.AuthorizeRequest.Nonce, Guid.NewGuid().ToString("N")) }; AuthorizeState state = await oidcClient.PrepareLoginAsync(new Parameters(parameters)); state.StartUrl = state.StartUrl.Replace("response_type=code&", ""); var request = new LoginRequest(); var browserOptions = new BrowserOptions(state.StartUrl, options.RedirectUri) { Timeout = TimeSpan.FromSeconds(request.BrowserTimeout), DisplayMode = request.BrowserDisplayMode }; var browserResult = await options.Browser.InvokeAsync(browserOptions); string browserResponse = string.Empty; string Error = string.Empty; string ErrorDescription = string.Empty; if (browserResult.ResultType == BrowserResultType.Success) browserResponse = browserResult.Response; else { Error = browserResult.Error ?? browserResult.ResultType.ToString(); ErrorDescription = browserResult.ErrorDescription; } if (!string.IsNullOrEmpty(browserResponse)) { var url = new Uri(browserResponse); string queryString = url.Query; var queryParse = HttpUtility.ParseQueryString(queryString); var queryDictionary = queryParse.ToDictionary(); var loginSession = queryDictionary.ToObject<LoginSession>(); //loginSession.oidcClient = oidcClient; //loginSession.options = options; return loginSession; } return new LoginSession { Error = Error, ErrorDescription = ErrorDescription }; }
我们已查看BrowserOptions的可用配置,但未找到解决办法:
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. using System; namespace IdentityModel.OidcClient.Browser { /// <summary> /// Options for the browser used for login. /// </summary> public class BrowserOptions { /// <summary> /// Gets the start URL. /// </summary> /// <value> /// The start URL. /// </value> public string StartUrl { get; } /// <summary> /// Gets the end URL. /// </summary> /// <value> /// The end URL. /// </value> public string EndUrl { get; } /// <summary> /// Gets or sets the browser display mode. /// </summary> /// <value> /// The display mode. /// </value> public DisplayMode DisplayMode { get; set; } = DisplayMode.Visible; /// <summary> /// Gets or sets the browser timeout. /// </summary> /// <value> /// The timeout. /// </value> public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(5); /// <summary> /// Initializes a new instance of the <see cref="BrowserOptions"/> class. /// </summary> /// <param name="startUrl">The start URL.</param> /// <param name="endUrl">The end URL.</param> public BrowserOptions(string startUrl, string endUrl) { StartUrl = startUrl; EndUrl = endUrl; } } }
解决思路
自定义iOS专属Browser实现
默认的iOS浏览器实现未针对iPad做全屏适配,可自定义IBrowser实现,在调用SFSafariViewController时强制设置全屏模式:public class CustomIosBrowser : IBrowser { public async Task<BrowserResult> InvokeAsync(BrowserOptions options) { var tcs = new TaskCompletionSource<BrowserResult>(); var safariVc = new SFSafariViewController(new Uri(options.StartUrl)); // 针对iPad设置全屏模态样式 if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad) { safariVc.ModalPresentationStyle = UIModalPresentationStyle.FullScreen; } safariVc.DismissButtonStyle = SFSafariViewControllerDismissButtonStyle.Close; safariVc.DidFinish += (_, __) => tcs.TrySetResult(new BrowserResult { ResultType = BrowserResultType.UserCancel }); // 获取当前顶层ViewController var currentVc = UIApplication.SharedApplication.KeyWindow?.RootViewController; while (currentVc?.PresentedViewController != null) { currentVc = currentVc.PresentedViewController; } if (currentVc != null) { await currentVc.PresentViewControllerAsync(safariVc, true); } // 此处需补充RedirectUri的回调监听逻辑,参考默认Browser实现处理认证回调 return await tcs.Task; } }在iOS项目的
AppDelegate.cs或MAUI的依赖注入配置中注册该自定义Browser:builder.Services.AddSingleton<IBrowser, CustomIosBrowser>();强制应用全屏运行
在iOS项目的Info.plist中添加配置,强制应用以全屏模式运行:<key>UIRequiresFullScreen</key> <true/>更新IdentityModel.OidcClient版本
检查并更新到最新版的IdentityModel.OidcClient,官方可能已修复iPad显示适配问题。显式设置DisplayMode
确认request.BrowserDisplayMode为DisplayMode.Visible,可在代码中显式设置:var browserOptions = new BrowserOptions(state.StartUrl, options.RedirectUri) { Timeout = TimeSpan.FromSeconds(request.BrowserTimeout), DisplayMode = DisplayMode.Visible };
内容的提问来源于stack exchange,提问作者Rui Silva
相关产品推荐
相关产品推荐

