Azure B2C-使用msal获得调用图API的授权
我最近开始与B2C合作。我设法让他们使用MSAL和API与我自己的租户一起工作 现在我想:Azure B2C-使用msal获得调用图API的授权,azure,microsoft-graph-api,azure-ad-b2c,Azure,Microsoft Graph Api,Azure Ad B2c,我最近开始与B2C合作。我设法让他们使用MSAL和API与我自己的租户一起工作 现在我想: 了解如何在不使用API的情况下运行此示例。该示例使用作用域获取对API的读/写访问权。如果我从应用程序中删除对API的引用,它将不再工作。当然,应该有某种方法可以在不需要API的情况下对B2C进行身份验证?这对我的应用程序来说并不重要,但我最想知道的是,作为身份验证过程的一部分,Web服务是否必须存在 与Graph Api(Windows或Microsoft Graph?)通信。MS提供了ADAL和一些控
public partial class Startup
{
// App config settings
public static string ClientId = ConfigurationManager.AppSettings["ida:ClientId"];
public static string ClientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
public static string AadInstance = ConfigurationManager.AppSettings["ida:AadInstance"];
public static string Tenant = ConfigurationManager.AppSettings["ida:Tenant"];
public static string RedirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
public static string ServiceUrl = ConfigurationManager.AppSettings["api:TaskServiceUrl"];
public static string ApiIdentifier = ConfigurationManager.AppSettings["api:ApiIdentifier"];
public static string ReadTasksScope = ApiIdentifier + ConfigurationManager.AppSettings["api:ReadScope"];
public static string WriteTasksScope = ApiIdentifier + ConfigurationManager.AppSettings["api:WriteScope"];
public static string[] Scopes = new string[] { ReadTasksScope, WriteTasksScope };
// B2C policy identifiers
public static string SignUpSignInPolicyId = ConfigurationManager.AppSettings["ida:SignUpSignInPolicyId"];
public static string EditProfilePolicyId = ConfigurationManager.AppSettings["ida:EditProfilePolicyId"];
public static string ResetPasswordPolicyId = ConfigurationManager.AppSettings["ida:ResetPasswordPolicyId"];
public static string DefaultPolicy = SignUpSignInPolicyId;
// OWIN auth middleware constants
public const string ObjectIdElement = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
// Authorities
public static string Authority = String.Format(AadInstance, Tenant, DefaultPolicy);
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// Generate the metadata address using the tenant and policy information
MetadataAddress = String.Format(AadInstance, Tenant, DefaultPolicy),
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = ClientId,
RedirectUri = RedirectUri,
PostLogoutRedirectUri = RedirectUri,
// Specify the callbacks for each type of notifications
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
},
// Specify the claims to validate
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
},
// Specify the scope by appending all of the scopes requested into one string (seperated by a blank space)
Scope = $"{OpenIdConnectScopes.OpenId} {ReadTasksScope} {WriteTasksScope}"
}
);
}
/*
* On each call to Azure AD B2C, check if a policy (e.g. the profile edit or password reset policy) has been specified in the OWIN context.
* If so, use that policy when making the call. Also, don't request a code (since it won't be needed).
*/
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var policy = notification.OwinContext.Get<string>("Policy");
if (!string.IsNullOrEmpty(policy) && !policy.Equals(DefaultPolicy))
{
notification.ProtocolMessage.Scope = OpenIdConnectScopes.OpenId;
notification.ProtocolMessage.ResponseType = OpenIdConnectResponseTypes.IdToken;
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(), policy.ToLower());
}
return Task.FromResult(0);
}
/*
* Catch any failures received by the authentication middleware and handle appropriately
*/
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
// Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in policy"
if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))
{
// If the user clicked the reset password link, redirect to the reset password route
notification.Response.Redirect("/Account/ResetPassword");
}
else if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
}
return Task.FromResult(0);
}
/*
* Callback function when an authorization code is received
*/
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
// Extract the code from the response notification
var code = notification.Code;
string signedInUserID = notification.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(ClientId, Authority, RedirectUri, new ClientCredential(ClientSecret), userTokenCache, null);
try
{
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, Scopes);
}
catch (Exception ex)
{
//TODO: Handle
throw;
}
}
相关ID:01040e7b-846c-4f81-9a0f-ff515fd00398
时间戳:2018-01-30 10:55:37Z
AADB2C90068:提供的ID为“9cd938c6-d3ed-4146-aee5-a661cd7d984b”的应用程序对此服务无效。请使用通过B2C门户创建的应用程序,然后重试
的确,它没有通过B2C门户网站注册,但这是说明中所说的;在应用程序注册下的B2C租户中注册,而不是B2C门户
所有魔术发生的Startup类如下所示:
public partial class Startup
{
// App config settings
public static string ClientId = ConfigurationManager.AppSettings["ida:ClientId"];
public static string ClientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
public static string AadInstance = ConfigurationManager.AppSettings["ida:AadInstance"];
public static string Tenant = ConfigurationManager.AppSettings["ida:Tenant"];
public static string RedirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
public static string ServiceUrl = ConfigurationManager.AppSettings["api:TaskServiceUrl"];
public static string ApiIdentifier = ConfigurationManager.AppSettings["api:ApiIdentifier"];
public static string ReadTasksScope = ApiIdentifier + ConfigurationManager.AppSettings["api:ReadScope"];
public static string WriteTasksScope = ApiIdentifier + ConfigurationManager.AppSettings["api:WriteScope"];
public static string[] Scopes = new string[] { ReadTasksScope, WriteTasksScope };
// B2C policy identifiers
public static string SignUpSignInPolicyId = ConfigurationManager.AppSettings["ida:SignUpSignInPolicyId"];
public static string EditProfilePolicyId = ConfigurationManager.AppSettings["ida:EditProfilePolicyId"];
public static string ResetPasswordPolicyId = ConfigurationManager.AppSettings["ida:ResetPasswordPolicyId"];
public static string DefaultPolicy = SignUpSignInPolicyId;
// OWIN auth middleware constants
public const string ObjectIdElement = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
// Authorities
public static string Authority = String.Format(AadInstance, Tenant, DefaultPolicy);
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// Generate the metadata address using the tenant and policy information
MetadataAddress = String.Format(AadInstance, Tenant, DefaultPolicy),
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = ClientId,
RedirectUri = RedirectUri,
PostLogoutRedirectUri = RedirectUri,
// Specify the callbacks for each type of notifications
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
},
// Specify the claims to validate
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
},
// Specify the scope by appending all of the scopes requested into one string (seperated by a blank space)
Scope = $"{OpenIdConnectScopes.OpenId} {ReadTasksScope} {WriteTasksScope}"
}
);
}
/*
* On each call to Azure AD B2C, check if a policy (e.g. the profile edit or password reset policy) has been specified in the OWIN context.
* If so, use that policy when making the call. Also, don't request a code (since it won't be needed).
*/
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var policy = notification.OwinContext.Get<string>("Policy");
if (!string.IsNullOrEmpty(policy) && !policy.Equals(DefaultPolicy))
{
notification.ProtocolMessage.Scope = OpenIdConnectScopes.OpenId;
notification.ProtocolMessage.ResponseType = OpenIdConnectResponseTypes.IdToken;
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(), policy.ToLower());
}
return Task.FromResult(0);
}
/*
* Catch any failures received by the authentication middleware and handle appropriately
*/
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
// Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in policy"
if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))
{
// If the user clicked the reset password link, redirect to the reset password route
notification.Response.Redirect("/Account/ResetPassword");
}
else if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
}
return Task.FromResult(0);
}
/*
* Callback function when an authorization code is received
*/
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
// Extract the code from the response notification
var code = notification.Code;
string signedInUserID = notification.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(ClientId, Authority, RedirectUri, new ClientCredential(ClientSecret), userTokenCache, null);
try
{
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, Scopes);
}
catch (Exception ex)
{
//TODO: Handle
throw;
}
}
公共部分类启动
{
//应用程序配置设置
公共静态字符串ClientId=ConfigurationManager.AppSettings[“ida:ClientId”];
公共静态字符串ClientSecret=ConfigurationManager.AppSettings[“ida:ClientSecret”];
公共静态字符串AadInstance=ConfigurationManager.AppSettings[“ida:AadInstance”];
公共静态字符串Tenant=ConfigurationManager.AppSettings[“ida:Tenant”];
公共静态字符串RedirectUri=ConfigurationManager.AppSettings[“ida:RedirectUri”];
公共静态字符串ServiceUrl=ConfigurationManager.AppSettings[“api:TaskServiceUrl”];
公共静态字符串ApiIdentifier=ConfigurationManager.AppSettings[“api:ApiIdentifier”];
公共静态字符串readtaskscope=apidentifier+ConfigurationManager.AppSettings[“api:ReadScope”];
公共静态字符串WriteTaskScope=APIDENTIFIER+ConfigurationManager.AppSettings[“api:WriteScope”];
公共静态字符串[]范围=新字符串[]{ReadTasksScope,WriteTasksScope};
//B2C策略标识符
公共静态字符串signupsignnpolicyid=ConfigurationManager.AppSettings[“ida:signupsignnpolicyid”];
公共静态字符串EditProfilePolicyId=ConfigurationManager.AppSettings[“ida:EditProfilePolicyId”];
公共静态字符串ResetPasswordPolicyId=ConfigurationManager.AppSettings[“ida:ResetPasswordPolicyId”];
公共静态字符串DefaultPolicy=signupsignnpolicyid;
//OWIN身份验证中间件常量
public const字符串objectdelement=”http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
//当局
publicstaticstringauthority=string.Format(AadInstance、Tenant、DefaultPolicy);
public void ConfigureAuth(IAppBuilder应用程序)
{
app.UseCookieAuthentication(新的CookieAuthenticationOptions());
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseOpenIdConnectAuthentication(
新的OpenIdConnectAuthenticationOptions
{
//使用租户和策略信息生成元数据地址
MetadataAddress=String.Format(AadInstance、租户、DefaultPolicy),
//这些是标准的OpenID连接参数,其值来自web.config
ClientId=ClientId,
RedirectUri=RedirectUri,
PostLogoutRedirectUri=RedirectUri,
//为每种类型的通知指定回调
通知=新的OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider=OnRedirectToIdentityProvider,
AuthorizationCodeReceived=OnAuthorizationCodeReceived,
AuthenticationFailed=OnAuthenticationFailed,
},
//指定要验证的声明
TokenValidationParameters=新的TokenValidationParameters
{
NameClaimType=“name”
},
//通过将所有请求的作用域追加到一个字符串中(用空格分隔)来指定作用域
Scope=$“{OpenIdConnectScopes.OpenId}{readtaskscope}{writetaskscope}”
}
);
}
/*
*在每次调用Azure AD B2C时,检查是否在OWIN上下文中指定了策略(例如配置文件编辑或密码重置策略)。
*如果是这样,在打电话时使用该策略。另外,不要请求代码(因为不需要代码)。
*/
专用任务OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification通知)
{
var policy=notification.OwinContext.Get(“策略”);
如果(!string.IsNullOrEmpty(策略)和&!policy.Equals(DefaultPolicy))
{
notification.ProtocolMessage.Scope=OpenIdConnectScopes.OpenId;
notification.ProtocolMessage.ResponseType=OpenIDConnectResponseType.IdToken;
notification.ProtocolMessage.IssuerAddress=notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(),policy.ToLower());
}
返回Task.FromResult(0);
}
/*
*捕获身份验证中间件接收到的任何故障,并
https://login.microsoftonline.com/{tenant}/oauth2/token