mirror of
https://github.com/Microsoft/sql-server-samples.git
synced 2025-12-08 14:58:54 +00:00
137 lines
5.6 KiB
C#
137 lines
5.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Globalization;
|
|
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
|
using System.Net.Http;
|
|
using System.Threading;
|
|
using System.Net.Http.Headers;
|
|
using System.Web.Script.Serialization;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Configuration;
|
|
|
|
namespace ClinicService
|
|
{
|
|
class TokenFactory
|
|
{
|
|
//
|
|
// The Client ID is used by the application to uniquely identify itself to Azure AD.
|
|
// The Cert Name is the subject name of the certificate used to authenticate this application to Azure AD.
|
|
// The Tenant is the name of the Azure AD tenant in which this application is registered.
|
|
// The AAD Instance is the instance of Azure, for example public Azure or Azure China.
|
|
// The Authority is the sign-in URL of the tenant.
|
|
//
|
|
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
|
|
private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
|
|
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
|
|
private static string certName = ConfigurationManager.AppSettings["ida:CertName"];
|
|
|
|
static string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
|
|
|
|
//
|
|
// To authenticate to the To Do list service, the client needs to know the service's App ID URI.
|
|
// To contact the To Do list service we need it's URL as well.
|
|
//
|
|
private static string sqlDBResourceId = ConfigurationManager.AppSettings["sqldb:ResourceId"];
|
|
//private static string todoListBaseAddress = ConfigurationManager.AppSettings["todo:TodoListBaseAddress"];
|
|
|
|
private static HttpClient httpClient = new HttpClient();
|
|
private static AuthenticationContext authContext = null;
|
|
private static ClientAssertionCertificate certCred = null;
|
|
private static string token;
|
|
|
|
public static string GetAccessToken()
|
|
{
|
|
//
|
|
// Create the authentication context to be used to acquire tokens.
|
|
//
|
|
authContext = new AuthenticationContext(authority);
|
|
|
|
//
|
|
// Initialize the Certificate Credential to be used by ADAL.
|
|
// First find the matching certificate in the cert store.
|
|
//
|
|
|
|
X509Certificate2 cert = null;
|
|
X509Store store = new X509Store(StoreLocation.CurrentUser);
|
|
try
|
|
{
|
|
store.Open(OpenFlags.ReadOnly);
|
|
// Place all certificates in an X509Certificate2Collection object.
|
|
X509Certificate2Collection certCollection = store.Certificates;
|
|
// Find unexpired certificates.
|
|
X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
|
|
// From the collection of unexpired certificates, find the ones with the correct name.
|
|
X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, false);
|
|
if (signingCert.Count == 0)
|
|
{
|
|
throw new Exception("Cannot find certificate: " + certName);
|
|
}
|
|
// Return the first certificate in the collection, has the right name and is current.
|
|
cert = signingCert[0];
|
|
}
|
|
finally
|
|
{
|
|
store.Close();
|
|
}
|
|
|
|
// Then create the certificate credential.
|
|
certCred = new ClientAssertionCertificate(clientId, cert);
|
|
AcquireToken().Wait();
|
|
return token;
|
|
}
|
|
|
|
static async Task AcquireToken()
|
|
{
|
|
//
|
|
// Get an access token from Azure AD using client credentials.
|
|
// If the attempt to get a token fails because the server is unavailable, retry twice after 3 seconds each.
|
|
//
|
|
AuthenticationResult result = null;
|
|
int retryCount = 0;
|
|
bool retry = false;
|
|
token = null;
|
|
|
|
do
|
|
{
|
|
retry = false;
|
|
try
|
|
{
|
|
// ADAL includes an in memory cache, so this call will only send a message to the server if the cached token is expired.
|
|
result = await authContext.AcquireTokenAsync(sqlDBResourceId, certCred);
|
|
}
|
|
catch (AdalException ex)
|
|
{
|
|
if (ex.ErrorCode == "temporarily_unavailable")
|
|
{
|
|
retry = true;
|
|
retryCount++;
|
|
Thread.Sleep(3000);
|
|
}
|
|
|
|
Console.WriteLine(
|
|
String.Format("An error occurred while acquiring a token\nTime: {0}\nError: {1}\nRetry: {2}\n",
|
|
DateTime.Now.ToString(),
|
|
ex.ToString(),
|
|
retry.ToString()));
|
|
}
|
|
|
|
} while ((retry == true) && (retryCount < 3));
|
|
|
|
if (result == null)
|
|
{
|
|
Console.WriteLine("Canceling attempt to contact To Do list service.\n");
|
|
return;
|
|
}
|
|
|
|
token = result.AccessToken;
|
|
Console.WriteLine("The access token obtained is:");
|
|
Console.WriteLine("--------------------------------------------------");
|
|
Console.WriteLine(result.AccessToken);
|
|
Console.WriteLine("--------------------------------------------------");
|
|
}
|
|
}
|
|
}
|