当前位置: 首页 > 知识库问答 >
问题:

从blazor调用Api并传递身份验证令牌

那弘
2023-03-14

我有一个从https://github.com/Azure-Samples/ms-identity-blazor-wasm/tree/main/WebApp-graph-user/Call-MSGraph.创建的blazor网络组装项目

它基本上是您使用时创建的项目。用于Blazor应用程序的net core模板,该应用程序通过AD B2B进行身份验证

dotnet new blazorwasm -au SingleOrg --client-id "{CLIENT ID}" -o {APP NAME} --tenant-id "{TENANT ID}"

然后我能够调用graph。用户登录时的api。然后,我尝试使用该身份验证调用自己的Api,如中所述https://docs.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-3.1.

我用过

   builder.Services.AddHttpClient<ITestDataService, TestDataService>(
      client => client.BaseAddress = new Uri("https://localhost:44342/"))
        .AddHttpMessageHandler(x =>
        {
            var handler = x.GetRequiredService<AuthorizationMessageHandler>()
                .ConfigureHandler(new[] { "https://localhost:44342/" },
                    scopes: new[] { "https://graph.microsoft.com/User.Read" });

            return handler;
        });

我可以看到在调用Api时附加了令牌,但身份验证失败(401)。api是从用于B2B广告的Visual Studio模板生成的,并使用同样用于Blazor应用程序的配置。

这是它的启动。反恐精英

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
        .AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
    services.AddControllers();
}


        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseCors(policy =>
            policy.WithOrigins("http://localhost:5000", 
                "https://localhost:5001")
            .AllowAnyMethod()
            .WithHeaders(HeaderNames.ContentType,
                HeaderNames.Authorization,
                "x-custom-header")
            .AllowCredentials());

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

你知道少了什么吗?

完整的源代码可在githubhttps://github.com/mathiasfritsch/blazor-calls-api

共有1个答案

潘驰
2023-03-14

如果您想在一个blazor webassembly项目中调用Microsoft graph和自定义API,我们可以通过创建不同的HTTP客户端来调用不同的API来实现

例如

>

  • 注册服务器API应用程序

    1. 为服务器API应用程序注册AAD应用程序
    2. 公开API

    注册客户端应用

    1. 注册客户端应用程序
    2. 启用隐式授予流
    3. 添加API权限。(图形API权限和API应用权限)

    配置API应用程序

    请在启动中添加以下代码。cs

     public void ConfigureServices(IServiceCollection services)
     {
            JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
            services.AddCors(options =>
                {
                    options.AddDefaultPolicy(
                        builder => builder.AllowAnyOrigin()
                            .AllowAnyHeader()
                            .AllowAnyMethod());
                });
                   services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
                    .AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
    
                services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
                {
                    options.Authority += "/v2.0";
    
    
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        
                        ValidIssuers = new[] {
                          $"https://sts.windows.net/{Configuration["AzureAD:TenantId"]}/",
                          $"https://login.microsoftonline.com/{Configuration["AzureAD:TenantId"]}/v2.0"
    
                        },
                        RoleClaimType = "roles",
                        // The web API accepts as audiences both the Client ID (options.Audience) and api://{ClientID}.
                        ValidAudiences = new[]
                        {
                               options.Audience,
                               $"api://{options.Audience}"
                        }
    
                    };
    
                });
    ....
    }
      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                app.UseSwagger();
                app.UseSwaggerUI(c =>
                {
                    c.OAuthClientId(Configuration["Swagger:ClientId"]);
                    c.OAuthScopeSeparator(" ");
                    c.OAuthAppName("Protected Api");
    
                    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
                });
                app.UseHttpsRedirection();
    
                app.UseRouting();
                app.UseCors();
                app.UseAuthentication();
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }
    
    • 配置客户端APP
    1. 为图形API和自定义API创建自定义AuthorizationMessageHandler
    // custom API
    using Microsoft.AspNetCore.Components;
    using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
    
    public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
    {
        public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
            NavigationManager navigationManager)
            : base(provider, navigationManager)
        {
            ConfigureHandler(
                authorizedUrls: new[] { "https://localhost:44300/" },
                scopes: new[] { "the API app scope" });
        }
    }
    
    //Graph API
    using Microsoft.AspNetCore.Components;
    using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
    
    public class GraphAuthorizationMessageHandler : AuthorizationMessageHandler
    {
        public GraphAuthorizationMessageHandler(IAccessTokenProvider provider,
            NavigationManager navigationManager)
            : base(provider, navigationManager)
        {
            ConfigureHandler(
                authorizedUrls: new[] { "https://graph.microsoft.com/" },
                scopes: new[] { "https://graph.microsoft.com/User.Read" });
        }
    }
    
    public class Program
        {
            public static async Task Main(string[] args)
            {
                var builder = WebAssemblyHostBuilder.CreateDefault(args);
                builder.RootComponents.Add<App>("app");
    
                builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
                builder.Services.AddScoped<GraphAuthorizationMessageHandler>();
                // register HTTP client to call our own api
                builder.Services.AddHttpClient("MyAPI", client => client.BaseAddress = new Uri("https://localhost:44300/"))
                  .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
                // register HTTP client to call graph api
                builder.Services.AddHttpClient("GraphAPI", client => client.BaseAddress = new Uri("https://graph.microsoft.com/"))
                  .AddHttpMessageHandler<GraphAuthorizationMessageHandler>();
      
                builder.Services.AddMsalAuthentication(options =>
                {
                    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
                    options.ProviderOptions.DefaultAccessTokenScopes.Add("<the API app scope>");
                    options.ProviderOptions.AdditionalScopesToConsent.Add("https://graph.microsoft.com/User.Read");
                });
    
                await builder.Build().RunAsync();
            }
        }
    
    @inject IHttpClientFactory _clientFactory
    
    var httpClient = _clientFactory.CreateClient("<the client name you register>");
    await apiClient.GetStringAsync("path");
    

  •  类似资料:
    • 我是Swagger的新手。 我使用Swagger UI来生成Swagger文档。我有两个API调用。第一个调用是基于用户名和密码生成令牌。第二次调用需要第一次调用生成的令牌。 我如何使用Swagger UI设置第二次调用的令牌?

    • 我刚刚开始在.NET中开发我的第一个REST API。由于它将是无状态的,我将使用令牌进行身份验证: 基本思想(System.Security.Cryptography): null 检查凭据是否有效(用户名,将哈希密码与db值进行比较) 如果为真,则加密数据对象 对生成的令牌使用HMAC,并将其存储到数据库 将令牌(不带HMAC)返回给用户(cookie/字符串) 对需要身份验证的方法的请求:

    • null 我的自定义rest筛选器: 上面的内容实际上会导致应用程序启动时出现一个错误:有人能告诉我如何最好地执行此操作吗?pre_auth筛选器是执行此操作的最好方法吗? 编辑 使用Spring-security实现解决方案 希望它能帮助其他人…

    • 我有一个普通的ASP。NET Web应用程序,我使用应用程序服务将其部署到Azure中。在部署它之后,我启用了应用程序服务身份验证并配置了Azure Active Directory。这使我能够发布我的Web应用程序,并具有身份验证,因此只有属于Active Directory的人员才能登录。 另一方面,我部署了一个ASP。NET Web API作为云服务。Web应用程序应该加载一些信息,调用We

    • 我在laravel上有自己的登录概念。现在我想让它成为第三方登录解决方案。所以我必须了解很多事情。所以请告诉我 为什么我们总是在Get和Post方法的头上传递身份验证令牌? 为什么不在直接url(查询字符串)上? 这有什么优点和缺点?

    • 问题内容: 我正在开发一个RailsWeb应用程序,该应用程序还为移动设备提供了基于JSON的API。移动客户端应首先通过(电子邮件/通过)获得令牌,然后客户端将使用该令牌进行后续的API调用。 我对Devise相当陌生,我正在寻找一个Devise API外观,并希望它返回true / false,然后基于此,我将创建并返回令牌或返回拒绝消息。但似乎Devise没有提供类似的信息。 我知道Devi