I am trying to change AzureADOptis at run time. I tried the following, but after this, clicking on the sign in link takes old values for redirecting it to microsoft login page. Expectation is to take updated options.
var options = new AzureADOptions
{
Instance = "https://login.microsoftonline.com/",
Domain = "....",
TenantId = "....",
ClientId = "....",
CallbackPath = "/signin-oidc"
};
_optionsCache.TryRemove(AzureADDefaults.AuthenticationScheme);
_optionsCache.TryAdd(AzureADDefaults.AuthenticationScheme, options);
You can use OpenIdConnectOptions since AzureADOptions will also map to OpenIdConnectOptions in library . And you need to inject OpenIdConnectPostConfigureOptions into DI system and call _postConfigureOptions.PostConfigure before _optionsCache.TryAdd :
ConfigureServices.cs:
services.AddSingleton<OpenIdConnectPostConfigureOptions>();
In your Controller:
private readonly IAuthenticationSchemeProvider _schemeProvider;
private readonly IOptionsMonitorCache<OpenIdConnectOptions> _optionsCache;
private readonly OpenIdConnectPostConfigureOptions _postConfigureOptions;
public HomeController(IAuthenticationSchemeProvider schemeProvider, IOptionsMonitorCache<OpenIdConnectOptions> optionsCache, OpenIdConnectPostConfigureOptions postConfigureOptions)
{
_schemeProvider = schemeProvider;
_optionsCache = optionsCache;
_postConfigureOptions = postConfigureOptions;
}
In your action :
var OIDCoptions = new OpenIdConnectOptions
{
Authority = "https://login.microsoftonline.com/YourTenantID/",
ClientId = "YourClientID",
CallbackPath = "/signin-oidc"
};
_postConfigureOptions.PostConfigure(AzureADDefaults.OpenIdScheme, OIDCoptions);
_optionsCache.TryRemove(AzureADDefaults.OpenIdScheme);
_optionsCache.TryAdd(AzureADDefaults.OpenIdScheme, OIDCoptions);
Related
I want to write a test that checks if my routingslip works as expected. I narrowed it down to this simplified Version.
namespace MasstransitTest
{
public class Tests
{
private readonly InMemoryTestHarness _harness;
public Tests()
{
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Debug));
services.AddMassTransitInMemoryTestHarness(cfg =>
{
cfg.AddExecuteActivity<ActivityOne, MyMessage>()
.Endpoint(c => c.Name = "queue1");
cfg.AddExecuteActivity<ActivityTwo, MyMessage>()
.Endpoint(c => c.Name = "queue2");
});
var serviceProvider = services.BuildServiceProvider(true);
_harness = serviceProvider.GetRequiredService<InMemoryTestHarness>();
_harness.Start();
}
[Test]
public async Task Test1()
{
var routingSlipBuilder = new RoutingSlipBuilder(Guid.NewGuid());
routingSlipBuilder.AddActivity("Activity1", new Uri("loopback://localhost/queue1"), new { MyMessage = new MyMessage()});
routingSlipBuilder.AddActivity("Activity2", new Uri("loopback://localhost/queue2"), new { MyMessage = new MyMessage()});
routingSlipBuilder.AddSubscription(new Uri("loopback://localhost/protocol-event-monitor"),RoutingSlipEvents.All, RoutingSlipEventContents.All);
var routingSlip = routingSlipBuilder.Build();
await _harness.Bus.Execute(routingSlip);
Assert.That(await _harness.Sent.Any<RoutingSlipCompleted>());
}
}
}
This Test failes, but it works if I replace one of the activities by an activity with another argument type. For example
cfg.AddExecuteActivity<ActivityTwo, MyOtherMessage>().Endpoint(c => c.Name = "queue2");
The failing test prints this log:
info: MassTransit[0] Configured endpoint queue2, Execute Activity: MasstransitTest.ActivityOne
info: MassTransit[0] Configured endpoint queue2, Execute Activity: MasstransitTest.ActivityTwo
dbug: MassTransit[0] Starting bus: loopback://localhost/
I think the Problem is that only one endpoint gets configured, but I don't know why. Is this a bug in the Testingframework?
When using .Endpoint to override the execute or compensate endpoint for an activity, the arguments or log type must be unique.
To change the endpoint name for activities that have a common argument or log type, use an ActivityDefinition or an ExecuteActivityDefinition
public class ActivityOnExecuteActivityDefinition :
ExecuteActivityDefinition<ActivityOne, One>
{
public ActivityOnExecuteActivityDefinition()
{
EndpointName = "queue1";
}
}
I'm having an issue where the token validation fails after some time (exactly when varies I think but usually counted in days). Restarting the app resolves the issue, so I think it's something wrong with how I initialize things.
I'm using Firebase and below is the bootstrapping code that runs at app startup.
I read in a comment on this old post https://stackoverflow.com/a/29779351/611441 that Google rotates certs, so now I'm thinking that might be the issue? I'm only fetching the certs once for the lifetime of the application. If that's the case, how would I be able to refresh these every now and then since this only runs at startup?
public void ConfigureAuthentication(IAppBuilder app)
{
var issuerSigningKeys = GetIssuerSigningKeys();
var firebaseAdminProjectId = ConfigurationManager.AppSettings.Get("FirebaseAdminProjectId");
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions()
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { firebaseAdminProjectId },
Provider = new OAuthBearerAuthenticationProvider
{
OnValidateIdentity = context =>
{
context.OwinContext.Set<bool>("OnValidateIdentity", true);
return Task.FromResult(0);
}
},
TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKeys = issuerSigningKeys,
ValidAudience = firebaseAdminProjectId,
ValidIssuer = ConfigurationManager.AppSettings.Get("FirebaseAdminValidIssuer"),
IssuerSigningKeyResolver = (arbitrarily, declaring, these, parameters) => issuerSigningKeys
}
});
}
private static List<X509SecurityKey> GetIssuerSigningKeys()
{
HttpClient client = new HttpClient();
var task = client.GetStringAsync("https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com"));
task.Wait();
string jsonResult = task.Result;
//Extract X509SecurityKeys from JSON result
List<X509SecurityKey> x509IssuerSigningKeys = JObject.Parse(jsonResult)
.Children()
.Cast<JProperty>()
.Select(i => BuildSecurityKey(i.Value.ToString())).ToList();
return x509IssuerSigningKeys;
}
private static X509SecurityKey BuildSecurityKey(string certificate)
{
//Removing "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" lines
var lines = certificate.Split('\n');
var selectedLines = lines.Skip(1).Take(lines.Length - 3);
var key = string.Join(Environment.NewLine, selectedLines);
return new X509SecurityKey(new X509Certificate2(Convert.FromBase64String(key)));
}
I think I've finally figured this out.
First of all, the signing keys seems to be rotated every 5 days because they have a validity property set with a date. This makes sense with the pattern I see...
However, I think the issue is in my code. The TokenValidationParameters' property IssuerSigningKeyResolver expects a delegate. But I'm getting the keys and assigning them to a variable which in turn is assigned to the property. So the "resolver" always resolves the initial keys returned. They'll never refresh. The fix is to simply assign the GetIssuerSigningKeys() method to the property instead:
IssuerSigningKeyResolver = (arbitrarily, declaring, these, parameters) => GetIssuerSigningKeys()
I am working on a project where I have a requirement to create workitem on Visual Studio Online instance. I am using personal access token. This will set CreatedBy as my name (Expected behavior). I am considering to use Oauth2; However, I am not sure if there's the way to do this Server-to-Server (Non-Interactive)? Any suggestions thoughts?
var personalAccessToken = "PAT Value fro Config";
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "", personalAccessToken))));
return client;
PAT's are created in Security context of the user. I need to find a way to use Oauth without having to involved UI. So I'm looking for Server-to-Server Auth.
object[] patchDocument = new object[5];
patchDocument[0] = new { op = "add", path = "/fields/System.Title", value = bugTitle };
patchDocument[1] = new { op = "add", path = "/fields/Microsoft.VSTS.TCM.ReproSteps", value = bugReproSteps };
patchDocument[2] = new { op = "add", path = "/fields/Microsoft.VSTS.Common.Priority", value = "1" };
patchDocument[3] = new { op = "add", path = "/fields/Microsoft.VSTS.Common.Severity", value = "2 - High" };
patchDocument[4] = new { op = "add", path = "/fields/System.IterationPath", value = deserializeIteration };
//System.IterationPath
string postUrl = $"{_vsoInstanceUrl}/DefaultCollection/ProjectName/_apis/wit/workitems/$Bug?api-version=1.0";
await ExecutePatch(patchDocument.ToArray(), postUrl, "application/json-patch+json");
No there is no Server-to-Server OAuth support. If you use the .NET Client Object Model you can leverage Impersonation support.
If your account has "Act on behalf of others" permissions you can also achieve a "User X via YourAccount".
I am working on Unit testing the MVC3 site using NUnit, MvcContrib.TestHelper package but I am facing the exception "Object reference not set to an instance of an object" when my test method accesses the controller having TryUpdateModel. I dont know what to do to pass the test. please help me in this.
I am also giving a code for that :
Action from Controller which test method calls, is given below :
public JsonResult AddPatient()
{
bool returnStatus;
string returnErrorMessage;
List<string> returnMessage;
PatientBLL patientBLL = new PatientBLL();
Models.PatientViewModel patientViewModel = new Models.PatientViewModel();
TryUpdateModel(patientViewModel);
Patient patient = patientBLL.AddPatient(
patientViewModel,
out returnMessage,
out returnStatus,
out returnErrorMessage);
patientViewModel.UpdateViewModel(patient, typeof(Patient).GetProperties());
patientViewModel.ReturnMessage = returnMessage;
patientViewModel.ReturnStatus = returnStatus;
return Json(patientViewModel);
}
and the test method which calls the above action is given below :
[Test]
public void Test_AddPatient()
{
TestControllerBuilder builder = new TestControllerBuilder();
string uniquePatientKey = GenerateUniqueID();
builder.Form["MedicalID"] = uniquePatientKey;
builder.Form["SocialSecurityNumber"] = uniquePatientKey;
builder.Form["FirstName"] = "Khushi";
builder.Form["LastName"] = "Maahi";
builder.Form["AddressLine1"] = "ABCD";
builder.Form["AddressLine2"] = "Technologies";
builder.Form["City"] = "OOna";
builder.Form["State"] = "UP";
builder.Form["ZipCode"] = "98456-7329";
builder.Form["PhoneNumber"] = "(425)882-8080";
builder.Form["DateOfBirth"] = "10/28/1987";
builder.Form["PatientDateOfBirth"] = "10/28/1987";
builder.Form["EffectiveDate"] = "01/01/1995";
builder.Form["PatientEffectiveDate"] = "01/01/1995";
PatientController patientController = builder.CreateController<PatientController>();
JsonResult jsonResult = (JsonResult)patientController.AddPatient();
dynamic jsonData = jsonResult.Data;
string jsonMessage=Convert.ToString(jsonData.ReturnMessage);
Assert.AreEqual(jsonData.ReturnStatus, true );
Assert.Greater(jsonData.PatientID, 0);
}
Please give me the solution for my probelm.
You have a null somewhere in patientViewModel. Can you post that type here? This could be a problem with mixing models and view models.
I would like to create User Properties using EWS so that they appear in the field chooser in Outlook. I know it's possible using VBA, the object model exposes an Item.UserProperties collection. However, using EWS I can only access Item.ExtendedProperty.
The issue with ExtendedProperty is that is doesn't appear in the selectable user properties list.
The underlying issue is that our server-side application tries to work nicely together with the Dynamics CRM Outlook Client. The CRM Outlook client uses UserProperty for storing custom properties and our application can only work with EWS and we cannot find a way to create user properties.
Some example code:
User Properties (VBA Outlook):
Dim WithEvents m_objApp As Outlook.AppointmentItem
Private Sub Application_ItemLoad(ByVal Item As Object)
If Item.Class = olAppointment Then
Set m_objApp = Item
End If
End Sub
Private Sub m_objApp_Open(Cancel As Boolean)
Dim oProp1 As UserProperty
Dim oProp2 As UserProperty
If m_objApp.UserProperties.Count = 0 Then
Set oProp1 = m_objApp.UserProperties.Add("crmid", olText)
oProp1.Value = ""
Set oProp2 = m_objApp.UserProperties.Add("crmLinkState", olText)
oProp2.Value = "0"
m_objApp.Save
End If
End Sub
Extended Properties (Exchange EWS):
CalendarItemType item = new CalendarItemType();
item.MeetingTimeZone = new TimeZoneType() { TimeZoneName = _userTimeZone };
item.StartSpecified = true;
item.Start = GetDateFromXml(node.Value);
item.EndSpecified = true;
item.End = GetDateFromXml(node.Value);
List<ExtendedPropertyType> properties = new List<ExtendedPropertyType>();
properties.Add(CreateExtendedProperty("crmid", pending.CrmId.Value.ToString(), MapiPropertyTypeType.String));
properties.Add(CreateExtendedProperty("crmLinkState", "2", MapiPropertyTypeType.Double));
item.ExtendedProperty = properties.ToArray();
CreateRequest createRequest = new CreateItemType()
{
Items = new NonEmptyArrayOfAllItemsType
{
Items = new ItemType[] { item }
},
SavedItemFolderId = new TargetFolderIdType()
{
Item = new DistinguishedFolderIdType()
{
Id = folder,
Mailbox = new EmailAddressType() { EmailAddress = _user.MailBox }
}
},
SendMeetingInvitations = CalendarItemCreateOrDeleteOperationType.SendToNone,
SendMeetingInvitationsSpecified = true
};
CreateItemResponseType response = exchange.CreateItem(createRequest);
private ExtendedPropertyType CreateExtendedProperty(string name, string value, MapiPropertyTypeType type)
{
return new ExtendedPropertyType()
{
ExtendedFieldURI = new PathToExtendedFieldType()
{
PropertyName = name,
DistinguishedPropertySetId = DistinguishedPropertySetType.PublicStrings,
DistinguishedPropertySetIdSpecified = true,
PropertyType = type
},
Item = value
};
}
A similar question has been asked on a Microsoft forum almost a year ago, but no answer yet. http://social.technet.microsoft.com/Forums/en-NZ/exchangesvrdevelopment/thread/c4d6bbb9-ba6a-4aa4-9e39-98a52b733a8c
I was hoping SO would be more successful :)
Thanks,
Jeffry
I thought the two methods were equivalent as long as you used publicstrings (which it looks like you do). How about using MFCMAPI to see the difference in what's generated?