本章全是干货干货干货,重要的事情说三遍。

最近在研究Azure, Cloud相关的东西,项目中用的是Graph API(这个在下一章会相信介绍),可能是Graph API推出的时间比较晚,部分API还在开发中,所以难免出现部分功能支持不完善,issue之类的,当然Microsoft也在不断更新完善中,期待Graph API时代的到来。

针对以上的问题,有时在项目中不得不采取一些非常规的手段,调用Microsoft backend API,什么是backend API呢,就是我们用Fiddle监控或者页面F12 Network 看到Microsoft调用的底层Rest API。

例如:Azure AD的Company Branding功能,Graph V 1.0版本没有API支持,但项目需要,怎么办?

1)、是查找是否有Beta版本,如果有,项目组决定是否可以使用Beta API ,因为Microsoft 官网是不建议Beta API应用于生产环境的。

https://docs.microsoft.com/en-us/graph/api/resources/organizationalbrandingproperties?view=graph-rest-beta

2)、就是我们今天说的重点,调用Microsoft backend API

首先说明一下啊,所有获取token的token endpoint都是统一地址

private string _tokenEndpoint = "https://login.microsoftonline.com/common/oauth2/token";

1、 Backend API Access Token

调用backend api,重点是获取access token,这里是impersonate user login(模拟用户登录的方式)。

private async Task<string> GetAADAccessToken(string username, string password)
{
var resource = $"resource=74658136-14ec-4630-ad9b-26e160ff0fc6&client_id=1950a258-227b-4e31-a9cf-717495945fc2&grant_type=password&username={username}&password={password}";
return await GetAccessToken(resource);
} private async Task<string> GetAccessToken(string resource)
{
var httpClient = new HttpClient();
using (var stringContent = new StringContent(resource, Encoding.UTF8, "application/x-www-form-urlencoded"))
{
try
{
var result = await httpClient.PostAsync(_tokenEndpoint, stringContent).ContinueWith((response) =>
{
return response.Result.Content.ReadAsStringAsync().Result;
}).ConfigureAwait(false); var tokenResult = JsonSerializer.Deserialize<JsonElement>(result);
var token = tokenResult.GetProperty("access_token").GetString();
return token;
}
catch (Exception ex)
{
throw new TokenException(ErrorCode.BadRequest, ex.Message);
}
}
}

解释一下哈:

“1950a258-227b-4e31-a9cf-717495945fc2” 是Microsoft build-in的application Id,

“74658136-14ec-4630-ad9b-26e160ff0fc6” 是token的颁发地址

以上两个ID是固定值,直接使用就可以。

获取到了access  token,接下需要构建HTTP Client:

private HttpClient BuildHttpClient(string accessToken)
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
httpClient.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
httpClient.DefaultRequestHeaders.Add("x-ms-client-request-id", $"{new Guid()}");
httpClient.DefaultRequestHeaders.Add("x-ms-correlation-id", $"{new Guid()}");
return httpClient;
}

最后发送HTTP请求,获取数据信息:

private static IEnumerable<CompanyBrandingModel> GetCompanyBrandings()
{
var services = new ServiceCollection();
var provider = services.ConfigureServices().BuildServiceProvider();
var httpClientService = provider.GetService<IHttpClientService>();
var httpClient = httpClientService?.GetHttpClient(_username, _password, TokenType.AzureAD, _clientId).GetAwaiter().GetResult(); var requestUrl = "https://main.iam.ad.ext.azure.com/api/LoginTenantBrandings";
var response = httpClient?.GetAsync(requestUrl).GetAwaiter().GetResult();
var content = response?.Content.ReadAsStringAsync().Result;
var brandings = JsonConvert.DeserializeObject<List<CompanyBrandingModel>>(content)
.Where(b => b.isConfigured.HasValue && b.isConfigured.Value);
return brandings; }

获取的结果和页面一致,证明backend API还是可行的,哈哈。

 2、Graph Token

