Identityserver4 具有标识4和OIDClient的授权代码流
对于Winforms桌面应用程序,我将使用PKCE的授权代码流。作为身份提供者,我使用和作为客户端库。 下一步,我必须决定使用哪个浏览器进行用户登录:Identityserver4 具有标识4和OIDClient的授权代码流,identityserver4,identitymodel,oidc-client,Identityserver4,Identitymodel,Oidc Client,对于Winforms桌面应用程序,我将使用PKCE的授权代码流。作为身份提供者,我使用和作为客户端库。 下一步,我必须决定使用哪个浏览器进行用户登录: For SystemBrowser讲述了流程的简单/清晰实现。 对于Extended WebBrowser,有些用户可能没有系统浏览器。但是WebBrowser是一个旧的IE版本吗?它是否允许用于安全身份验证 尽管如此,我还是尝试了“ExtendedWebBrowser”示例,并将其与自己的IS4服务器集成到我的原型环境中。因此,我需要一
public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken)
{
using (var listener = new LoopbackHttpListener(Port, _path))
{
OpenBrowser(options.StartUrl);
try
{
var result = await listener.WaitForCallbackAsync();
if (String.IsNullOrWhiteSpace(result))
{
return new BrowserResult { ResultType = BrowserResultType.UnknownError, Error = "Empty response." };
}
return new BrowserResult { Response = result, ResultType = BrowserResultType.Success };
}
catch (TaskCanceledException ex)
{ ....}
}
}
当前的最佳实践是使用用户的默认web浏览器,而不是嵌入浏览器组件。至于如何实现这一点——由于无法使用这种方法截获浏览器导航事件,因此需要实现一个HTTP侦听器,该侦听器可以接受来自
identityserver4
实现的POST请求
读一读:
本RFC:
public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken)
{
using (var listener = new LoopbackHttpListener(Port, _path))
{
OpenBrowser(options.StartUrl);
try
{
var result = await listener.WaitForCallbackAsync();
if (String.IsNullOrWhiteSpace(result))
{
return new BrowserResult { ResultType = BrowserResultType.UnknownError, Error = "Empty response." };
}
return new BrowserResult { Response = result, ResultType = BrowserResultType.Success };
}
catch (TaskCanceledException ex)
{ ....}
}
}
public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default(CancellationToken))
{
using (var form = _formFactory.Invoke())
using (var browser = new ExtendedWebBrowser()
{
Dock = DockStyle.Fill
})
{
var signal = new SemaphoreSlim(0, 1);
var result = new BrowserResult
{
ResultType = BrowserResultType.UserCancel
};
form.FormClosed += (o, e) =>
{
signal.Release();
};
browser.NavigateError += (o, e) =>
{
e.Cancel = true;
if (e.Url.StartsWith(options.EndUrl))
{
result.ResultType = BrowserResultType.Success;
result.Response = e.Url;
}
else
{
result.ResultType = BrowserResultType.HttpError;
result.Error = e.StatusCode.ToString();
}
signal.Release();
};
browser.BeforeNavigate2 += (o, e) =>
{
var b = e.Url.StartsWith(options.EndUrl);
if (b)
{
e.Cancel = true;
result.ResultType = BrowserResultType.Success;
result.Response = e.Url;
signal.Release();
}
};
form.Controls.Add(browser);
browser.Show();
System.Threading.Timer timer = null;
form.Show();
browser.Navigate(options.StartUrl);
await signal.WaitAsync();
if (timer != null) timer.Change(Timeout.Infinite, Timeout.Infinite);
form.Hide();
browser.Hide();
return result;
}
}
result.ResultType = BrowserResultType.Success;
result.Response = e.Url;