尝试使用 OpenID 和 dotnetopenauth 登录 Azure AD 但得到 "No OpenID endpoint found."

Trying to log into Azure AD using OpenID and dotnetopenauth but getting "No OpenID endpoint found."

我在 SO 中搜索了类似的问题并查看了所有问题,但没有找到可以帮助我解决我遇到的问题的问题。

我正在尝试为 Azure AD 的旧 Web 表单应用程序添加身份验证。另一位开发人员已经添加了 OpenID 支持,所以我认为最简单的方法是使用 AzureAD 中的 OpenID 端点和我们应用程序中的现有代码。但是,我无法让它工作。

我不知道问题出在我正在使用的端点 URL、我们用来尝试连接的代码、我如何配置 AzureAD 应用程序,还是一个基本问题对我想做的事情有误解。

这应该是一个 multi-tenant 应用程序,意思是,如果我理解正确的话,用户可以使用我们的 Azure AD 或其他 Azure AD 中的帐户登录,然后我们的应用程序可以选择授予不授予访问权限.但是,我什至无法让它确认我的目标是有效的 OpenID 端点,更不用说从我们自己的 Azure AD 中使用用户登录了。

OpenID代码使用http://dotnetopenauth.net/编写,调用CreateRequest()时出现错误

Using OpenID As New OpenIdRelyingParty
Dim LoginEndpoint = "<azure ad endpoint goes here>"
Dim Request As IAuthenticationRequest = OpenID.CreateRequest(LoginEndpoint)
End Using

对于 LoginEndpoint,我已经尝试了所有我能想到的组合。

作为基准,我首先使用 Yahoo 进行了测试,效果很好。我使用了端点 https://me.yahoo.com

然后,根据MS Docs,我发现 https://login.microsoftonline.com/MyEXAMPLE.com/v2.0/.well-known/openid-configuration 或者 https://login.microsoftonline.com/MyEXAMPL-GUID-0000-0000-000000000000/v2.0/.well-known/openid-configuration

并且在返回的 JSON 中我选择了 authorization_endpoint 看起来像 https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize

authorization_endpoint 是我在上面的代码示例中尝试作为 LoginEndpoint 传递的内容。

当这不起作用时,我尝试在浏览器中查看 Yahoo 页面和 Azure AD authorization_endpoint,Azure AD 报告缺少一些字段,而 Yahoo 报告 404,所以我'我猜想这些并不是直接在浏览器中访问的。

但是,为了穷尽所有可能性,我尝试通过在查询字符串上传递它们来为 Azure AD 提供它想要的值。所以我最终得到了类似的东西 https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize?client_id=CLIENTID-GUID-0000-0000-000000000000&scope=openid

我通过进入 Azure AD 并找到我注册的应用程序获得了 client_id,我得到了标记为应用程序 ID 的值。我 认为 我这样做是因为我有另一个可用的应用程序(asp.net 核心而不是 asp.net 框架 webforms)并且我们使用应用程序 ID 作为客户端 ID 并且它有效,但如果我应该从其他地方获取客户 ID,请告诉我。

无论如何,当我这样做并将其插入浏览器时,它显示了 MS 登录页面,没有错误,但是当我尝试在我的代码中使用 URL 作为 LoginEndpoint 时,它仍然不起作用。

我尝试查看在登录 Yahoo 和 Azure AD 时网络服务器在 Fiddler 中发送和接收的网络流量,虽然我发现了一些有趣的东西,但我没有找到任何可以帮助我解决问题的东西。基本上,我想我理解为什么 dotnetopenauth.net 不喜欢我给它的 url,但这并没有帮助我修复它。这不是我的专业领域,但我没有看到我认为 dotnetopenauth.net 在 HTML 和 HTTP Headers 中执行 "discovery" 时正在寻找的东西,所以它认为它不是 OpenID 端点。

所以接下来我打开日志记录并再次尝试使用我的端点的两个版本 url 但它没有向我显示任何有用的信息,但也许它会对阅读本文的人有所帮助。

