asp.net-mvc – 如何从HttpContext获取JWT(使用OpenIdConnect),
背景
我们在2016年开发了一个使用WS-Federation进行身份验证的应用程序,用于从内部部署AD获取声明. IT战略的方向已经发生变化,并且正朝着Azure AD(目前托管混合环境)发展. 我们正在使用OpenIDConnect将身份验证从WS-Fed迁移到AAD.让用户登录并使用新方法进行身份验证非常简单 – 正确配置,并发出身份验证挑战,而Robert是您母亲的兄弟. 问题 如果我的术语在这里错了,请纠正我;我们需要通过默认的JWT从Active Directory中获取一些无法访问的属性(据我所知).因此,我们需要通过HTTP将JWT传递给Graph API,以从Active Directory获取我们想要的属性. 我知道格式正确且经过身份验证的请求可以提取必要的数据,因为我已经设法使用图形浏览器(AAD一个,而不是Microsoft Graph一个)来查看它. 问题 如果我的理解是正确的,我如何从ASP.Net中的HttpContext中提取JWT?如果我已经正确地掌握了所有这些较低级别的HTTP内容,我需要在Graph API请求的请求标头中包含JWT,我应该获得我需要的JSON文档作为响应. (编辑,为了未来读者的利益:您实际上需要为您尝试访问的特定服务获取新令牌,在本例中为Azure AD.您可以使用代表流程或使用作为应用程序流程). Request.Headers [“IdToken”]返回null,所以我想知道这里出了什么问题. 代码 public void Configuration(IAppBuilder app) { AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; //ConfigureAuth(app); //Old WsFed Auth Code //start the quartz task scheduler //RCHTaskScheduler.Start(); //Azure AD Configuration app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.USEOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { //sets client ID,authority,and RedirectUri as obtained from web config ClientId = clientId,ClientSecret = appKey,Authority = authority,RedirectUri = redirectUrl,//page that users are redirected to on logout PostLogoutRedirectUri = redirectUrl,//scope - the claims that the app will make Scope = OpenIdConnectScope.OpenIdProfile,ResponseType = OpenIdConnectResponseType.IdToken,//setup multi-tennant support here,or set ValidateIssuer = true to config for single tennancy TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true,SaveSigninToken = true },Notifications = new OpenIdConnectAuthenticationNotifications { AuthenticationFailed = OnAuthenticationFailed } } ); } 这是我用于制作GraphAPI请求的部分完整代码: public static async Task<int> getEmployeeNumber(HttpContextBase context) { string token; int employeeId = -1; string path = "https://graph.windows.net/<domain>/users/<AAD_USER_ID>?api-version=1.6"; HttpWebRequest request = null; request = (HttpWebRequest)HttpWebRequest.Create(path); request.Method = "GET"; request.Headers.Add(context.GetOwinContext().Request.Headers["IdToken"]); WebResponse response = await request.GetResponseAsync(); throw new NotImplementedException(); } 解决方法
好吧我花了几天的时间来研究(以及Juunas的一些指示),但这对于代码
here的一些细微修改肯定是可行的.前面提到的是Microsoft的OpenId指南.
我肯定会建议您阅读具体的authentication scenario,并查看相关样本. 以上内容将为您提供帮助,但要从Graph API获取JWT(不要与Microsoft Graph混淆),您需要在进行身份验证时获取身份验证代码,并将其存储在令牌缓存中. 您可以从Microsoft(MIT许可证)的this样本中获取可用的令牌缓存.现在,就我个人而言,我发现这些样本过于复杂,使用复杂的用例,实际上他们应该概述基础知识,但那只是我.不过,这些足以让你走近. 现在为一些代码.请允许我提请您注意’ResponseType = CodeIdToken’. public void ConfigureAuth(IAppBuilder app) { //Azure AD Configuration app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.USEOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { //sets client ID,and RedirectUri as obtained from web config ClientId = clientId,//page that users are redirected to on logout PostLogoutRedirectUri = redirectUrl,//scope - the claims that the app will make Scope = OpenIdConnectScope.OpenIdProfile,ResponseType = OpenIdConnectResponseType.CodeIdToken,or set ValidateIssuer = true to config for single tennancy TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true,//SaveSigninToken = true },Notifications = new OpenIdConnectAuthenticationNotifications { AuthenticationFailed = OnAuthenticationFailed,AuthorizationCodeReceived = OnAuthorizationCodeReceived,} } ); } 提供上述参数时,以下代码将在您进行身份验证时运行: private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context) { var code = context.Code; ClientCredential cred = new ClientCredential(clientId,appKey); string userObjectId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; AuthenticationContext authContext = new AuthenticationContext(authority,new NaiveSessionCache(userObjectId)); // If you create the redirectUri this way,it will contain a trailing slash. // Make sure you've registered the same exact Uri in the Azure Portal (including the slash). Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)); AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code,uri,cred,"https://graph.windows.net"); } 这将为您的令牌缓存提供可以传递给Graph API的代码.从这里开始,我们可以尝试使用Graph API进行身份验证. string path = "https://graph.windows.net/me?api-version=1.6"; string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"]; string userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; string resource = "https://graph.windows.net"; AuthenticationResult result = null; string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture,System.Configuration.ConfigurationManager.AppSettings["Authority"],tenant); ClientCredential cc = new ClientCredential(ConfigurationManager.AppSettings["ClientId"],ConfigurationManager.AppSettings["ClientSecret"]); AuthenticationContext auth = new AuthenticationContext(authority,new NaiveSessionCache(userObjectId)); try { result = await auth.AcquireTokenSilentAsync(resource,ConfigurationManager.AppSettings["ClientId"],new UserIdentifier(userObjectId,UserIdentifierType.UniqueId)).ConfigureAwait(false); } catch (AdalSilentTokenAcquisitionException e) { result = await auth.AcquireTokenAsync(resource,cc,new UserAssertion(userObjectId)); } 获得身份验证令牌后,您可以通过Http Request将其传递给Graph API(这很容易). HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(path); request.Method = "GET"; request.Headers.Set(HttpRequestHeader.Authorization,"Bearer " + result.AccessToken); WebResponse response = request.GetResponse(); System.IO.Stream dataStream = response.GetResponseStream(); 从这里开始,您有一个数据流,您可以将其传递到流读取器,从中获取JSON,并根据需要执行任何操作.就我而言,我只是在查找目录中的用户数据,但不包含在Azure AD身份验证中的默认声明中.所以在我的情况下,我正在调用的URL是 "https://graph.windows.net/me?api-version=1.6" 如果您需要对目录进行更深入的研究,我建议您使用Graph Explorer.这将帮助您构建API调用.再一次,我发现微软文档有点迟钝(如果你想看到一些光滑的东西,请查看Twilio API).但是一旦你弄明白,它实际上并没有那么糟糕. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc – 视图中的HttpContext.User或Page.User?
- asp.net – Sitecore获取渲染的HTML
- ASP.NET发布Web API接口时请求方式版本差异问题
- asp.net-mvc – 从MVC中的控制器确定部分视图的模型
- asp.net-mvc – 如何添加代码隐藏页面到视图或部分视图
- asp.net-mvc-3 – 错误:asp.net mvc3中当前上下文中不存在
- IIS应用程序池_缓存回收
- odata – 与Breezejs发布批量请求
- asp.net – 干净的方式来防止输入按钮提交表单
- asp.net – 带有MVC 4.0的DotNetOpenAuth