Как использовать Microsoft Graph API с сертификатами (INTUNE) - PullRequest
1 голос
/ 17 апреля 2020

C# код для доступа к API MS GRAPH (В ЭТОМ СЛУЧАЕ INTUNE) и использования сертификатов для аутентификации. Это основано на статье, которую можно найти здесь: https://laurakokkarinen.com/authenticating-to-office-365-apis-with-a-certificate-step-by-step/comment-page-2/#comment -697

Первый - это скрипт powershell для генерации сертификата. Тогда есть интерфейс регистратора и конфигуратор для чтения из файла JSON. Вследствие этого существует ЧИТАТЕЛЬ, использующий асинхронные вызовы для аутентификации с помощью API и получения взамен токена.

# Run this script as an administrator
# --- config start
$dnsName = "mytenant.sharepoint.com" # Your DNS name
$password = "F1exera!" # Certificate password
$folderPath = "C:\InTuneCertificate" # Where do you want the files to get saved to? The folder needs to exist.
$fileName = "InTune" # What do you want to call the cert files? without the file extension
$yearsValid = 10 # Number of years until you need to renew the certificate
# --- config end
$certStoreLocation = "cert:\LocalMachine\My"
$expirationDate = (Get-Date).AddYears($yearsValid)

$certificate = New-SelfSignedCertificate -DnsName $dnsName -CertStoreLocation $certStoreLocation -NotAfter $expirationDate -KeyExportPolicy Exportable -KeySpec Signature

$certificatePath = $certStoreLocation + '\' + $certificate.Thumbprint
$filePath = $folderPath + '\' + $fileName
$securePassword = ConvertTo-SecureString -String $password -Force -AsPlainText
Export-Certificate -Cert $certificatePath -FilePath ($filePath + '.cer')

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

    namespace universalExtractor
    {
        // Configurator

        interface Iconfigurator
        {
            void getAuthentication();               // get credentials
            //void getEndpoints();                    // get endpoints    
            void run(); // interface method (does not have a body)
        }

        class configurator : Iconfigurator
        {
            public string authorizationEndpoint;
            public string TokenEndpoint;
            public string ClientID;
            public string Certificate;
            public string RedirectUrl;
            public string proxyServer;
            public string proxyUsername;
            public string proxyPassword;
            public string TenantID;

            /*public void getAuthentication()
            {

            }*/
            public void getAuthentication()
            {
                string text = System.IO.File.ReadAllText("extractorConfig.json");
                JsonTextReader reader = new JsonTextReader(new StringReader(text));
                while (reader.Read())
                {
                    if (reader.Value != null)
                    {                   

                        //Console.WriteLine("Token: {0}, Value: {1}", reader.TokenType, reader.Value);
                        switch (reader.Path)
                        {
                            case "authorizationEndpoint":
                                authorizationEndpoint = reader.Value.ToString();
                                break;
                            case "TokenEndpoint":
                                TokenEndpoint = reader.Value.ToString();
                                break;
                            case "ClientID":
                                ClientID = reader.Value.ToString();
                                break;
                            case "Certificate":
                                Certificate = reader.Value.ToString();
                                break;
                            case "TenantID":
                                TenantID = reader.Value.ToString();
                                break;
                            case "RedirectUrl":
                                RedirectUrl = reader.Value.ToString();
                                break;
                            case "proxyServer":
                                proxyServer = reader.Value.ToString();
                                break;
                            case "proxyUsername":
                                proxyUsername = reader.Value.ToString();
                                break;
                            default:
                                //Console.WriteLine("Default case");
                                break;
                        }
                    }
                    /*else
                    {
                        Console.WriteLine("Token: {0}", reader.TokenType);
                    }*/
                }

            }

        public void run()
        {

        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace universalExtractor
{
    //Logger

    interface Ilogger
    {
        void write(String logMessage,  String typeMessage);                 // endpoint type
    }

    class logger : Ilogger
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public void write(String logMessage,String typeMessage)
        {
            switch (typeMessage)
            {
                case "Info":
                    log.Info(logMessage);
                    break;
                case "Warn":
                    log.Warn(logMessage);
                    break;
                case "Error":
                    log.Error(logMessage);
                    break;
                default:
                    //Console.WriteLine("Default case");
                    break;
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace universalExtractor
{
    interface Ireader
    {
        void authenticate();
        void buildRequest();                    // most typically REST request
        void mapToInputMap();                   // store result into array
    }
    class reader : Ireader
    {
        public void authenticate()
        {

        }

        public void buildRequest()
        {

        }
        public void mapToInputMap()
        {

        }
    }
}

using System;

using Microsoft.Graph;
using Microsoft.Identity.Client;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using ClientAssertionCertificate = Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate;

namespace universalExtractor
{
    class InTuneReader : reader
    {
        private string token;
        private string url = "https://graph.microsoft.com";

        public string authenticate(string tenantId, string clientId, string certificateThumbprint, string debugCertificatePath = null, string debugCertificatePassword = null)
        {
            Authorization auth = new Authorization(tenantId, clientId, certificateThumbprint, debugCertificatePath, debugCertificatePassword);
            Task<string> token = auth.GetAccessTokenAsync(url);

            return (token.ToString());
        }
     }
    public class Authorization
    {
        private readonly string _tenantId;
        private readonly string _clientId;
        private readonly string _certificateThumbprint;
        private readonly string _debugCertificatePath;
        private readonly string _debugCertificatePassword;
        logger log = new logger();

        public Authorization(string tenantId, string clientId, string certificateThumbprint, string debugCertificatePath = null, string debugCertificatePassword = null)
        {
            _tenantId = tenantId;
            _clientId = clientId;
            _certificateThumbprint = certificateThumbprint;
            _debugCertificatePath = debugCertificatePath;
            _debugCertificatePassword = debugCertificatePassword;
        }
        public async Task<string> GetAccessTokenAsync(string url)
        {
            url = GetTenantUrl(url);
            try
            {
                var authContext = new AuthenticationContext($"https://login.microsoftonline.com/{_tenantId}/oauth2/token"); // you can also use the v2.0 endpoint URL
                return (await authContext.AcquireTokenAsync(url, GetCertificate(_clientId, _certificateThumbprint))).AccessToken;
            }
            catch(Exception e)
            {
                log.write(e.ToString(), "Info");
                return null;
            }

        }
        private static string GetTenantUrl(string url)
        {
            const string suffix = "sharepoint.com";
            var index = url.IndexOf(suffix, StringComparison.OrdinalIgnoreCase);
            return index != -1 ? url.Substring(0, index + suffix.Length) : url;
        }
        private ClientAssertionCertificate GetCertificate(string clientId, string thumbprint)
        {
            var certificate = Debugger.IsAttached ? GetCertificateFromDirectory(_debugCertificatePath, _debugCertificatePassword) : GetCertificateFromStore(thumbprint);
            return new ClientAssertionCertificate(clientId, certificate);
        }
        private static X509Certificate2 GetCertificateFromDirectory(string path, string password)
        {
            return new X509Certificate2(System.IO.Path.GetFullPath(path), password, X509KeyStorageFlags.MachineKeySet);
        }
        private static X509Certificate2 GetCertificateFromStore(string thumbprint)
        {
            var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
            store.Close();
            return certificates[0];
        }
    }
}

JSON

{
  "authorizationEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
  "TokenEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
  "ClientID": "9870d-6d0f-4c-c4363504c",
  "RedirectUrl": "https://login.microsoftonline.com/common/oauth2/nativeclient",
  "proxyServer": "",
  "proxyUsername": "",
  "proxyPassword": ""
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;

namespace universalExtractor
{
    class Program
    {
        static void Main(string[] args)
        {

            logger log = new logger();

            configurator config = new configurator();
            InTuneReader reader = new InTuneReader();

            log.write("Get authentication from JSON file", "Info"); 
            config.getAuthentication();

            string configString = "Tenant ID " + config.TenantID + " ClientID " + config.ClientID + " Certificate ";
            log.write(configString, "Info");
            log.write("Authorization https://graph.microsoft.com ", "Info");
            string accessToken = reader.authenticate(config.TenantID, config.ClientID, config.Certificate, null, null);
            log.write("TOKEN", "Info");
            log.write(accessToken, "Info");

            //configurator config = new configurator();
            //config.getEndpoints();

            Console.WriteLine("Hit enter");
            Console.ReadLine();
            //inputObjectMap inputObjectMap = new inputObjectMap();
            //configurator.readXML(path, inputObjectMap);
        }
    }
}

1 Ответ

0 голосов
/ 17 апреля 2020

Хороший пример аутентификации MS GRAPH API с сертификатом

https://laurakokkarinen.com/authenticating-to-office-365-apis-with-a-certificate-step-by-step/comment-page-2/#comment -697

Этот пост расширяет эту статью ...


Microsoft Graph API (и MS InTune) содержит библиотеку REST. Пример моего кода ниже содержит приложение C#, которое использует сертификаты для аутентификации и расширяет пример в: https://laurakokkarinen.com/authenticating-to-office-365-apis-with-a-certificate-step-by-step/comment-page-2/#comment -697

...