2019-01-02 23:26:30,450 (GMT-5) [11] INFO  DotNetOpenAuth - DotNetOpenAuth.Core, Version=4.3.4.13329, Culture=neutral, PublicKeyToken=2780ccd10d57b246 (official)
2019-01-02 23:26:30,450 (GMT-5) [11] INFO  DotNetOpenAuth - DotNetOpenAuth.Core, Version=4.3.4.13329, Culture=neutral, PublicKeyToken=2780ccd10d57b246 (official)
2019-01-02 23:26:30,517 (GMT-5) [11] INFO  DotNetOpenAuth - Reporting will use isolated storage with scope: User, Domain, Assembly
2019-01-02 23:26:30,517 (GMT-5) [11] INFO  DotNetOpenAuth - Reporting will use isolated storage with scope: User, Domain, Assembly
2019-01-02 23:26:34,738 (GMT-5) [11] INFO  DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: http://localhost:49221/Initial/Login.aspx?ReturnUrl=%2fDashboard.aspx
2019-01-02 23:26:34,738 (GMT-5) [11] INFO  DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: http://localhost:49221/Initial/Login.aspx?ReturnUrl=%2fDashboard.aspx
2019-01-02 23:26:34,741 (GMT-5) [11] DEBUG DotNetOpenAuth.Messaging.Channel - Incoming HTTP request: GET http://localhost:49221/Initial/Login.aspx?ReturnUrl=%2fDashboard.aspx
2019-01-02 23:26:34,741 (GMT-5) [11] DEBUG DotNetOpenAuth.Messaging.Channel - Incoming HTTP request: GET http://localhost:49221/Initial/Login.aspx?ReturnUrl=%2fDashboard.aspx
2019-01-02 23:26:57,115 (GMT-5) [8] INFO  DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: http://localhost:49221/Initial/Login.aspx?ReturnUrl=%2f
2019-01-02 23:26:57,115 (GMT-5) [8] INFO  DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: http://localhost:49221/Initial/Login.aspx?ReturnUrl=%2f
2019-01-02 23:26:57,116 (GMT-5) [8] DEBUG DotNetOpenAuth.Messaging.Channel - Incoming HTTP request: GET http://localhost:49221/Initial/Login.aspx?ReturnUrl=%2f
2019-01-02 23:26:57,116 (GMT-5) [8] DEBUG DotNetOpenAuth.Messaging.Channel - Incoming HTTP request: GET http://localhost:49221/Initial/Login.aspx?ReturnUrl=%2f
2019-01-02 23:33:39,365 (GMT-5) [10] DEBUG DotNetOpenAuth.OpenId - .NET Uri class path compression overridden.
2019-01-02 23:33:39,365 (GMT-5) [10] DEBUG DotNetOpenAuth.OpenId - .NET Uri class path compression overridden.
2019-01-02 23:33:39,433 (GMT-5) [10] DEBUG DotNetOpenAuth.Http - HTTP GET https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize?client_id=CLIENTID-GUID-0000-0000-000000000000&scope=openid
2019-01-02 23:33:39,433 (GMT-5) [10] DEBUG DotNetOpenAuth.Http - HTTP GET https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize?client_id=CLIENTID-GUID-0000-0000-000000000000&scope=openid
2019-01-02 23:33:39,855 (GMT-5) [10] DEBUG DotNetOpenAuth.Yadis - HTML discovery failed to find any endpoints.
2019-01-02 23:33:39,855 (GMT-5) [10] DEBUG DotNetOpenAuth.Yadis - HTML discovery failed to find any endpoints.
2019-01-02 23:33:39,865 (GMT-5) [10] INFO  DotNetOpenAuth.Yadis - Performing discovery on user-supplied identifier: https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize?client_id=CLIENTID-GUID-0000-0000-000000000000&scope=openid
2019-01-02 23:33:39,865 (GMT-5) [10] INFO  DotNetOpenAuth.Yadis - Performing discovery on user-supplied identifier: https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize?client_id=CLIENTID-GUID-0000-0000-000000000000&scope=openid
2019-01-02 23:33:39,869 (GMT-5) [10] DEBUG DotNetOpenAuth.Yadis - Filtering and sorting of endpoints did not affect the list.
2019-01-02 23:33:39,869 (GMT-5) [10] DEBUG DotNetOpenAuth.Yadis - Filtering and sorting of endpoints did not affect the list.
2019-01-02 23:51:30,214 (GMT-5) [17] DEBUG DotNetOpenAuth.Http - HTTP GET https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize
2019-01-02 23:51:30,214 (GMT-5) [17] DEBUG DotNetOpenAuth.Http - HTTP GET https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize
2019-01-02 23:51:30,492 (GMT-5) [17] DEBUG DotNetOpenAuth.Yadis - HTML discovery failed to find any endpoints.
2019-01-02 23:51:30,492 (GMT-5) [17] DEBUG DotNetOpenAuth.Yadis - HTML discovery failed to find any endpoints.
2019-01-02 23:51:30,493 (GMT-5) [17] INFO  DotNetOpenAuth.Yadis - Performing discovery on user-supplied identifier: https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize
2019-01-02 23:51:30,493 (GMT-5) [17] INFO  DotNetOpenAuth.Yadis - Performing discovery on user-supplied identifier: https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize
2019-01-02 23:51:30,495 (GMT-5) [17] DEBUG DotNetOpenAuth.Yadis - Filtering and sorting of endpoints did not affect the list.
2019-01-02 23:51:30,495 (GMT-5) [17] DEBUG DotNetOpenAuth.Yadis - Filtering and sorting of endpoints did not affect the list.

