我有一个正在使用Azure AD身份验证的应用程序。我还需要访问Microsoft Graph API以获取用户数据。我发现的每个向Graph API发出请求的示例都使用了缓存的会话令牌,但由于我使用的是JWT,因此显然不需要存储会话状态。如何使用JWT将我的应用程序作为受众来获得具有适当受众的JWT?
例如,这里有一个从Microsoft Graph AspNetCore示例检索令牌的请求:
_userTokenCache = new SessionTokenCache(userId, _memoryCache).GetCacheInstance();
var cca = new ConfidentialClientApplication(
_appId,
_redirectUri,
_credential,
_userTokenCache,
null);
var result = await cca.AcquireTokenSilentAsync(_scopes, cca.Users.First());
return result.AccessToken;
它利用内存缓存从使用OpenId Connect cookie的Challenge()重定向登录中提取令牌。但是,由于我使用的是JWT,我已经有了一个不记名令牌,但权限错误。我需要做些什么来获取一个可以用来访问Graph API的新令牌?我仍然希望令牌对我的应用程序ID进行授权,所以我想要一个新令牌,允许我通过服务器端Rest请求访问API。
编辑:错误地标记为 Azure AD 图形,重新标记为微软图形。
编辑编辑:为了澄清,到目前为止,我看到的每个示例都在使用会话cookie:
services.AddAuthentication(sharedOptions => {
sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAd(options => Configuration.Bind("AzureAd", options))
.AddCookie();
但是,我使用的是JWT,所以没有缓存令牌:
app.UseJwtBearerAuthentication(new JwtBearerOptions {
Authority = $"{instance}{tenant}",
Audience = audience,
SaveToken = true
});
我从对login.microsoftonline.com
的请求中获得的JWT将我的应用程序作为受众,而这些示例生成的JWT将https://graph.microsoft.com
作为受众。所以我需要(我认为至少)仅使用我从标准身份验证请求中获得的令牌为这些受众获取令牌。
不要将如何管理令牌(即令牌缓存)与令牌本身混淆。缓存令牌的原因很简单,您可以根据需要请求刷新令牌(refresh_token
)。刷新令牌仅为某些sceanios提供(即,当使用<code>authorization_code</code>流时,您已请求<code>离线访问</code>范围)。
如果使用的是没有刷新令牌(即隐式
或client_credentials)的
流,则可能不需要缓存令牌。通常仍应缓存它们,因为从 AAD 获取令牌会产生开销成本,并且缓存只允许在现有令牌过期时检索新令牌。
使用委托身份验证提供程序与现有令牌
尽管如此,听起来你已经有了一个令牌。由于MSAL(这也是< code > confidential client application 的来源)的全部目的是为您检索和管理令牌,我不太确定您为什么要这样做。我会简单地跳过MSAL完全只使用您现有的令牌。
如果你用的是微软的图表。您可以完全删除MSAL,只需通过< code > DelegateAuthenticationProvider 使用您现有的令牌(< code>access_token):
var graphServiceClient = new GraphServiceClient(
new DelegateAuthenticationProvider((requestMessage) => {
requestMessage.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token.access_token);
return Task.FromResult(0);
})
);
至于“适当的观众”,我不确定我理解了上下文。您的令牌将需要包括Microsoft Graph的范围,但是您如何定义它们取决于您如何获得令牌。
v1 终结点
如果使用较旧的Azure AD OAUTH终结点(又称v1终结点),则需要通过Azure门户配置应用程序权限。为了在不同的API(称为资源)之间切换,您需要请求offline_access
并使用refresh_token
。切换涉及在传入新的资源
时请求刷新的令牌。然后生成的令牌将使用该资源。
例如,如果我的默认资源是SharePoint Online实例(https://tenant.sharepoint.com
),那么我通常会使用如下内容刷新我的令牌:
private async Task<string> RequestTokenAsync() {
var data = new Dictionary<string, string>();
data.Add("grant_type", "refresh_token");
data.Add("client_id", _clientId);
data.Add("client_secret", _clientSecret);
data.Add("resource", "https://tenant.sharepoint.com");
data.Add("redirect_uri", RedirectUri);
data.Add("refresh_token ", refresh_token);
HttpClient httpClient = new HttpClient();
var response = await httpClient.PostAsync(_tokenUri, new FormUrlEncodedContent(data));
response.EnsureSuccessStatusCode();
var result = await result.Content.ReadAsStringAsync();
}
现在,如果我想调用微软图形,我首先需要获取 https://graph.microsoft.com
资源的令牌:
private async Task<string> RequestTokenAsync() {
var data = new Dictionary<string, string>();
data.Add("grant_type", "refresh_token");
data.Add("client_id", _clientId);
data.Add("client_secret", _clientSecret);
data.Add("resource", "https://graph.microsoft.com");
data.Add("redirect_uri", RedirectUri);
data.Add("refresh_token ", refresh_token);
HttpClient httpClient = new HttpClient();
var response = await httpClient.PostAsync(_tokenUri, new FormUrlEncodedContent(data));
response.EnsureSuccessStatusCode();
var result = await result.Content.ReadAsStringAsync();
}
现在我有两个令牌,一个用于SharePoint,一个用于Microsoft Graph。我可以通过简单地刷新适当资源的令牌来在资源之间切换。但是,我必须确保我正确刷新,因为如果我的refresh_token
在我可以替换它之前过期,我就完全丢失了我的凭据。
如果这听起来很复杂,那确实如此。通常,您需要构建一些机制来管理哪些令牌处于活动状态,哪些令牌需要替换等。这就是令牌缓存的全部内容,因为 MSAL/ADAL 会为您处理此问题。
v2 终结点
较新的v2endpoint更容易使用。它使用< code >范围,而不是< code >资源。这些范围包括资源标识符,可以根据需要动态分配。
因此,虽然在v1中我们可能从Microsoft Graph分配< code>user.read和从Outlook Rest API分配< code>user.read,但我们现在可以通过同时请求< code > https://Graph . Microsoft . com/user . read 和< code > https://Outlook . office . com/user . read 在单个令牌中同时分配这两者。这意味着我们获得了一个可以与任一API一起使用的单一令牌,而无需从上面进入“更新以切换资源”的业务。
v2的缺点是目前只有有限数量的API支持它。如果您需要跨多个API工作,出于这个原因,使用v1可能更好。
希望这能有点帮助。
当我使用自己的客户端id在浏览器中转到以下URL时: https://account-d.docusign.com/oauth/auth?response_type=token 我需要登录,然后我被重定向到:http://localhost:8888/auth#access_token=myAccessToken 现在我有一个节点。在js应用程序中,我想使用我的访问令牌进行API调用,直到现在,我
首先,如果这是一个很长的代码段,我很抱歉,但是,我想做一个模态窗口,它将你在我的用户表单中写的东西写下来,并要求你确认它。我目前正在学习Javascript,我不允许使用innerHTML,我必须动态地编写“名字”等(名字的文本),不允许只在弹出窗口内写它。我已经让大多数东西工作,但“名字”“名字”等显示为“未定义”,或者(正如你可以看到的,我在这种情况下只用名字尝试的事情)显示为“空”。 希望有
问题内容: 我想从客户端上的JavaScript向我的Web应用程序(ASP.NET,IIS 7)发出定期的后台请求,但我不希望该请求影响ASP.NET会话超时。 有没有办法做到这一点? 问题答案: 您必须避免随请求一起发送cookie,因为这是会话ID的传输方式。 如果您有xmlHTTPRequest对象,则可以通过调用删除Cookie标头
我有一个在AWS BeanStalk中运行的应用程序(Tomcat8+SpringMVC+PostgreSQL+EclipseLink)。 我正在使用: eclipselink-org.eclipse.persistence.jpa-2.5.2 Spring MVC-许多特性-4.1.4.发布 postgreSQL-org.postgreSQL-9.3-1100-jdbc41 并将扩展的JpaTr
有没有办法在Spring MVC中获取当前会话,但不是通过请求。通常,我们所做的是在操作/控制器类方法中获取请求。从这个请求中,我们逐个请求获得会话。getSession()。但是,有没有办法在没有此请求对象的情况下获取此会话? 我的动机是,在一个实用程序类中,我需要访问会话中设置的值,而这个实用程序类方法是从控制器类的50多个方法中访问的。如果我必须从请求中获得会话,那么我需要更改所有这50个位
问题内容: 我正在使用Angular框架编写单页应用程序。我是新来的。我已经阅读了本指南,以帮助我了解jQuery和Angular之间的根本区别,并且我想尽可能地遵循本指南,而不使用jQuery。 除了jQuery可以解决一些浏览器不兼容问题之外,并提供有用的函数库,例如能够从窗口顶部知道元素的顶部位置,如。没有普通的JavaScript似乎能够接近而不需要重写这个功能,在这一点岂不_是_ 一个更