使用 OpenId 从 Web App 调用 Web API 时无法使用授权标签

问题描述 投票:0回答:1

我正在使用 OpenId 从我的 Web 应用程序中的 Azure AD 进行身份验证,并尝试在我的 Web API 中进行授权。

我可以从 Web App (.NET 4.8) 访问我的 WebAPI (.NET Framework 6.0),没有任何问题。然而,当尝试在我的 WebAPI 控制器中使用授权标签时,我热衷于收到内部错误。

Web 应用程序 - Startup.cs

    private static string _clientId = Properties.Resource.ClientId;
    private static string _aadInstance = EnsureTrailingSlash(Properties.Resource.AADInstance);
    private static string _tenantId = Properties.Resource.TenantId;
    private static string _RedirectUri = Properties.Resource.RedirectUri;
    private static string _clientSecret = Properties.Resource.ClientSecret;
    private string _authority = _aadInstance + _tenantId;
    private string _scope = Properties.Resource.Scope;
    
    public void ConfigureAuth(IAppBuilder app)
    {
        //Set the authentication to cookies
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
    
        //Create a new cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
    
        //Set the openId connect authentication settings and call the WebPortal app in Azure
        app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            ClientId = _clientId,
            Authority = _authority,
            RedirectUri = _RedirectUri,
            PostLogoutRedirectUri = _RedirectUri,
            ClientSecret = _clientSecret,
            UseTokenLifetime = false,
            SaveTokens = true,
            RedeemCode = true,
            Scope = _scope,
            ResponseType = OpenIdConnectResponseType.Code,
            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                AuthenticationFailed = (context) =>
                {
                    return Task.FromResult(0);
                }
            }
        });
    
        app.UseStageMarker(PipelineStage.Authenticate);
    }

Web Api 代码 - Program.cs

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(options =>{options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;options.DefaultChallengeScheme = "oidc";}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme).AddOpenIdConnect(openIdOptions =>{openIdOptions.ClientId = "7221484D-1550-4087-840D-7170BC566B93";openIdOptions.Authority = "https://login.microsoftonline.com/4c2ecc82-c268-467a-bb63-0e92247d5fab";openIdOptions.ResponseType = OpenIdConnectResponseType.Code;openIdOptions.GetClaimsFromUserInfoEndpoint = false;openIdOptions.CallbackPath = "/signin-oidc";openIdOptions.SaveTokens = true;openIdOptions.ClientSecret = "****";});

builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();
var app = builder.Build();

// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();}
app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

app.Run();

Web Api 控制器 - 授权不起作用的地方

[Authorize]
[HttpGet("GetRoleInfo")]
public async Task<IActionResult> GetRoleInfo()
{
    try
    {
        string userId = GetAzureUserId();

        List<Role> roles = await GetRoles();
        List<AdminRole> adminRoles = await GetAdminRoles();
        List<BusinessUser> businessUsers = await GetBusinessUsers();
        List<ApplicationUser> applicationUsers = await GetApplicationUsers();
        List<Application> applications = await GetApplications();

        var roleAdminModel = PopulateRoleInfo(userId, roles, adminRoles,   
        businessUsers,applicationUsers, applications);

        return Ok(roleAdminModel);

    }
    catch (Exception ex)
    {
        return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message);
    }
}

我遇到错误

c# asp.net openid webapi
1个回答
0
投票

网络应用程序.NET 4.8。

我无法获取 OpenId 来获取 Azure AD 中的自定义范围,因此无法获取 Web API 进行授权。因此我现在使用 Microsoft.Identity.Client。您可以从 Nuget 包管理器获取此信息。

我的 Login.cs 页面中有以下代码。

代码流程login.cs页面 -> AuthenticateProcess -> PopulateRoleInfo -> GetHttpResponseType -> Web API

using Microsoft.Identity.Client;

public partial class Login : Page
{

    private void AuthenticateProcess()
    {

        //Get the access token from Azure
        Task<string> accessToken = Task.Run(async () => await GetAccessToken());

        if (accessToken != null && accessToken.Result != null && accessToken.Result.Count() > 0)
        {
            Task<List<RoleAdminRoleModel>> roleAdminRoleModel = Task.Run(() => PopulateRoleInfo(accessToken.Result));

        }
    }

    private async Task<string> GetAccessToken()
    {
        string accessToken = string.Empty;
        try
        {
            string[] Graphscopes = new string[] { Resource.Scope };
            var clientApp = PublicClientApplicationBuilder.Create(Resource.ClientId)
            .WithAuthority($"{Resource.AADInstance}{Resource.TenantId}")
            .WithDefaultRedirectUri()
            .Build();

            var azureAccounts = await clientApp.GetAccountsAsync();
            var azureAccount = azureAccounts.FirstOrDefault();
            var authResult = await clientApp
            .AcquireTokenInteractive(Graphscopes)?
            .WithAccount(azureAccount)?
            .ExecuteAsync();

            if (authResult != null
            {
                accessToken = authResult.AccessToken;
            }
        }
        catch (Exception ex)
        {
            Response.Redirect(Resource.ErrorPage + " " + ex.Message);
        }
        return accessToken;
    }

    private async Task<List<RoleAdminRoleModel>> PopulateRoleInfo(string accessToken)
    {
        var webPortalAPIAccess = new WebPortalAPIAccess(accessToken);

        List<RoleAdminRoleModel> roleAdminRoleModel = await webPortalAPIAccess.GetRoleInfo();

        return roleAdminRoleModel;
    }

    public async Task<List<RoleAdminRoleModel>> GetRoleInfo()
    {
        var roleAdminRoleModel = await GetHttpResponseType<List<RoleAdminRoleModel>>($"{_webPortalPublicAPIPath}/api/WebPortal/GetRoleInfo");

        return roleAdminRoleModel;
    }

    private async Task<T> GetHttpResponseType<T>(string url)
    {
        var options = new System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = true };
        var stream = await _httpClient.GetStreamAsync(url);
        var instance = await DeserializeAsync<T>(stream, options);
        return instance;
    }
}

然后像这样设置 Web API -> Program.cs。

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;


var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
        .EnableTokenAcquisitionToCallDownstreamApi()
            .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))           
            .AddInMemoryTokenCaches();

builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();


app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

app.Run();

现在设置 Web API 控制器。请注意授权和范围标签。控制器顶部是按键。范围标记是指 Azure AD 中的自定义范围设置。您可以出于测试目的手动输入此值,而不是从 appsettings.json 文件引用范围(“MicrosoftGraph:Scopes”)。

using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Net;
using Models;
using System.Data;
using Application = Models.Application;
using RolePermission = Models.RolePermission;
using Permission = Models.Permission;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Identity.Web;

[Authorize]
[AuthorizeForScopes(ScopeKeySection = "MicrosoftGraph:Scopes")]
[ApiController]
[Route("api/[controller]")]
public class WebPortalController : Controller
{

    [HttpGet("GetRoleInfo")]
    public async Task<IActionResult> GetRoleInfo()
    {
        try
        {
            string userId = GetAzureUserId();
            List<Role> roles = await GetRoles();
            List<AdminRole> adminRoles = await GetAdminRoles();
            List<BusinessUser> businessUsers = await GetBusinessUsers();
            List<ApplicationUser> applicationUsers = await GetApplicationUsers();
            List<Application> applications = await GetApplications();

            var roleAdminModel = PopulateRoleInfo(userId, roles, adminRoles, businessUsers, applicationUsers, applications);

            return Ok(roleAdminModel);
        }
        catch (Exception ex)
        {
            return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.