Skip to content

Instantly share code, notes, and snippets.

@nzpcmad
Created April 27, 2016 21:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nzpcmad/544c13f9d589e8a4847f7bc0a6c49e7a to your computer and use it in GitHub Desktop.
Save nzpcmad/544c13f9d589e8a4847f7bc0a6c49e7a to your computer and use it in GitHub Desktop.
Daemon and Web API on Server 2016 TP4 ADFS 4.0
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<!--ADFS 4.0-->
<add key="ida:ClientId" value="bee24b9a-13ac-45fc-988c-8cce06160c07" />
<add key="ida:AppKey" value="wp...nE" />
<add key="todo:TodoListResourceId" value="https://localhost:44326/NativeTodoListService" />
<add key="todo:TodoListBaseAddress" value="https://localhost:44326" />
</appSettings>
<system.net>
<!--To bypass proxy if applicable - ADFS 4.0-->
<defaultProxy useDefaultCredentials="true" />
</system.net>
</configuration>
//----------------------------------------------------------------------------------------------
// Copyright 2014 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//----------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// The following using statements were added for this sample.
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.Configuration;
namespace TodoListDaemon
{
class Program
{
//
// The Client ID is used by the application to uniquely identify itself to Azure AD.
// The App Key is a credential used by the application to authenticate to Azure AD.
// ADFS 4.0
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 appKey = ConfigurationManager.AppSettings["ida:AppKey"];
//
// 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 todoListResourceId = ConfigurationManager.AppSettings["todo:TodoListResourceId"];
private static string todoListBaseAddress = ConfigurationManager.AppSettings["todo:TodoListBaseAddress"];
private static HttpClient httpClient = new HttpClient();
private static AuthenticationContext authContext = null;
private static ClientCredential clientCredential = null;
static void Main(string[] args)
{
//
// Call the To Do service 10 times with short delay between calls.
//
// ADFS 4.0
//authContext = new AuthenticationContext(authority);
authContext = new AuthenticationContext("https://my-adfs/adfs/", false);
clientCredential = new ClientCredential(clientId, appKey);
for (int i = 0; i < 10; i++)
{
Thread.Sleep(3000);
PostTodo().Wait();
Thread.Sleep(3000);
GetTodo().Wait();
}
}
static async Task PostTodo()
{
//
// 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;
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 = authContext.AcquireToken(todoListResourceId, clientCredential);
}
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;
}
//
// Post an item to the To Do list service.
//
// Add the access token to the authorization header of the request.
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Forms encode To Do item and POST to the todo list web api.
string timeNow = DateTime.Now.ToString();
Console.WriteLine("Posting to To Do list at {0}", timeNow);
string todoText = "Task at time: " + timeNow;
HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("Title", todoText) });
HttpResponseMessage response = await httpClient.PostAsync(todoListBaseAddress + "/api/todolist", content);
if (response.IsSuccessStatusCode == true)
{
Console.WriteLine("Successfully posted new To Do item: {0}\n", todoText);
}
else
{
Console.WriteLine("Failed to post a new To Do item\nError: {0}\n", response.ReasonPhrase);
}
}
static async Task GetTodo()
{
//
// 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;
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 = authContext.AcquireToken(todoListResourceId, clientCredential);
}
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;
}
//
// Read items from the To Do list service.
//
// Add the access token to the authorization header of the request.
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Call the To Do list service.
Console.WriteLine("Retrieving To Do list at {0}", DateTime.Now.ToString());
HttpResponseMessage response = await httpClient.GetAsync(todoListBaseAddress + "/api/todolist");
if (response.IsSuccessStatusCode)
{
// Read the response and output it to the console.
string s = await response.Content.ReadAsStringAsync();
JavaScriptSerializer serializer = new JavaScriptSerializer();
List<TodoItem> toDoArray = serializer.Deserialize<List<TodoItem>>(s);
int count = 0;
foreach (TodoItem item in toDoArray)
{
Console.WriteLine(item.Title);
count++;
}
Console.WriteLine("Total item count: {0}\n", count);
}
else
{
Console.WriteLine("Failed to retrieve To Do list\nError: {0}\n", response.ReasonPhrase);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.ActiveDirectory;
using Owin;
namespace TodoListService
{
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
/*app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"]
});*/
// Added ADFS 4.0 code
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
Audience = "https://localhost:44326/NativeTodoListService",
MetadataEndpoint = "https://my-adfs/FederationMetadata/2007-06/FederationMetadata.xml"
});
}
}
}
...
<configuration>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<!--ADFS 4.0-->
<!--<add key="ida:Tenant" value="[Enter tenant name, e.g. contoso.onmicrosoft.com]" />
<add key="ida:Audience" value="[Enter App ID URI of TodoListService, e.g. https://contoso.onmicrosoft.com/TodoListService]" />-->
</appSettings>
...
{Rest is the same}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment