Tengo algunos problemas para recuperar datos de sharepoint (Discos) para una aplicación central de dotnet. Por el momento, mi aplicación intenta usar la aplicación en sí, y no el usuario que inició sesión para recuperar discos, pero la forma preferida sería usar el accesstoken para el usuario conectado .

¿Quizás la autenticación como la aplicación con clientId y secret no funcionará con unidades en absoluto?

El inicio de sesión funciona bien.

He configurado una aplicación central de dotnet con el siguiente inicio:

 services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
                {
                    options.ExpireTimeSpan = TimeSpan.FromDays(30);
                })
                .AddAzureAD(options => Configuration.Bind("AzureAd", options));

También tengo los siguientes servicios registrados:

services.AddTransient<IAuthenticationProvider, GraphAuthenticationProvider>();
services.AddTransient<IGraphServiceClient, GraphServiceClient>();
services.AddTransient<IGraphProvider, MicrosoftGraphProvider>();

Donde uso esto para autenticar:

public class GraphAuthenticationProvider : IAuthenticationProvider
    {
        public const string GRAPH_URI = "https://graph.microsoft.com/";
        private string _tenantId { get; set; }
        private string _clientId { get; set; }
        private string _clientSecret { get; set; }

        public GraphAuthenticationProvider(IConfiguration configuration)
        {
            _tenantId = configuration.GetValue<string>("AzureAd:TenantId");
            _clientId = configuration.GetValue<string>("AzureAd:ClientId");
            _clientSecret = configuration.GetValue<string>("AzureAd:ClientSecret");
        }

        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            AuthenticationContext authContext = new AuthenticationContext($"https://login.microsoftonline.com/{_tenantId}");
            ClientCredential creds = new ClientCredential(_clientId, _clientSecret);

            //I have tried using acquireTokensAsync with scopes, but there is no such method.

            AuthenticationResult authResult = await authContext.AcquireTokenAsync(GRAPH_URI, creds);
            request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);
        }
    }

Le he dado a la aplicación muchos permisos en la configuración de API en el portal, principalmente porque no estoy seguro de lo que necesito, y por el momento estoy ansioso por hacer que funcione primero, luego refactorice algunos.

enter image description here

La aplicación puede iniciar sesión y recuperar los siguientes datos con el SDK:

var groups = await _graphServiceClient.Groups[appSettings.AzureAd.GroupId].Request().GetAsync();

Sin embargo: lo siguiente no funciona:

var groupDrives = await _graphServiceClient.Groups[appSettings.AzureAd.GroupId].Drives
                .Request()
                .GetAsync();

Y obtengo el siguiente error: Código: Mensaje de acceso denegado: ya sea scp o el reclamo de roles deben estar presentes en el token.

También tengo inicio de sesión de usuario en el inicio, y la aplicación no se usará sin iniciar sesión en azure AD: ¿podría usar accessToken para el usuario?

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
            {
                options.Authority = options.Authority + "/v2.0/";
                options.TokenValidationParameters = new TokenValidationParameters() { NameClaimType = "name" };
                options.TokenValidationParameters.ValidateIssuer = false;

                options.Events = new OpenIdConnectEvents
                {
                    OnTokenValidated = async ctx =>
                    {
                        var roleGroups = new Dictionary<string, string>();
                        Configuration.Bind("AuthorizationGroups", roleGroups);

                        var clientApp = ConfidentialClientApplicationBuilder
                            .Create(Configuration["AzureAD:ClientId"])
                            .WithTenantId(Configuration["AzureAD:TenantId"])
                            .WithClientSecret(Configuration["AzureAD:ClientSecret"])
                            .Build();

                        var authResult = await clientApp
                            .AcquireTokenOnBehalfOf(new[] { "User.Read", "Group.Read.All" }, new UserAssertion(ctx.SecurityToken.RawData))
                            .ExecuteAsync();

                        var graphClient = new GraphServiceClient(
                            "https://graph.microsoft.com/v1.0",
                            new DelegateAuthenticationProvider(async (requestMessage) =>
                            {
                                requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authResult.AccessToken);
                            }));

                       
                        //Could i register the graphservice as a singelton with the users accesstoken?
                        //Fetching drives here with the accessToken from user works. 

                        var graphService = new GraphService(graphClient, Configuration);
                        var memberGroups = await graphService.CheckMemberGroupsAsync(roleGroups.Keys);
                        var claims = memberGroups.Select(groupGuid => new Claim(ClaimTypes.Role, roleGroups[groupGuid]));
                        var appIdentity = new ClaimsIdentity(claims);
                        ctx.Principal.AddIdentity(appIdentity);

                    }
                };
            });

En realidad, me gustaría usar el acceso a los usuarios para recuperar las unidades, etc., pero no estoy seguro de cómo almacenar \ reutilizar el acceso. ¿Probablemente debería registrar el servicio como un singelton con el token de acceso de los usuarios como se menciona en el comentario?

Seguí esta guía, y tiene las mismas clases \ servicios que he usado: http://www.keithmsmith.com / get-begin-microsoft-graph-api-calls-net-core-3 /

De hecho, pensé que la opción en la parte superior aquí era solo un encabezado. Ahora podría ser más fácil ... https://i.imgur.com/yfZWaoe.png

0
sindrem 24 jun. 2020 a las 13:07

2 respuestas

La mejor respuesta

Parece que estás mezclando un montón de conceptos aquí. ese ejemplo que está utilizando se basa en el flujo de credenciales del cliente. probablemente debería comenzar leyendo sobre los diferentes tipos de flujos de autenticación disponibles. https://docs.microsoft.com/ es-es / azure / directorio-activo / desarrollo / msal-autenticación-flujos

  1. En general, cuando usa el flujo de credenciales del cliente, los permisos que necesita establecer son los permisos de la aplicación en la hoja de permisos de la API. Los permisos delegados son para flujos de inicio de sesión de usuario.

  2. cuando está utilizando permisos delegados como el anterior. y usa un flujo que obtiene tokens de usuario, entonces el acceso que tiene la aplicación se basa en el acceso que tiene el usuario. por ejemplo, si delega grupos.read.all con permisos delegados, eso le da a la aplicación acceso para leer todos los grupos que Ese usuario específico tiene acceso . no le da acceso a la aplicación a todos los grupos. si esto es lo que quieres, entonces utiliza el flujo de usuario.

No mencionó si estaba escribiendo una aplicación web, o qué, pero si es así, es posible que desee mirar cuidadosamente el flujo en nombre de. Aquí hay un ejemplo de ello. https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/2-WebApp-graph-user/2-1-Call-MSGraph

Pero nuevamente se aplica a los permisos, cuando obtiene un token de usuario, su aplicación solo tendrá acceso a los elementos a los que tiene acceso el usuario. no más. por ejemplo, el usuario A tiene acceso al sitio sharepoint A, el usuario B no tiene acceso al sitio A, cuando utiliza un token de usuario para que el usuario B llame al gráfico, no devolverá resultados para el sitio A ya que el usuario B no tiene acceso al mismo.

1
alphaz18 25 jun. 2020 a las 03:17

Ha definido ámbitos delegados pero está intentando autenticarse utilizando las credenciales del cliente. Los ámbitos delegados se denominan así porque el usuario está delegando su acceso a su aplicación.

Debe solicitar los ámbitos de aplicación cuando autentique sin un usuario.

1
Marc LaFleur 24 jun. 2020 a las 20:04