Graph API官网为我们提供了多种方式使用Graph API:

1、通过Nuget 安装Graph SDK,调用Graph SDK

构建GraphServiceClient对象,这里提供了2种方式,Delegated 和 Application,Application又分Secret 和 Certification,我们这里只介绍Application Secret。

 public GraphServiceClient GetGraphServiceClientByApp(string tenantId, string clientId, string clientSecret)
{
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
var credentialProvider = new ClientCredentialProvider(confidentialClientApplication);
var graphClient = new GraphServiceClient(credentialProvider);
return graphClient;
}

2、调用Graph Rest API,首先需要获取Graph access token,示例代码如下:

public async Task<string> GetAppAccessToken(string clientId, string clientSecret)
{
     if (string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(clientSecret))
     {
       throw new TokenException(ErrorCode.InvalidArguments, ExceptionConstants.NullOrEmpty);
     }
     var resource = $"scope=https://graph.microsoft.com/.default&grant_type=client_credentials&client_id={clientId}&client_secret={clientSecret}";
     return await GetAccessToken(resource);
}

有了access token之后,就可以构建http client,发送http请求了,同上,这里就不在累述了,说多了都是废话,标题就是干货干货干货

 3、SharePoint access token

操作SharePoint的API有好多种,这里咱们只说Asp.NET Core CSOM, .NET Framework比较简单,这里就不多说了,想了解的下方留言吧。

首先获取SharePoint access token,直接干代码:

private async Task<string> GetSPAccessToken(string username, string password, string clientId)
{
var spAdminUrl = $"https://{username.Substring(username.IndexOf("@") + 1, username.IndexOf(".") - username.IndexOf("@") - 1)}-admin.sharepoint.com/";
try
{
var uri = new Uri(spAdminUrl);
string _resource = $"{uri.Scheme}://{uri.DnsSafeHost}";
var resource = $"resource={_resource}&client_id={clientId}&grant_type=password&username={HttpUtility.UrlEncode(username)}&password={HttpUtility.UrlEncode(password)}";
return await GetAccessToken(resource);
}
catch (System.UriFormatException e)
{
throw new UriFormatException(e.Message, e);
}
}

拿到token之后,通过Nuget安装package,构建ClientContext对象:

public class SPClientContextService
{
private readonly ITokenCacheService _tokenCacheService; public SPClientContextService(ITokenCacheService tokenCacheService)
{
this._tokenCacheService = tokenCacheService;
} public async Task<ClientContext> GetSPClientContextInstance(string username, string password, string clientId)
{
var accessToken = await _tokenCacheService.TryGetValue(username, password, TokenType.SharePoint, clientId);
var spAdminUrl = $"https://{username.Substring(username.IndexOf("@") + 1, username.IndexOf(".") - username.IndexOf("@") - 1)}-admin.sharepoint.com/";
var context = new ClientContext(new Uri(spAdminUrl));
context.ExecutingWebRequest += (sender, e) =>
{
e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + accessToken;
};
return context;
}
}

OK,篇幅已经比较长了,如需了解更多,请在下方留言,源码请参见Github。

