对于Winforms Desktop应用程序,我将在PKCE中使用授权代码流。作为身份提供者,我使用IdentityServer并作为客户端库OicdClient。 下一步,我必须确定要用于用户登录的浏览器:
对于SystemBrowser来说,该流程是简单/清晰的实现。 对于扩展WebBrowser来说,某些用户可能没有SystemBrowser。但是WebBrowser是较旧的IE版本吗?并允许用于安全身份验证吗?
尽管如此,我还是尝试了“扩展的WebBrowser”示例,并尝试将其与自己的IS4服务器集成到我的原型环境中。因此,我需要对代码流和重定向有所了解。 我已经使用纯.Net类实现了此授权代码流,但是使用OicdClient会使我有点困惑(一开始就像黑盒子一样)。
我的问题是重定向如何与此库一起工作,谁负责重定向,谁负责接收代码重定向(以交换访问令牌)?
代码流具有以下步骤(没有诸如clientID,PKCE ...之类的详细信息):
使用OidcClient并使用Automatic Mode:
var options = new OidcClientOptions
{
Authority = "https://demo.identityserver.io",
ClientId = "native",
RedirectUri = redirectUri,
Scope = "openid profile api",
Browser = new SystemBrowser()
};
var client = new OidcClient(options);
var result = await client.LoginAsync();
这对我来说是不可思议的。只有对LoginAsync()的调用才能使它起作用...
重要的一点似乎是带有IBrowser接口的选项的Browser属性及其此方法的实现:
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)
{ ....}
}
}
如果我尝试映射到流程步骤:
1和5可能是由OicdClient完成的。该示例相当清楚,需要确认重定向是由IS4完成的。
另一个示例Extended WebBrowser
中的实现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;
}
}
这有什么问题吗? 在IS4上,AccountController.Login被调用 调用/连接/授权/回调?与redirect_uri。 但是,BeforeNavigate2并没有做到这一点。相反,出现NavigateError事件,结果设置为:
result.ResultType = BrowserResultType.Success;
result.Response = e.Url;
答案 0 :(得分:1)
当前的最佳实践是使用用户的默认Web浏览器,而不是嵌入浏览器组件。至于如何实现-由于无法使用这种方法拦截浏览器导航事件,因此您需要实现一个HTTP侦听器,该侦听器可以接受来自identityserver4
实现的POST请求。
已阅读以下内容:https://auth0.com/blog/oauth-2-best-practices-for-native-apps/