我注册了一个网络API https://dev.office.com/app-registration。我保留了签名网址 localhost:8000和RedirectURI as localhost:8000。
在此之后,我创建了一个控制台应用程序来访问图API。这是代码。但它不起作用。我收到错误“访问被拒绝”。
我在这里遗漏了什么?
还有一件事,我检查了access_token,我在那里看不到任何用户信息。 string clientId =“<>”; string clientsecret =“<>”; string tenant =“my.com”;
var authUri = "https://login.microsoftonline.com/" + tenant + "/oauth2/token";
var RESOURCE_URL = "https://graph.microsoft.com";
HttpClient client = new HttpClient();
var authContext = new AuthenticationContext(authUri);
var credential = new ClientCredential(clientId: clientId, clientSecret: clientsecret);
var result = authContext.AcquireTokenAsync(RESOURCE_URL, credential).Result;
Console.WriteLine(result.AccessToken.ToString());
client.DefaultRequestHeaders.Add("Authorization", "bearer " + result.AccessToken);
var httpContent = new StringContent(content, Encoding.GetEncoding("utf-8"), "application/json");
var response = client.GetAsync("https://graph.microsoft.com/v1.0/users/ankushb/calendar/events").Result;
// var response = client.PostAsync("https://graph.microsoft.com/v1.0/groups", httpContent).Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
答案 0 :(得分:0)
Azure AD使用的OAuth2有两种基本身份验证流程。
首先是authorization code grant flow,用于访问本机客户端和网站的Web API。在此流程中,用户委派对客户端应用程序的访问权限。
第二个是Client Credentials grant flow,它允许Web服务(机密客户端)在调用另一个Web服务时使用自己的凭据进行身份验证,而不是模仿用户。在这种情况下,客户端通常是中间层Web服务,守护程序服务或网站。
上面的代码使用的是客户端凭据授权流程,这就是没有用户信息的原因。
在您的方案中,您应该注册一个原生应用程序(控制台应用程序不是不应该使用该秘密来请求令牌的机密客户端)并使用授权代码授予流程< / strong>允许用户使用其帐户登录。要在控制台应用程序中使用此流程,我们需要提示Web对话框导航到登录页面并获取auth代码以请求访问令牌。
以下是使用授权代码授权流程对应用进行身份验证的示例:
var oauth = new OauthConfiguration
{
Authority = "https://login.microsoftonline.com",
Tenant = "common",
ClientId = "{clientId}",
RedirectURI = "{redirectURL}",
Secret = ""
};
var tokenResponse = new OAuth2.OauthWebAuthHelper(oauth).AcquireTokenWithResource("https://graph.microsoft.com");
var accessToken = tokenResponse.GetValue("access_token").Value<string>();
var refreshToken = tokenResponse.GetValue("refresh_token").Value<string>();
namespace OAuth2
{
public class OauthWebAuthHelper
{
public enum Version
{
V1 = 1,
V2 = 2
}
private OauthConfiguration _configuration;
private const string OAUTH2_AUTHORIZE_V1_SUFFIX = @"oauth2/";
private const string OAUTH2_AUTHORIZE_V2_SUFFIX = @"oauth2/v2.0";
private string _authorizeSuffix;
public OauthWebAuthHelper(OauthConfiguration configuration, Version version = Version.V1)
{
_configuration = configuration;
switch (version)
{
case Version.V1: _authorizeSuffix = OAUTH2_AUTHORIZE_V1_SUFFIX; break;
case Version.V2: _authorizeSuffix = OAUTH2_AUTHORIZE_V2_SUFFIX; break;
}
}
public void LogOut()
{
var dialog = new WebBrowserDialog();
dialog.Open(string.Format("{0}/logout", EndPointUrl));
}
protected string EndPointUrl
{
get
{
return string.Format("{0}/{1}/{2}", _configuration.Authority, _configuration.Tenant, _authorizeSuffix);
}
}
public JObject GetAuthorizationCode()
{
JObject response = new JObject();
var parameters = new Dictionary<string, string>
{
{ "response_type", "code" },
{ "client_id", _configuration.ClientId },
{ "redirect_uri", _configuration.RedirectURI },
{ "prompt", "login"}
};
var requestUrl = string.Format("{0}/authorize?{1}", EndPointUrl, BuildQueryString(parameters));
var dialog = new WebBrowserDialog();
dialog.OnNavigated((sender, arg) =>
{
if (arg.Url.AbsoluteUri.StartsWith(_configuration.RedirectURI))
{
var collection = HttpUtility.ParseQueryString(arg.Url.Query);
foreach (var key in collection.AllKeys)
{
response.Add(key, collection[key]);
}
dialog.Close();
}
});
dialog.Open(requestUrl);
return response;
}
public JObject GetAuthorizationCode(string scope)
{
JObject response = new JObject();
var parameters = new Dictionary<string, string>
{
{ "response_type", "code" },
{ "client_id", _configuration.ClientId },
{ "redirect_uri", _configuration.RedirectURI },
{ "prompt", "login"},
{ "scope", scope}
};
var requestUrl = string.Format("{0}/authorize?{1}", EndPointUrl, BuildQueryString(parameters));
var dialog = new WebBrowserDialog();
dialog.OnNavigated((sender, arg) =>
{
if (arg.Url.AbsoluteUri.StartsWith(_configuration.RedirectURI))
{
var collection = HttpUtility.ParseQueryString(arg.Url.Query);
foreach (var key in collection.AllKeys)
{
response.Add(key, collection[key]);
}
dialog.Close();
}
});
dialog.Open(requestUrl);
return response;
}
public JObject AcquireTokenWithResource(string resource)
{
var codeResponse = GetAuthorizationCode();
var code = codeResponse.GetValue("code").Value<string>();
var parameters = new Dictionary<string, string>
{
{ "resource", resource},
{ "client_id", _configuration.ClientId },
{ "code", code},
{ "grant_type", "authorization_code" },
{ "redirect_uri", _configuration.RedirectURI},
{ "client_secret",_configuration.Secret}
};
var client = new HttpClient();
var content = new StringContent(BuildQueryString(parameters), Encoding.GetEncoding("utf-8"), "application/x-www-form-urlencoded");
var url = string.Format("{0}/token", EndPointUrl);
var response = client.PostAsync(url, content).Result;
var text = response.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject(text) as JObject;
}
public JObject RefreshTokenWithResource(string refreshToken)
{
var parameters = new Dictionary<string, string>
{
{ "client_id", _configuration.ClientId },
{ "refresh_token", refreshToken},
{ "grant_type", "refresh_token" }
};
var client = new HttpClient();
var content = new StringContent(BuildQueryString(parameters), Encoding.GetEncoding("utf-8"), "application/x-www-form-urlencoded");
var url = string.Format("{0}/token", EndPointUrl);
var response = client.PostAsync(url, content).Result;
var text = response.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject(text) as JObject;
}
public JObject AcquireTokenWithScope(string scope)
{
var codeResponse = GetAuthorizationCode(scope);
var code = codeResponse.GetValue("code").Value<string>();
var parameters = new Dictionary<string, string>
{
{ "client_id", _configuration.ClientId },
{ "code", code},
{ "grant_type", "authorization_code" },
{ "redirect_uri", _configuration.RedirectURI},
};
var client = new HttpClient();
var content = new StringContent(BuildQueryString(parameters), Encoding.GetEncoding("utf-8"), "application/x-www-form-urlencoded");
var url = string.Format("{0}/token", EndPointUrl);
var response = client.PostAsync(url, content).Result;
var text = response.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject(text) as JObject;
}
private string BuildQueryString(IDictionary<string, string> parameters)
{
var list = new List<string>();
foreach (var parameter in parameters)
{
if (!string.IsNullOrEmpty(parameter.Value))
list.Add(string.Format("{0}={1}", parameter.Key, HttpUtility.UrlEncode(parameter.Value)));
}
return string.Join("&", list);
}
}
public class OauthConfiguration
{
public string Authority { get; set; }
public string Tenant { get; set; }
public string ClientId { get; set; }
public string RedirectURI { get; set; }
public string Secret { get; set; }
}
public class WebBrowserDialog
{
private const int DEFAULT_WIDTH = 400;
private const int DEFAULT_HEIGHT = 500;
private Form _displayLoginForm;
private string _title;
private WebBrowser _browser;
private WebBrowserNavigatedEventHandler _webBrowserNavigatedEventHandler;
public WebBrowserDialog()
{
_title = "OAuth Basic";
_browser = new WebBrowser();
_browser.Width = DEFAULT_WIDTH;
_browser.Height = DEFAULT_HEIGHT;
_browser.Navigated += WebBrowserNavigatedEventHandler;
_displayLoginForm = new Form();
_displayLoginForm.SuspendLayout();
_displayLoginForm.Width = DEFAULT_WIDTH;
_displayLoginForm.Height = DEFAULT_HEIGHT;
_displayLoginForm.Text = _title;
_displayLoginForm.Controls.Add(_browser);
_displayLoginForm.ResumeLayout(false);
}
public void OnNavigated(WebBrowserNavigatedEventHandler handler)
{
_webBrowserNavigatedEventHandler = handler;
}
protected void WebBrowserNavigatedEventHandler(object sender, WebBrowserNavigatedEventArgs e)
{
if(_webBrowserNavigatedEventHandler != null)
{
_webBrowserNavigatedEventHandler.Invoke(sender, e);
}
}
public void Open(string url)
{
_browser.Navigate(url);
_displayLoginForm.ShowDialog();
}
public void Close()
{
_displayLoginForm.Close();
}
}
}
您可以从here获取更多有关Microsoft Graph的示例。