You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI中IdentityModel OidcClient浏览器在iPad无法全屏的问题

问题:MAUI中IdentityModel OidcClient在iPad上无法全屏显示认证页面

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

显示效果对比

  • iPad显示效果:iPad显示效果
  • 安卓平板显示效果:安卓平板显示效果
  • iPhone显示效果: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:09:55