请让我知道您需要的任何其他信息,我会添加。

编辑 2019-01-03 5:04PM 东部 如果我添加 ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3

我在我的应用程序中遇到了同样的异常,但日志现在显示以下错误

2019-01-03 17:00:31,925 (GMT-5) [7] DEBUG DotNetOpenAuth.Http - HTTP GET https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize
2019-01-03 17:00:32,374 (GMT-5) [7] ERROR DotNetOpenAuth.Http - SendFailure connecting to https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize
2019-01-03 17:00:32,374 (GMT-5) [7] ERROR DotNetOpenAuth.Http - SendFailure connecting to https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize
2019-01-03 17:00:32,376 (GMT-5) [7] ERROR DotNetOpenAuth.Yadis - Error while performing discovery on: "https://login.microsoftonline.com/ANOTHER0-GUID-0000-0000-000000000000/oauth2/v2.0/authorize": DotNetOpenAuth.Messaging.ProtocolException: Error occurred while sending a direct message or getting the response. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.TlsStream.CallProcessAuthentication(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.ConnectStream.WriteHeaders(Boolean async)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
   at DotNetOpenAuth.Messaging.StandardWebRequestHandler.GetResponse(HttpWebRequest request, DirectWebRequestOptions options)
   --- End of inner exception stack trace ---
   at DotNetOpenAuth.Messaging.StandardWebRequestHandler.GetResponse(HttpWebRequest request, DirectWebRequestOptions options)
   at DotNetOpenAuth.Messaging.UntrustedWebRequestHandler.GetResponse(HttpWebRequest request, DirectWebRequestOptions options)
   at DotNetOpenAuth.Yadis.Yadis.Request(IDirectWebRequestHandler requestHandler, Uri uri, Boolean requireSsl, String[] acceptTypes)
   at DotNetOpenAuth.Yadis.Yadis.Discover(IDirectWebRequestHandler requestHandler, UriIdentifier uri, Boolean requireSsl)
   at DotNetOpenAuth.OpenId.UriDiscoveryService.Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, Boolean& abortDiscoveryChain)
   at DotNetOpenAuth.OpenId.IdentifierDiscoveryServices.Discover(Identifier identifier)
   at DotNetOpenAuth.OpenId.RelyingParty.AuthenticationRequest.Create(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, Boolean createNewAssociationsAsNeeded)

进行此更改后,代码将如下所示:

Using OpenID As New OpenIdRelyingParty
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
Dim LoginEndpoint = "<azure ad endpoint goes here>"
Dim Request As IAuthenticationRequest = OpenID.CreateRequest(LoginEndpoint)
End Using

请尝试将此行添加到您的网站,然后再调用 OpenIdRelyingParty.CreateRequest:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 ;

如果这有帮助,请告诉我们。我们最近发现这解决了某些 Azure 配置的问题。

我发布这个是为了回答我自己的问题,但我想提醒一下,我不是 100% 确定我在这个问题上是正确的,但我很确定。

我认为我的问题是 DotNetOpenAuth.net 或者至少是我正在使用的部分试图在我尝试连接到 OpenID Connect 端点的地方建立 OpenID 2 连接。

当我开始这个的时候,我没有意识到它们是不同的,并且花了很多时间直到我遇到一个解释。

DotNetOpenAuth.net Git 存储库中确实有一个连接到 AzureAD 端点的示例,但它使用的代码和对象似乎与我在代码和在撰写本文时,我可以在 DotNetOpenAuth.net 文档中找到什么。也许我只是找不到它,但我在任何地方都没有看到它。

所以我决定,既然无论如何我都必须使用不同的东西,我将只使用 Microsoft 的 OpenID Connect 和 AzureAD 代码。