我正在领导一个由azure函数开发人员组成的庞大团队。因此,Microsoft使用azure Web界面引用的大多数示例都不适用于我。我正在使用模拟器在本地开发Azure功能以节省一些成本。我通过visual studio将我的所有功能发布到我的集成环境中。
我正在开发一堆azure函数,需要api网关来使用Azure AD B2C处理身份验证工作流。现在,我没有本地运行的api网关模拟器或Azure AD B2C模拟器。我的身份验证工作流程涉及拦截对api的请求,将它们重定向到AD B2C进行身份验证,然后将auth-token添加到http标头,然后调用http触发的azure函数。
现在,问题变成了,如何测试身份验证工作流程? 如何设置api网关将我在Visual Studio中本地运行的函数注册为云端api网关的api端点?
答案 0 :(得分:7)
如果您正在开发通过Easy Auth使用Azure-AD或Azure B2C的SPA,这是另一种选择,它将为您执行JWT令牌验证并让您执行以下操作:
您的SPA甚至将在本地获得令牌,因此请执行以下操作:
这是一些从标头中提取JWT令牌的示例代码(将HttpRequest注入到每个函数中):
private JwtSecurityToken ReadJwtTokenFromHeader(HttpRequest req)
{
if (req.Headers.ContainsKey("Authorization"))
{
var authHeader = req.Headers["Authorization"];
var headerValue = AuthenticationHeaderValue.Parse(authHeader);
var handler = new JwtSecurityTokenHandler();
return handler.ReadJwtToken(headerValue.Parameter);
}
return null;
}
注意:这要求System.IdentityModel.Tokens.Jwt NuGet包使用JwtSecurityTokenHandler。
答案 1 :(得分:2)
在@ David-Yates的回答下,我在本地运行时替换了Principal
module Debug = begin
open System.IdentityModel.Tokens.Jwt
open System.Net.Http.Headers
open System.Security.Claims
let setPrincipalFromBearerToken (log : ILogger) (req : HttpRequest) =
log.LogInformation ("Reading Authorization header")
let success, authHeader = req.Headers.TryGetValue("Authorization")
if not success
then log.LogWarning ("Authorization header missing")
else
match Seq.tryExactlyOne authHeader with
| None -> log.LogWarning ("Authorization header has 0 or more than 1 value")
| Some headerValue ->
let headerValue = AuthenticationHeaderValue.Parse(headerValue);
log.LogInformation ("Authorization header succesfully parsed")
let handler = new JwtSecurityTokenHandler();
let token = handler.ReadJwtToken(headerValue.Parameter);
log.LogInformation ("JWT succesfully parsed")
let identity =
ClaimsIdentity(
req.HttpContext.User.Identity,
token.Claims)//,
//Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme),
//"oid", "roles")
let principal = ClaimsPrincipal(identity)
req.HttpContext.User <- principal
let userIdClaim =
principal.Claims
|> Seq.where (fun c -> c.Type = "oid") // TODO: Use const from MS package if possible
|> Seq.head
log.LogInformation ("Principal succesfully updated, user ID '{0}'", userIdClaim.Value)
end
let isLocal = String.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID"))
if isLocal then Debug.setPrincipalFromBearerToken log req
答案 2 :(得分:1)
我做了什么:
优点: