如何使用OAuth授予应用程序对Office365的访问权限
本文关键字:Office365 访问 访问权 权限 应用程序 何使用 OAuth | 更新日期: 2023-09-27 18:10:59
我尝试让用户浏览到一个网页,在那里他必须决定我的应用程序是否可以访问他在OneDrive for Business上的文件。
我用下面的代码和使用这个网站做到了这一点:
private string _authorizationEndpoint = "https://login.windows.net/[code]/oauth2/authorize?api-version=1.0/";
private string _tokenEndpoint = "https://login.windows.net/";
private string _clientId = "[Client Id]";
private string _resource = "https%3A%2F%2F[company]-my.sharepoint.com%2F";
private string _redirectURI = "http%3A%2F%2Fwww.nu.nl%2F";
private string _state = "5gdfd60b-8447-4536-b23f-fcb658e19458";
private string _authorizationCode = "";
private TokenInformation _tokenInformation = new TokenInformation();
private AuthorizationInformation _authorizationInformation = new AuthorizationInformation();
private void btnAuthenticate_Click(object sender, EventArgs e)
{
webBrowser1.Navigate(GetAuthorizationUrl());
}
private string GetAuthorizationUrl()
{
// Create a request for an authorization code.
string url = string.Format("{0}common/oauth2/authorize?response_type=code&client_id={1}&redirect_uri={2}&resource={3}&state={4}",
_authorizationEndpoint,
_clientId,
_redirectURI,
_resource,
_state);
return url; //"https://login.windows.net/[code]/oauth2/authorize?api-version=1.0/common/oauth2/authorize?response_type=code&client_id=[Client Id]&redirect_uri=http%3A%2F%2Fwww.nu.nl%2F&resource=https:%2f%2foutlook.office365.com%2f&state=5gdfd60b-8447-4536-b23f-fcb658e19458"
}
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
txtUrl.Text = e.Url.AbsoluteUri.ToString();
if (e.Url.AbsoluteUri.Contains("code=") && e.Url.AbsoluteUri.Contains("state"))
{
var splited = e.Url.AbsoluteUri.Split(new char[] { '=', '&' });
_authorizationInformation.Code = splited[1];
_authorizationInformation.SessionState = splited[3];
if (_authorizationInformation.SessionState.Equals(_state)) // Needs to change every request in order to avoid CSRF
{
GetTokenInformation(_authorizationInformation);
}
else
{
MessageBox.Show("Cross-site request forgery", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private string GetAdminPermissionUrl()
{
return string.Format("{0}common/oauth2/authorize?&response_type=code&client_id={1}&redirect_uri={2}&resource={3}&state={4}&prompt=admin_consent",
_authorizationEndpoint,
_clientId,
_redirectURI,
_resource,
_state
);
}
private TokenInformation GetTokenInformation(AuthorizationInformation authInformation)
{
try
{
var response = Post(HttpUtility.UrlEncode(_tokenEndpoint + "common/oauth2/token/"), new NameValueCollection(){
{ "grant_type", "authorization_code" },
{ "code", authInformation.Code },
{ "redirect_uri", _redirectURI },
{ "client_id", _clientId },
//{ "client_secret", "" }, According to the website I mentioned I need to have a clientsecret, but this is a nativa application so I dont have one
});
Stream responseStream = new MemoryStream(response);
using (var reader = new StreamReader(responseStream))
{
var json = reader.ReadToEnd();
_tokenInformation = JsonConvert.DeserializeObject<TokenInformation>(json);
}
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Error" + exception.HResult.ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return null;
}
public byte[] Post(string uri, NameValueCollection pairs)
{
byte[] response = null;
using (WebClient client = new WebClient())
{
response = client.UploadValues(uri, pairs);
}
return response;
}
—您可以假设我使用了正确的凭据。
当用户登录并授予访问权限时。
根据我之前提到的网站,我得到一个返回的代码来交换一个accesstoken和一个refreshtoken。
现在有一个问题,我没有client_secret(在Azure Active Directory),因为我开发了一个本地应用程序,我猜。
GetTokenInformation方法现在不能工作。如何正确获取访问令牌和刷新令牌?
提前感谢!
如果您在Azure管理门户中将应用程序配置为本机应用程序,则不需要提供"client_secret"参数。
但是,您确实需要在POST中为令牌授权端点提供一个"资源"参数。这是一个字符串,它指向您希望获得访问/刷新令牌的Office 365资源。这将是您已经在初始身份验证请求url中使用的相同的资源字符串。(编辑:我认为甚至没有必要将资源参数添加到初始身份验证请求中-在我的测试中没有它就可以工作。但是,当post到授权端点以获取令牌时,这当然是必要的)最后,你还应该确保你的原生应用在Azure管理门户中有正确的权限设置。更具体地说,如果还没有这样做,你需要将"Office 365 Sharepoint Online"应用程序添加到"其他应用程序的权限"部分,并将该应用程序的必要详细权限标记为勾选。
v2.0协议- OAuth 2.0授权码流程https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flowhttps://auth0.com/docs/connections/enterprise/azure-active-directory/v2 6-create-connections '
private static string redirectDomain = System.Configuration.ConfigurationManager.AppSettings["DomainName"];
private string state = Guid.NewGuid().ToString();
private static string client_id = System.Configuration.ConfigurationManager.AppSettings["O365ClientId"];
private static string client_secret = System.Configuration.ConfigurationManager.AppSettings["O365ClientSecret"];
public ActionResult IndexAsync(CancellationToken cancellationToken)
{
string url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id="+client_id+"&response_type=code&redirect_uri=http://localhost/Controllers/o365login/callback&response_mode=query&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read&state=" + state;
return Redirect(url);
}
public async void Callback(string code,string state)
{
var o365UserInfo = await getO365UserInfo(code);
if(o365UserInfo != null)
{
O365user o365User = GetEmailFromIdToken(o365UserInfo.access_token);
if (o365User != null)
{
}
}
}
private async Task<O365UserInfo> getO365UserInfo(string code)
{
try
{
string url = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
postData.Add(new KeyValuePair<string, string>("code", code));
postData.Add(new KeyValuePair<string, string>("redirect_uri", "http://localhost/Controllers/o365login/callback"));
postData.Add(new KeyValuePair<string, string>("client_id", client_id));
postData.Add(new KeyValuePair<string, string>("client_secret", client_secret));
using (var httpClient = new HttpClient())
{
using (var content = new FormUrlEncodedContent(postData))
{
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var req = new HttpRequestMessage(HttpMethod.Post, url) { Content = content };
HttpResponseMessage response = await httpClient.SendAsync(req);
O365UserInfo o365UserInfo= await response.Content.ReadAsAsync<O365UserInfo>();
return o365UserInfo;
}
}
}catch(Exception ex)
{
return null;
}
}
class O365UserInfo
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string expires_on { get; set; }
public string resource { get; set; }
public string refresh_token { get; set; }
public string scope { get; set; }
public string id_token { get; set; }
}
class O365user
{
public string name { get; set; }
public string upn { get; set; }
}
"