Azure AD, Endpoint Manger(Intune), SharePoint access token 的获取的更多相关文章

  1. IdentityServer4专题之四:Authorization Endpoint、Token Endpoint、scope、Access Token和Refresh Token、授权服务器发生错误

    1.Authorization Endpoint 它是与用户交互的端点,用户在此进行为客户端应用授权的操作,即authorization grant 2.Token Endpoint 端点,就是一个w ...

  2. 微信公众平台开发视频教程-03-获取Access Token和获取微信服务器IP,添加微信菜单

    1 获取access token 此token是以后每次调用微信接口都会带上的票据,token是公众号全局唯一票据,在调用其他接口之前都需要先得到token,taoken长度至少512个字符,通常用s ...

  3. 【Azure Developer】如何验证 Azure AD的JWT Token (JSON Web 令牌)?

    问题描述 使用微软Azure AD,对授权进行管理.通过所注册应用的OAuth API(https://login.chinacloudapi.cn/{TENANT ID}/oauth2/v2.0/t ...

  4. Laravel Cache 缓存钉钉微应用的 Access Token

    钉钉微应用的 Access token 如何获取? Access_Token 是企业访问钉钉开放平台全局接口的唯一凭证,即调用接口时需携带Access_Token.从接口列表看,所有接口都需要携带 a ...

  5. Access Token 机制详解

    我们在访问很多大公司的开放 api 的时候,都会发现这些 api 要求传递一个 access token 参数.这个参数是什么呢?需要去哪里获取这个 access token 呢? access to ...

  6. 【Azure Developer】【Python 】使用 azure.identity 和 azure.common.credentials 获取Azure AD的Access Token的两种方式

    问题描述 使用Python代码,展示如何从Azure AD 中获取目标资源的 Access Token. 如要了解如何从AAD中获取 client id,client secret,tenant id ...

  7. SharePoint Online 使用 adal js 获取access token

    最近在写一些SharePoint 的sample code, 有兴趣的小伙伴可以查看我的GitHub. 今天给大家介绍SharePoint Framework (SPFx  )web part 当中怎 ...

  8. 【Azure Developer】使用Postman获取Azure AD中注册应用程序的授权Token,及为Azure REST API设置Authorization

    Azure Active Directory (Azure AD) is Microsoft's cloud-based identity and access management service, ...

  9. 【Azure Developer】Python 获取Micrisoft Graph API资源的Access Token, 并调用Microsoft Graph API servicePrincipals接口获取应用ID

    问题描述 在Azure开发中,我们时常面临获取Authorization问题,需要使用代码获取到Access Token后,在调用对应的API,如servicePrincipals接口. 如果是直接调 ...

随机推荐

  1. 洛谷 P4143 采集矿石 后缀数组

    题目背景 ZRQ 成功从坍塌的洞穴中逃了出来.终于,他看到了要研究的矿石.他想挑一些带回去完成任务. 题目来源:Zhang_RQ哦对了 \(ZRQ\) 就他,嗯 题目描述 ZRQ 发现这里有 \(N\ ...

  2. IDE - vscode

    [一]VSCODE官方插件库 https://marketplace.visualstudio.com/ 最好能在文件->首选项->设置中,搜索update,将Auto Update关闭, ...

  3. LINUX - 随机数

    #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h& ...

  4. js & document.designMode

    js & document.designMode js 一键开启页面编辑模式 var mode = document.designMode; document.designMode = val ...

  5. 如何使用 js 写一个正常人看不懂的无聊代码

    如何使用 js 写一个正常人看不懂的无聊代码 代码质量, 代码可读性, 代码可维护性, clean code WAT js WTF https://www.destroyallsoftware.com ...

  6. 微信小程序-生命周期图解

    微信小程序-生命周期图解 小程序生命周期 App 生命周期 https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.htm ...

  7. Webpack 4.x 默认支持 ES6 语法

    Webpack 4.x 默认支持 ES6 语法 Q: 为什么 webpack4 默认支持 ES6 语法的压缩? A: terser 里面实现了 ES6 语法的 AST解析. webpack 4 里使用 ...

  8. p5.js

    p5.js p5.j​​s是一个用于创意编码的JavaScript库,其重点是使艺术家,设计师,教育者,初学者以及其他任何人都可以访问并包含所有编码! https://p5js.org/ https: ...

  9. taro H5

    taro H5 开发指南 https://nervjs.github.io/taro/docs/GETTING-STARTED.html#h5 taro # build $ taro build -- ...

  10. 在线预览word,excel,ppt

    https://view.officeapps.live.com/op/view.aspx?src=服务器地址微软提供的地址拼接自己的可以预览了拼接自己的服务器地址可以在线预览