Files
sql-server-samples/samples/features/security/azure-active-directory-auth/token/TokenFactory.cs
T
2016-07-28 15:06:14 -07:00

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("--------------------------------------------------");
}
}
}