Skip to content

Instantly share code, notes, and snippets.

@buchizo
Created April 29, 2019 19:10
Show Gist options
  • Save buchizo/8d3a53f6e8676ab87cf853934ab35acf to your computer and use it in GitHub Desktop.
Save buchizo/8d3a53f6e8676ab87cf853934ab35acf to your computer and use it in GitHub Desktop.
call Azure ARM REST API with FileCache
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography; //add System.Security.Cryptography.ProtectedData nuget package
using System.Threading.Tasks;
using System.Net.Http;
namespace ConsoleApp11
{
class Program
{
static void Main(string[] args)
{
Task.Run(() => GetToken()).Wait();
}
private const string ARMClientID = "1950a258-227b-4e31-a9cf-717495945fc2"; // <- this is Azure PowerShell client id
static async Task GetToken()
{
var authContextURL = "https://login.windows.net/common/";
var filecache = new FileCache();
var cachetoken = filecache.ReadItems().FirstOrDefault();
var bearertoken = "";
if (cachetoken != null && cachetoken.ExpiresOn > DateTimeOffset.UtcNow)
{
bearertoken = "Bearer " + cachetoken.AccessToken;
}
else
{
var authenticationContext = new AuthenticationContext(authContextURL, filecache);
var deviceresult = await authenticationContext.AcquireDeviceCodeAsync("https://management.azure.com/", ARMClientID);
Console.WriteLine(deviceresult.VerificationUrl);
Console.WriteLine("device code: {0}", deviceresult.UserCode);
bearertoken = (await authenticationContext.AcquireTokenByDeviceCodeAsync(deviceresult)).CreateAuthorizationHeader();
}
// call to Azure ARM REST API using user token
var req = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://management.azure.com/providers/Microsoft.Features/operations?api-version=2015-12-01")
};
req.Headers.Add("Authorization", bearertoken);
var client = new HttpClient();
var res = await client.SendAsync(req);
Console.WriteLine("-----------------------");
Console.WriteLine(res.StatusCode);
var body = await res.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
}
public class FileCache : TokenCache
{
public string CacheFilePath;
private static readonly object FileLock = new object();
// Initializes the cache against a local file.
// If the file is already present, it loads its content in the ADAL cache
public FileCache(string filePath = @".\TokenCache.dat")
{
CacheFilePath = filePath;
this.AfterAccess = AfterAccessNotification;
this.BeforeAccess = BeforeAccessNotification;
lock (FileLock)
{
this.Deserialize(File.Exists(CacheFilePath) ? ProtectedData.Unprotect(File.ReadAllBytes(CacheFilePath), null, DataProtectionScope.CurrentUser) : null);
}
}
// Empties the persistent store.
public override void Clear()
{
base.Clear();
File.Delete(CacheFilePath);
}
// Triggered right before ADAL needs to access the cache.
// Reload the cache from the persistent store in case it changed since the last access.
void BeforeAccessNotification(TokenCacheNotificationArgs args)
{
lock (FileLock)
{
this.Deserialize(File.Exists(CacheFilePath) ? ProtectedData.Unprotect(File.ReadAllBytes(CacheFilePath), null, DataProtectionScope.CurrentUser) : null);
}
}
// Triggered right after ADAL accessed the cache.
void AfterAccessNotification(TokenCacheNotificationArgs args)
{
// if the access operation resulted in a cache update
if (this.HasStateChanged)
{
lock (FileLock)
{
// reflect changes in the persistent store
File.WriteAllBytes(CacheFilePath, ProtectedData.Protect(this.Serialize(), null, DataProtectionScope.CurrentUser));
// once the write operation took place, restore the HasStateChanged bit to false
this.HasStateChanged = false;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment